minerender 2.1.0-beta.5 → 2.1.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser/esm/Materials.mjs +3 -2
- package/dist/browser/esm/Materials.mjs.map +1 -1
- package/dist/browser/esm/assets/Fonts.mjs +31 -4
- package/dist/browser/esm/assets/Fonts.mjs.map +1 -1
- package/dist/browser/esm/assets/_fonts/Unihex.mjs +166 -0
- package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -0
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs +12 -1
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
- package/dist/browser/esm/assets/source/parser/AssetParsers.mjs +1 -0
- package/dist/browser/esm/assets/source/parser/AssetParsers.mjs.map +1 -1
- package/dist/browser/esm/cache/Caching.mjs +2 -0
- package/dist/browser/esm/cache/Caching.mjs.map +1 -1
- package/dist/browser/esm/entity/scene/EntityAnimationPlayer.mjs +62 -11
- package/dist/browser/esm/entity/scene/EntityAnimationPlayer.mjs.map +1 -1
- package/dist/browser/esm/entity/scene/EntityObject.mjs +53 -20
- package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
- package/dist/browser/esm/env/browser/section.worker.mjs +5 -3
- package/dist/browser/esm/env/browser/section.worker.mjs.map +1 -1
- package/dist/browser/esm/gui/GuiText.mjs +4 -3
- package/dist/browser/esm/gui/GuiText.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +52 -10
- package/dist/browser/esm/model/scene/ModelObject.mjs +4 -0
- package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
- package/dist/browser/esm/util/model.mjs +7 -7
- package/dist/browser/esm/util/model.mjs.map +1 -1
- package/dist/browser/esm/world/SectionGeometry.mjs +5 -3
- package/dist/browser/esm/world/SectionGeometry.mjs.map +1 -1
- package/dist/browser/esm/world/SectionMesh.mjs +4 -0
- package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
- package/dist/browser/esm/world/SectionModels.mjs +2 -2
- package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
- package/dist/browser/index.d.ts +52 -10
- package/dist/browser/index.js +382 -73
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +425 -73
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +52 -10
- package/dist/node/index.d.ts +52 -10
- package/dist/node/index.js +387 -73
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +386 -73
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.js
CHANGED
|
@@ -310,6 +310,9 @@ var init_Caching = __esm({
|
|
|
310
310
|
static {
|
|
311
311
|
this.blockEntityIndexCache = _Caching.createAssetCache();
|
|
312
312
|
}
|
|
313
|
+
static {
|
|
314
|
+
this.unihexCache = _Caching.createAssetCache();
|
|
315
|
+
}
|
|
313
316
|
static {
|
|
314
317
|
this.fontCache = _Caching.createAssetCache();
|
|
315
318
|
}
|
|
@@ -352,6 +355,7 @@ var init_Caching = __esm({
|
|
|
352
355
|
this.entityAnimationCache,
|
|
353
356
|
this.blockEntityIndexCache,
|
|
354
357
|
this.fontCache,
|
|
358
|
+
this.unihexCache,
|
|
355
359
|
this.bannerPatternCache,
|
|
356
360
|
this.mineRenderDataCache,
|
|
357
361
|
this.usernameUuidCache,
|
|
@@ -1113,6 +1117,7 @@ var init_Materials = __esm({
|
|
|
1113
1117
|
static createShadedCanvasMaterial(canvas, transparent = false, shade = false, boundUvs = false) {
|
|
1114
1118
|
const vertShader = `
|
|
1115
1119
|
uniform bool SHADE;
|
|
1120
|
+
attribute float shade;
|
|
1116
1121
|
|
|
1117
1122
|
// Keep MSAA edge pixels from sampling outside the face's atlas region.
|
|
1118
1123
|
#if __VERSION__ >= 300
|
|
@@ -1135,7 +1140,7 @@ var init_Materials = __esm({
|
|
|
1135
1140
|
void main()
|
|
1136
1141
|
{
|
|
1137
1142
|
|
|
1138
|
-
if (SHADE) {
|
|
1143
|
+
if (SHADE && shade > 0.5) {
|
|
1139
1144
|
|
|
1140
1145
|
#ifdef USE_INSTANCING
|
|
1141
1146
|
vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );
|
|
@@ -1244,7 +1249,7 @@ var init_Materials = __esm({
|
|
|
1244
1249
|
side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
|
|
1245
1250
|
alphaTest: 0.5
|
|
1246
1251
|
});
|
|
1247
|
-
Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
|
|
1252
|
+
Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });
|
|
1248
1253
|
return material;
|
|
1249
1254
|
} catch (e) {
|
|
1250
1255
|
console.warn(e);
|
|
@@ -1409,6 +1414,7 @@ var init_AssetParsers = __esm({
|
|
|
1409
1414
|
AssetParser2["IMAGE"] = "image";
|
|
1410
1415
|
AssetParser2["LIST"] = "list";
|
|
1411
1416
|
AssetParser2["JSON"] = "json";
|
|
1417
|
+
AssetParser2["BINARY"] = "binary";
|
|
1412
1418
|
return AssetParser2;
|
|
1413
1419
|
})(AssetParser || {});
|
|
1414
1420
|
}
|
|
@@ -2691,13 +2697,13 @@ function applyElementRotation(rotation, geometry) {
|
|
|
2691
2697
|
break;
|
|
2692
2698
|
}
|
|
2693
2699
|
if (rotation.rescale) {
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2700
|
+
const angle = toRadians(rotation.angle);
|
|
2701
|
+
const s = 1 / Math.max(Math.abs(Math.cos(angle)), Math.abs(Math.sin(angle)));
|
|
2702
|
+
geometry.scale(
|
|
2703
|
+
rotation.axis === "x" /* X */ ? 1 : s,
|
|
2704
|
+
rotation.axis === "y" /* Y */ ? 1 : s,
|
|
2705
|
+
rotation.axis === "z" /* Z */ ? 1 : s
|
|
2706
|
+
);
|
|
2701
2707
|
}
|
|
2702
2708
|
geometry.translate(origin.x, origin.y, origin.z);
|
|
2703
2709
|
}
|
|
@@ -2881,7 +2887,7 @@ var init_parser = __esm({
|
|
|
2881
2887
|
});
|
|
2882
2888
|
|
|
2883
2889
|
// src/assets/source/HostedAssetSource.ts
|
|
2884
|
-
var p3, DEFAULT_OPTIONS, HostedAssetSource;
|
|
2890
|
+
var BINARY_TIMEOUT, p3, DEFAULT_OPTIONS, HostedAssetSource;
|
|
2885
2891
|
var init_HostedAssetSource = __esm({
|
|
2886
2892
|
"src/assets/source/HostedAssetSource.ts"() {
|
|
2887
2893
|
init_AssetSource();
|
|
@@ -2894,6 +2900,7 @@ var init_HostedAssetSource = __esm({
|
|
|
2894
2900
|
init_AssetLoader();
|
|
2895
2901
|
init_parser();
|
|
2896
2902
|
init_merge();
|
|
2903
|
+
BINARY_TIMEOUT = 6e4;
|
|
2897
2904
|
p3 = prefix("HostedAssetSource");
|
|
2898
2905
|
DEFAULT_OPTIONS = {
|
|
2899
2906
|
retryDefaults: true
|
|
@@ -2964,6 +2971,17 @@ var init_HostedAssetSource = __esm({
|
|
|
2964
2971
|
}
|
|
2965
2972
|
};
|
|
2966
2973
|
}
|
|
2974
|
+
static {
|
|
2975
|
+
this.BINARY = {
|
|
2976
|
+
config(request) {
|
|
2977
|
+
request.timeout = BINARY_TIMEOUT;
|
|
2978
|
+
request.responseType = "arraybuffer";
|
|
2979
|
+
},
|
|
2980
|
+
parse(response) {
|
|
2981
|
+
return { data: new Uint8Array(response.data) };
|
|
2982
|
+
}
|
|
2983
|
+
};
|
|
2984
|
+
}
|
|
2967
2985
|
static {
|
|
2968
2986
|
this.PARSER_MAP = /* @__PURE__ */ new Map([
|
|
2969
2987
|
["model" /* MODEL */, _HostedAssetSource.MODEL],
|
|
@@ -2972,7 +2990,8 @@ var init_HostedAssetSource = __esm({
|
|
|
2972
2990
|
["nbt" /* NBT */, _HostedAssetSource.NBT],
|
|
2973
2991
|
["image" /* IMAGE */, _HostedAssetSource.IMAGE],
|
|
2974
2992
|
["list" /* LIST */, _HostedAssetSource.LIST],
|
|
2975
|
-
["json" /* JSON */, _HostedAssetSource.JSON]
|
|
2993
|
+
["json" /* JSON */, _HostedAssetSource.JSON],
|
|
2994
|
+
["binary" /* BINARY */, _HostedAssetSource.BINARY]
|
|
2976
2995
|
]);
|
|
2977
2996
|
}
|
|
2978
2997
|
/** Retries missing assets with the `minecraft` namespace and default root. Other failures reject. */
|
|
@@ -4858,6 +4877,178 @@ var init_Entities = __esm({
|
|
|
4858
4877
|
}
|
|
4859
4878
|
});
|
|
4860
4879
|
|
|
4880
|
+
// src/assets/_fonts/Unihex.ts
|
|
4881
|
+
var Unihex_exports = {};
|
|
4882
|
+
__export(Unihex_exports, {
|
|
4883
|
+
loadUnihex: () => loadUnihex
|
|
4884
|
+
});
|
|
4885
|
+
function readHex(text2, filename, glyphs) {
|
|
4886
|
+
const lines = text2.split("\n");
|
|
4887
|
+
if (lines[lines.length - 1] === "") lines.pop();
|
|
4888
|
+
lines.forEach((line, index) => {
|
|
4889
|
+
const match = /^([0-9A-F]{4,6}):([0-9A-F]+)$/.exec(line);
|
|
4890
|
+
if (!match || ![32, 64, 96, 128].includes(match[2].length)) {
|
|
4891
|
+
throw new Error(`Invalid Unihex record in ${filename} at line ${index + 1}`);
|
|
4892
|
+
}
|
|
4893
|
+
const codepoint = parseInt(match[1], 16);
|
|
4894
|
+
if (codepoint > 1114111) throw new Error(`Invalid Unihex codepoint in ${filename} at line ${index + 1}`);
|
|
4895
|
+
const bitWidth = match[2].length / 4;
|
|
4896
|
+
const rowLength = bitWidth / 4;
|
|
4897
|
+
const rows = new Uint32Array(GLYPH_HEIGHT);
|
|
4898
|
+
let mask = 0;
|
|
4899
|
+
for (let y = 0; y < GLYPH_HEIGHT; y++) {
|
|
4900
|
+
rows[y] = parseInt(match[2].slice(y * rowLength, (y + 1) * rowLength), 16);
|
|
4901
|
+
mask |= rows[y];
|
|
4902
|
+
}
|
|
4903
|
+
let left = 0, right = bitWidth;
|
|
4904
|
+
if (mask) {
|
|
4905
|
+
while (!(mask >>> bitWidth - left - 1 & 1)) left++;
|
|
4906
|
+
right = bitWidth - 1;
|
|
4907
|
+
while (!(mask >>> bitWidth - right - 1 & 1)) right--;
|
|
4908
|
+
}
|
|
4909
|
+
glyphs.set(codepoint, { rows, bitWidth, left, right });
|
|
4910
|
+
});
|
|
4911
|
+
}
|
|
4912
|
+
async function parseUnihex(key) {
|
|
4913
|
+
try {
|
|
4914
|
+
const asset2 = await AssetLoader.get(key, "binary" /* BINARY */);
|
|
4915
|
+
if (!asset2) throw new Error(`Could not load Unihex archive ${key.toNamespacedString()}`);
|
|
4916
|
+
const records = /* @__PURE__ */ new Map();
|
|
4917
|
+
const reader = new import_zip2.ZipReader(new import_zip2.Uint8ArrayReader(asset2.data), { useWebWorkers: false, useCompressionStream: false });
|
|
4918
|
+
try {
|
|
4919
|
+
for (const entry of await reader.getEntries()) {
|
|
4920
|
+
if (!entry.directory && entry.filename.endsWith(".hex")) {
|
|
4921
|
+
readHex(await entry.getData(new import_zip2.TextWriter(), { checkSignature: true }), entry.filename, records);
|
|
4922
|
+
}
|
|
4923
|
+
}
|
|
4924
|
+
} finally {
|
|
4925
|
+
await reader.close();
|
|
4926
|
+
}
|
|
4927
|
+
const indices = new Int32Array(1114112).fill(-1);
|
|
4928
|
+
const rows = new Uint32Array(records.size * GLYPH_HEIGHT), metrics = new Uint8Array(records.size * 3);
|
|
4929
|
+
let index = 0;
|
|
4930
|
+
for (const [codepoint, record] of records) {
|
|
4931
|
+
indices[codepoint] = index;
|
|
4932
|
+
rows.set(record.rows, index * GLYPH_HEIGHT);
|
|
4933
|
+
metrics.set([record.bitWidth, record.left, record.right], index * 3);
|
|
4934
|
+
index++;
|
|
4935
|
+
}
|
|
4936
|
+
return { indices, rows, metrics };
|
|
4937
|
+
} catch (error) {
|
|
4938
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
|
|
4939
|
+
return void 0;
|
|
4940
|
+
}
|
|
4941
|
+
}
|
|
4942
|
+
async function loadUnihex(provider, fontKey, characters) {
|
|
4943
|
+
const origin = new AssetKey(DEFAULT_NAMESPACE, "", void 0, void 0, "assets", "", fontKey.root);
|
|
4944
|
+
const key = AssetKey.parse("font", provider.hex_file, origin);
|
|
4945
|
+
key.assetType = void 0;
|
|
4946
|
+
const glyphs = /* @__PURE__ */ new Map();
|
|
4947
|
+
let overrides;
|
|
4948
|
+
try {
|
|
4949
|
+
overrides = (provider.size_overrides ?? []).map((override) => {
|
|
4950
|
+
const from = override.from.codePointAt(0), to = override.to.codePointAt(0);
|
|
4951
|
+
if ([...override.from].length !== 1 || [...override.to].length !== 1 || from >= to || !Number.isInteger(override.left) || !Number.isInteger(override.right) || override.right < override.left) {
|
|
4952
|
+
throw new Error(`Invalid Unihex size override in font ${fontKey.toNamespacedString()}`);
|
|
4953
|
+
}
|
|
4954
|
+
return { ...override, from, to };
|
|
4955
|
+
});
|
|
4956
|
+
} catch (error) {
|
|
4957
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
|
|
4958
|
+
return glyphs;
|
|
4959
|
+
}
|
|
4960
|
+
const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));
|
|
4961
|
+
if (!file) return glyphs;
|
|
4962
|
+
let atlas = atlases.get(provider);
|
|
4963
|
+
if (!atlas) {
|
|
4964
|
+
atlas = new UnihexAtlas();
|
|
4965
|
+
atlases.set(provider, atlas);
|
|
4966
|
+
}
|
|
4967
|
+
for (const character of characters) {
|
|
4968
|
+
const codepoint = character.codePointAt(0), index = file.indices[codepoint];
|
|
4969
|
+
if (index < 0) continue;
|
|
4970
|
+
const record = {
|
|
4971
|
+
rows: file.rows.subarray(index * GLYPH_HEIGHT, (index + 1) * GLYPH_HEIGHT),
|
|
4972
|
+
bitWidth: file.metrics[index * 3],
|
|
4973
|
+
left: file.metrics[index * 3 + 1],
|
|
4974
|
+
right: file.metrics[index * 3 + 2]
|
|
4975
|
+
};
|
|
4976
|
+
const override = overrides.find((range) => codepoint >= range.from && codepoint <= range.to);
|
|
4977
|
+
if (override) {
|
|
4978
|
+
record.left = override.left;
|
|
4979
|
+
record.right = override.right;
|
|
4980
|
+
}
|
|
4981
|
+
const width = record.right - record.left + 1;
|
|
4982
|
+
let rendered;
|
|
4983
|
+
const render = () => rendered ??= atlas.draw(record);
|
|
4984
|
+
glyphs.set(character, {
|
|
4985
|
+
get image() {
|
|
4986
|
+
return render().image;
|
|
4987
|
+
},
|
|
4988
|
+
get x() {
|
|
4989
|
+
return render().x;
|
|
4990
|
+
},
|
|
4991
|
+
get y() {
|
|
4992
|
+
return render().y;
|
|
4993
|
+
},
|
|
4994
|
+
width,
|
|
4995
|
+
height: GLYPH_HEIGHT,
|
|
4996
|
+
scale: 0.5,
|
|
4997
|
+
ascent: 7,
|
|
4998
|
+
advance: Math.floor(width / 2) + 1,
|
|
4999
|
+
boldOffset: 0.5,
|
|
5000
|
+
shadowOffset: 0.5
|
|
5001
|
+
});
|
|
5002
|
+
}
|
|
5003
|
+
return glyphs;
|
|
5004
|
+
}
|
|
5005
|
+
var import_zip2, ATLAS_SIZE, GLYPH_HEIGHT, UnihexAtlas, atlases;
|
|
5006
|
+
var init_Unihex = __esm({
|
|
5007
|
+
"src/assets/_fonts/Unihex.ts"() {
|
|
5008
|
+
import_zip2 = require("@zip.js/zip.js");
|
|
5009
|
+
init_AssetKey();
|
|
5010
|
+
init_AssetLoader();
|
|
5011
|
+
init_Assets();
|
|
5012
|
+
init_Caching();
|
|
5013
|
+
init_AssetParsers();
|
|
5014
|
+
init_CanvasCompat();
|
|
5015
|
+
ATLAS_SIZE = 512;
|
|
5016
|
+
GLYPH_HEIGHT = 16;
|
|
5017
|
+
UnihexAtlas = class {
|
|
5018
|
+
constructor() {
|
|
5019
|
+
this.x = 0;
|
|
5020
|
+
this.y = 0;
|
|
5021
|
+
}
|
|
5022
|
+
draw(glyph) {
|
|
5023
|
+
const width = glyph.right - glyph.left + 1;
|
|
5024
|
+
if (this.image && this.x + width > this.image.width) {
|
|
5025
|
+
this.x = 0;
|
|
5026
|
+
this.y += GLYPH_HEIGHT;
|
|
5027
|
+
}
|
|
5028
|
+
if (!this.image || this.y + GLYPH_HEIGHT > this.image.height || width > this.image.width) {
|
|
5029
|
+
this.image = createCanvas2(Math.max(ATLAS_SIZE, width), ATLAS_SIZE);
|
|
5030
|
+
this.x = 0;
|
|
5031
|
+
this.y = 0;
|
|
5032
|
+
}
|
|
5033
|
+
const context = this.image.getContext("2d");
|
|
5034
|
+
const pixels = context.createImageData(width, GLYPH_HEIGHT);
|
|
5035
|
+
for (let y = 0; y < GLYPH_HEIGHT; y++) {
|
|
5036
|
+
for (let x = 0; x < width; x++) {
|
|
5037
|
+
const column = glyph.left + x;
|
|
5038
|
+
if (column < 0 || column >= glyph.bitWidth || !(glyph.rows[y] >>> glyph.bitWidth - column - 1 & 1)) continue;
|
|
5039
|
+
pixels.data.fill(255, (y * width + x) * 4, (y * width + x + 1) * 4);
|
|
5040
|
+
}
|
|
5041
|
+
}
|
|
5042
|
+
const result = { image: this.image, x: this.x, y: this.y };
|
|
5043
|
+
context.putImageData(pixels, this.x, this.y);
|
|
5044
|
+
this.x += width;
|
|
5045
|
+
return result;
|
|
5046
|
+
}
|
|
5047
|
+
};
|
|
5048
|
+
atlases = /* @__PURE__ */ new WeakMap();
|
|
5049
|
+
}
|
|
5050
|
+
});
|
|
5051
|
+
|
|
4861
5052
|
// src/assets/Fonts.ts
|
|
4862
5053
|
var Fonts;
|
|
4863
5054
|
var init_Fonts = __esm({
|
|
@@ -4868,7 +5059,7 @@ var init_Fonts = __esm({
|
|
|
4868
5059
|
init_ModelTextures();
|
|
4869
5060
|
init_Caching();
|
|
4870
5061
|
Fonts = class {
|
|
4871
|
-
/** Combines font definitions in source-priority order.
|
|
5062
|
+
/** Combines font definitions in source-priority order. TrueType providers are skipped. */
|
|
4872
5063
|
static async get(key = "minecraft:default") {
|
|
4873
5064
|
const fontKey = typeof key === "string" ? AssetKey.parse("font", key) : key;
|
|
4874
5065
|
return await Caching.fontCache.get(fontKey.serialize(), () => this.load(fontKey, []));
|
|
@@ -4884,6 +5075,7 @@ var init_Fonts = __esm({
|
|
|
4884
5075
|
const stack = await AssetLoader.getAll(key, "json" /* JSON */);
|
|
4885
5076
|
if (stack.length === 0) throw new Error(`Could not load font ${key.toNamespacedString()}`);
|
|
4886
5077
|
const glyphs = /* @__PURE__ */ new Map();
|
|
5078
|
+
const providers = [];
|
|
4887
5079
|
for (const asset2 of stack) {
|
|
4888
5080
|
for (const provider of asset2.providers) {
|
|
4889
5081
|
if (provider.filter?.uniform || provider.filter?.jp) continue;
|
|
@@ -4902,17 +5094,43 @@ var init_Fonts = __esm({
|
|
|
4902
5094
|
break;
|
|
4903
5095
|
case "reference":
|
|
4904
5096
|
case "minecraft:reference":
|
|
4905
|
-
|
|
5097
|
+
const reference = await this.load(this.relatedKey("font", provider.id, key), [...parents, serialized]);
|
|
5098
|
+
if (reference.resolve) {
|
|
5099
|
+
providers.push(async (characters) => {
|
|
5100
|
+
await reference.resolve(characters);
|
|
5101
|
+
return reference.glyphs;
|
|
5102
|
+
});
|
|
5103
|
+
continue;
|
|
5104
|
+
}
|
|
5105
|
+
provided = reference.glyphs;
|
|
4906
5106
|
break;
|
|
5107
|
+
case "unihex":
|
|
5108
|
+
case "minecraft:unihex":
|
|
5109
|
+
providers.push(async (characters) => (await Promise.resolve().then(() => (init_Unihex(), Unihex_exports))).loadUnihex(provider, key, characters));
|
|
5110
|
+
continue;
|
|
4907
5111
|
default:
|
|
4908
5112
|
continue;
|
|
4909
5113
|
}
|
|
4910
|
-
for (const [character, glyph] of provided) {
|
|
5114
|
+
if (providers.every((provider2) => provider2 instanceof Map)) for (const [character, glyph] of provided) {
|
|
4911
5115
|
if (character !== "\0" && !glyphs.has(character)) glyphs.set(character, glyph);
|
|
4912
5116
|
}
|
|
5117
|
+
providers.push(provided);
|
|
5118
|
+
}
|
|
5119
|
+
}
|
|
5120
|
+
return { glyphs, resolve: providers.every((provider) => provider instanceof Map) ? void 0 : async (characters) => {
|
|
5121
|
+
const remaining = new Set([...characters].filter((character) => character !== "\0" && character !== "\n" && character !== "\r" && !glyphs.has(character)));
|
|
5122
|
+
for (const provider of providers) {
|
|
5123
|
+
if (!remaining.size) break;
|
|
5124
|
+
const provided = provider instanceof Map ? provider : await provider([...remaining].join(""));
|
|
5125
|
+
for (const character of remaining) {
|
|
5126
|
+
const glyph = provided.get(character);
|
|
5127
|
+
if (glyph) {
|
|
5128
|
+
glyphs.set(character, glyph);
|
|
5129
|
+
remaining.delete(character);
|
|
5130
|
+
}
|
|
5131
|
+
}
|
|
4913
5132
|
}
|
|
4914
|
-
}
|
|
4915
|
-
return { glyphs };
|
|
5133
|
+
} };
|
|
4916
5134
|
}
|
|
4917
5135
|
static async bitmap(provider, fontKey) {
|
|
4918
5136
|
const rows = provider.chars.map((row) => [...row]);
|
|
@@ -5005,6 +5223,13 @@ var init_EntityAnimation = __esm({
|
|
|
5005
5223
|
});
|
|
5006
5224
|
|
|
5007
5225
|
// src/entity/scene/EntityAnimationPlayer.ts
|
|
5226
|
+
function validateAnimationWeights(weights, count) {
|
|
5227
|
+
const values = Array.from(weights);
|
|
5228
|
+
if (values.length !== count || values.some((weight) => !Number.isFinite(weight) || weight < 0)) {
|
|
5229
|
+
throw new Error("Animation weights must match the clip count and contain only finite nonnegative numbers");
|
|
5230
|
+
}
|
|
5231
|
+
return values;
|
|
5232
|
+
}
|
|
5008
5233
|
var import_three11, ZERO, EntityAnimationPlayer;
|
|
5009
5234
|
var init_EntityAnimationPlayer = __esm({
|
|
5010
5235
|
"src/entity/scene/EntityAnimationPlayer.ts"() {
|
|
@@ -5014,12 +5239,20 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5014
5239
|
EntityAnimationPlayer = class {
|
|
5015
5240
|
constructor() {
|
|
5016
5241
|
this.parts = [];
|
|
5242
|
+
this._animations = [];
|
|
5243
|
+
this._weights = [];
|
|
5244
|
+
this.loops = [];
|
|
5017
5245
|
this._time = 0;
|
|
5018
|
-
this.loop = false;
|
|
5019
5246
|
this.speed = 1;
|
|
5020
5247
|
}
|
|
5021
5248
|
get animation() {
|
|
5022
|
-
return this.
|
|
5249
|
+
return this._animations[0];
|
|
5250
|
+
}
|
|
5251
|
+
get animations() {
|
|
5252
|
+
return this._animations.slice();
|
|
5253
|
+
}
|
|
5254
|
+
get weights() {
|
|
5255
|
+
return this._weights.slice();
|
|
5023
5256
|
}
|
|
5024
5257
|
get time() {
|
|
5025
5258
|
return this._time;
|
|
@@ -5029,10 +5262,20 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5029
5262
|
* without them, the current pose is used. Stopping restores the pose from before playback.
|
|
5030
5263
|
*/
|
|
5031
5264
|
play(layers, animation, options = {}, poses) {
|
|
5265
|
+
this.playAnimations(layers, [animation], options, poses);
|
|
5266
|
+
}
|
|
5267
|
+
/**
|
|
5268
|
+
* Starts clips on matching parts with a shared clock. Weighted offsets add to the supplied baked poses
|
|
5269
|
+
* or, without poses, to each animated part's pose when playback starts.
|
|
5270
|
+
*/
|
|
5271
|
+
playAnimations(layers, animations, options = {}, poses) {
|
|
5272
|
+
const weights = validateAnimationWeights(options.weights ?? animations.map(() => 1), animations.length);
|
|
5032
5273
|
this.stop();
|
|
5033
|
-
this.
|
|
5274
|
+
this._animations = animations.slice();
|
|
5275
|
+
this._weights = weights;
|
|
5276
|
+
if (!animations.length) return;
|
|
5034
5277
|
this._time = options.time ?? 0;
|
|
5035
|
-
this.
|
|
5278
|
+
this.loops = animations.map((animation) => options.loop ?? animation.loop);
|
|
5036
5279
|
this.speed = options.speed ?? 1;
|
|
5037
5280
|
for (const layer of layers) {
|
|
5038
5281
|
const objects = [];
|
|
@@ -5041,7 +5284,8 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5041
5284
|
if (poses.has(object4)) objects.push(object4);
|
|
5042
5285
|
});
|
|
5043
5286
|
} else {
|
|
5044
|
-
|
|
5287
|
+
const bones = new Set(animations.flatMap((animation) => Object.keys(animation.bones)));
|
|
5288
|
+
for (const bone of bones) {
|
|
5045
5289
|
const object4 = layer.getObjectByName(`group:${bone}`);
|
|
5046
5290
|
if (object4) objects.push(object4);
|
|
5047
5291
|
}
|
|
@@ -5065,7 +5309,7 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5065
5309
|
}
|
|
5066
5310
|
/** Restores the poses from before playback. Returns whether an animation was active. */
|
|
5067
5311
|
stop() {
|
|
5068
|
-
if (!this.
|
|
5312
|
+
if (!this._animations.length) return false;
|
|
5069
5313
|
for (const part of this.parts) {
|
|
5070
5314
|
part.object.position.copy(part.position);
|
|
5071
5315
|
part.object.rotation.copy(part.rotation);
|
|
@@ -5077,12 +5321,14 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5077
5321
|
/** Forgets the animation without touching the parts, for parts that no longer exist. */
|
|
5078
5322
|
clear() {
|
|
5079
5323
|
this.parts = [];
|
|
5080
|
-
this.
|
|
5324
|
+
this._animations = [];
|
|
5325
|
+
this._weights = [];
|
|
5326
|
+
this.loops = [];
|
|
5081
5327
|
this._time = 0;
|
|
5082
5328
|
}
|
|
5083
5329
|
/** Applies the pose at an absolute playback time. Returns `false` when no clip is active. */
|
|
5084
5330
|
setTime(seconds) {
|
|
5085
|
-
if (!this.
|
|
5331
|
+
if (!this._animations.length) return false;
|
|
5086
5332
|
this._time = seconds;
|
|
5087
5333
|
this.apply();
|
|
5088
5334
|
return true;
|
|
@@ -5091,8 +5337,30 @@ var init_EntityAnimationPlayer = __esm({
|
|
|
5091
5337
|
advance(deltaSeconds) {
|
|
5092
5338
|
return this.setTime(this._time + deltaSeconds * this.speed);
|
|
5093
5339
|
}
|
|
5340
|
+
/** Changes weights in clip order and reapplies the current time without restarting playback. */
|
|
5341
|
+
setWeights(weights) {
|
|
5342
|
+
if (!this._animations.length) return false;
|
|
5343
|
+
const validated = validateAnimationWeights(weights, this._animations.length);
|
|
5344
|
+
this._weights = validated;
|
|
5345
|
+
this.apply();
|
|
5346
|
+
return true;
|
|
5347
|
+
}
|
|
5094
5348
|
apply() {
|
|
5095
|
-
const pose =
|
|
5349
|
+
const pose = /* @__PURE__ */ Object.create(null);
|
|
5350
|
+
for (let i = 0; i < this._animations.length; i++) {
|
|
5351
|
+
const weight = this._weights[i];
|
|
5352
|
+
if (weight === 0) continue;
|
|
5353
|
+
const sampled = sampleEntityAnimation(this._animations[i], this._time, this.loops[i]);
|
|
5354
|
+
for (const [bone, channels] of Object.entries(sampled)) {
|
|
5355
|
+
const blended = pose[bone] ??= {};
|
|
5356
|
+
for (const channel of ENTITY_ANIMATION_CHANNELS) {
|
|
5357
|
+
const value = channels[channel];
|
|
5358
|
+
if (!value) continue;
|
|
5359
|
+
const target = blended[channel] ??= [0, 0, 0];
|
|
5360
|
+
for (let axis = 0; axis < 3; axis++) target[axis] += value[axis] * weight;
|
|
5361
|
+
}
|
|
5362
|
+
}
|
|
5363
|
+
}
|
|
5096
5364
|
for (const part of this.parts) {
|
|
5097
5365
|
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone] ?? {};
|
|
5098
5366
|
part.object.position.set(part.basePosition.x + position[0], part.basePosition.y + position[1], part.basePosition.z + position[2]);
|
|
@@ -5716,7 +5984,7 @@ var init_EntityObject = __esm({
|
|
|
5716
5984
|
for (const geometry of this.geometries) geometry.dispose();
|
|
5717
5985
|
this.geometries.clear();
|
|
5718
5986
|
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
5719
|
-
for (const player of this.animationPlayers.splice(0)) player.clear();
|
|
5987
|
+
for (const { player } of this.animationPlayers.splice(0)) player.clear();
|
|
5720
5988
|
this.partPoses.clear();
|
|
5721
5989
|
super.disposeAndRemoveAllChildren();
|
|
5722
5990
|
}
|
|
@@ -5751,15 +6019,31 @@ var init_EntityObject = __esm({
|
|
|
5751
6019
|
//<editor-fold desc="ANIMATION">
|
|
5752
6020
|
/** The first active clip, until playback is stopped or the object is disposed. */
|
|
5753
6021
|
get animation() {
|
|
5754
|
-
return this.animationPlayers[0]?.animation;
|
|
6022
|
+
return this.animationPlayers[0]?.player.animation;
|
|
5755
6023
|
}
|
|
5756
|
-
/** Clips playing together,
|
|
6024
|
+
/** Clips playing together, in the order passed to {@link playAnimations}. */
|
|
5757
6025
|
get activeAnimations() {
|
|
5758
|
-
|
|
6026
|
+
const animations = [];
|
|
6027
|
+
for (const { player, indices } of this.animationPlayers) {
|
|
6028
|
+
player.animations.forEach((animation, i) => {
|
|
6029
|
+
animations[indices[i]] = animation;
|
|
6030
|
+
});
|
|
6031
|
+
}
|
|
6032
|
+
return animations;
|
|
6033
|
+
}
|
|
6034
|
+
/** Weights of the active clips, in the same order as {@link activeAnimations}. */
|
|
6035
|
+
get animationWeights() {
|
|
6036
|
+
const weights = [];
|
|
6037
|
+
for (const { player, indices } of this.animationPlayers) {
|
|
6038
|
+
player.weights.forEach((weight, i) => {
|
|
6039
|
+
weights[indices[i]] = weight;
|
|
6040
|
+
});
|
|
6041
|
+
}
|
|
6042
|
+
return weights;
|
|
5759
6043
|
}
|
|
5760
6044
|
/** Seconds since the animation started, before looping. */
|
|
5761
6045
|
get animationTime() {
|
|
5762
|
-
return this.animationPlayers[0]?.time ?? 0;
|
|
6046
|
+
return this.animationPlayers[0]?.player.time ?? 0;
|
|
5763
6047
|
}
|
|
5764
6048
|
/**
|
|
5765
6049
|
* Plays a clip from {@link Entities.getAnimations}, replacing all active clips.
|
|
@@ -5770,42 +6054,59 @@ var init_EntityObject = __esm({
|
|
|
5770
6054
|
playAnimation(animation, options) {
|
|
5771
6055
|
this.playAnimations([animation], options);
|
|
5772
6056
|
}
|
|
5773
|
-
/**
|
|
6057
|
+
/**
|
|
6058
|
+
* Plays clips with a shared clock, adding their weighted offsets within each geometry layer.
|
|
6059
|
+
* Weights default to 1 and are not normalized. Selected layers without their own clip follow `main`.
|
|
6060
|
+
*/
|
|
5774
6061
|
playAnimations(animations, options) {
|
|
5775
|
-
const
|
|
5776
|
-
const selections =
|
|
6062
|
+
const weights = validateAnimationWeights(options?.weights ?? animations.map(() => 1), animations.length);
|
|
6063
|
+
const selections = /* @__PURE__ */ new Map();
|
|
6064
|
+
animations.forEach((animation, index) => {
|
|
5777
6065
|
const layer = animation.layer ?? "main";
|
|
5778
|
-
if (targets.has(layer)) throw new Error(`Multiple animations target layer "${layer}"`);
|
|
5779
|
-
targets.add(layer);
|
|
5780
6066
|
const names = Object.keys(this.entityLayers).filter((name) => name.split("#")[0] === layer);
|
|
5781
6067
|
if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer "${layer}"`);
|
|
5782
|
-
|
|
6068
|
+
let selection = selections.get(layer);
|
|
6069
|
+
if (!selection) selections.set(layer, selection = { animations: [], names, indices: [] });
|
|
6070
|
+
selection.animations.push(animation);
|
|
6071
|
+
selection.indices.push(index);
|
|
5783
6072
|
});
|
|
5784
|
-
const main = selections.
|
|
5785
|
-
if (main) main.names.push(...Object.keys(this.entityLayers).filter((name) => !
|
|
6073
|
+
const main = selections.get("main");
|
|
6074
|
+
if (main) main.names.push(...Object.keys(this.entityLayers).filter((name) => !selections.has(name.split("#")[0])));
|
|
5786
6075
|
this.createMeshes();
|
|
5787
6076
|
this.stopAnimation();
|
|
5788
|
-
for (const {
|
|
6077
|
+
for (const { animations: clips, names, indices } of selections.values()) {
|
|
5789
6078
|
const player = new EntityAnimationPlayer();
|
|
5790
|
-
player.
|
|
5791
|
-
|
|
6079
|
+
player.playAnimations(
|
|
6080
|
+
names.map((name) => this.getLayerGroup(name)),
|
|
6081
|
+
clips,
|
|
6082
|
+
{ ...options, weights: indices.map((index) => weights[index]) },
|
|
6083
|
+
this.partPoses
|
|
6084
|
+
);
|
|
6085
|
+
this.animationPlayers.push({ player, indices });
|
|
5792
6086
|
}
|
|
5793
6087
|
this.notifyDirty();
|
|
5794
6088
|
}
|
|
6089
|
+
/** Changes weights in active clip order, notifying the scene without restarting the shared clock. Has no effect without an animation. */
|
|
6090
|
+
setAnimationWeights(weights) {
|
|
6091
|
+
if (!this.animationPlayers.length) return;
|
|
6092
|
+
const values = validateAnimationWeights(weights, this.activeAnimations.length);
|
|
6093
|
+
for (const { player, indices } of this.animationPlayers) player.setWeights(indices.map((index) => values[index]));
|
|
6094
|
+
this.notifyDirty();
|
|
6095
|
+
}
|
|
5795
6096
|
/** Stops all clips and restores the poses from before playback. */
|
|
5796
6097
|
stopAnimation() {
|
|
5797
6098
|
const players = this.animationPlayers.splice(0);
|
|
5798
|
-
for (const player of players) player.stop();
|
|
6099
|
+
for (const { player } of players) player.stop();
|
|
5799
6100
|
if (players.length) this.notifyDirty();
|
|
5800
6101
|
}
|
|
5801
6102
|
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
5802
6103
|
setAnimationTime(seconds) {
|
|
5803
|
-
for (const player of this.animationPlayers) player.setTime(seconds);
|
|
6104
|
+
for (const { player } of this.animationPlayers) player.setTime(seconds);
|
|
5804
6105
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
5805
6106
|
}
|
|
5806
6107
|
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
5807
6108
|
advanceAnimation(deltaSeconds) {
|
|
5808
|
-
for (const player of this.animationPlayers) player.advance(deltaSeconds);
|
|
6109
|
+
for (const { player } of this.animationPlayers) player.advance(deltaSeconds);
|
|
5809
6110
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
5810
6111
|
}
|
|
5811
6112
|
//</editor-fold>
|
|
@@ -8038,6 +8339,7 @@ async function layoutGuiText(text2, options = {}) {
|
|
|
8038
8339
|
}
|
|
8039
8340
|
const font = await Fonts.get(options.font);
|
|
8040
8341
|
const runs = typeof text2 === "string" ? [{ text: text2 }] : text2;
|
|
8342
|
+
await font.resolve?.(runs.map((run) => run.text).join(""));
|
|
8041
8343
|
const glyphs = [], lineWidths = [];
|
|
8042
8344
|
let line = [], width = 0;
|
|
8043
8345
|
let trailingNewline = false;
|
|
@@ -8064,7 +8366,7 @@ async function layoutGuiText(text2, options = {}) {
|
|
|
8064
8366
|
continue;
|
|
8065
8367
|
}
|
|
8066
8368
|
const glyph = font.glyphs.get(character);
|
|
8067
|
-
const advance = (glyph?.advance ?? 6) + (style.bold ? 1 : 0);
|
|
8369
|
+
const advance = (glyph?.advance ?? 6) + (style.bold ? glyph?.boldOffset ?? 1 : 0);
|
|
8068
8370
|
line.push({ character, glyph, advance, style, x: 0, y: 0 });
|
|
8069
8371
|
width += advance;
|
|
8070
8372
|
while (width > maxWidth && line.length > 1) {
|
|
@@ -8092,7 +8394,7 @@ function createGuiTextGeometry(layout, shadow = true) {
|
|
|
8092
8394
|
batches.push(batch);
|
|
8093
8395
|
}
|
|
8094
8396
|
const color2 = new import_three20.Color(isShadow ? (style.color & 16579836) >> 2 : style.color);
|
|
8095
|
-
const offset = isShadow ? 1 : 0;
|
|
8397
|
+
const offset = isShadow ? glyph?.shadowOffset ?? 1 : 0;
|
|
8096
8398
|
const top = glyph ? 7 - glyph.ascent : 0;
|
|
8097
8399
|
const height = glyph ? glyph.height * glyph.scale : 8;
|
|
8098
8400
|
const width = glyph ? glyph.width * glyph.scale : 5;
|
|
@@ -8122,7 +8424,7 @@ function createGuiTextGeometry(layout, shadow = true) {
|
|
|
8122
8424
|
for (let i = 0; i < 4; i++) batch.colors.push(color2.r, color2.g, color2.b);
|
|
8123
8425
|
batch.indices.push(base, base + 2, base + 1, base + 2, base + 3, base + 1);
|
|
8124
8426
|
};
|
|
8125
|
-
for (const boldOffset of style.bold ? [0, 1] : [0]) {
|
|
8427
|
+
for (const boldOffset of style.bold ? [0, glyph?.boldOffset ?? 1] : [0]) {
|
|
8126
8428
|
if (glyph) quad(0, top, width, top + height, boldOffset);
|
|
8127
8429
|
else {
|
|
8128
8430
|
quad(0, 0, 5, 1, boldOffset);
|
|
@@ -9896,6 +10198,10 @@ var init_ModelObject = __esm({
|
|
|
9896
10198
|
this.atlas.model.elements?.forEach((el) => {
|
|
9897
10199
|
const elGeo = this._getBoxGeometryFromElement(el).clone();
|
|
9898
10200
|
this.geometries.add(elGeo);
|
|
10201
|
+
elGeo.setAttribute("shade", new import_three27.BufferAttribute(
|
|
10202
|
+
new Float32Array(elGeo.getAttribute("position").count).fill(!this.originalModel.itemId && el.shade === false ? 0 : 1),
|
|
10203
|
+
1
|
|
10204
|
+
));
|
|
9899
10205
|
if (this.options.cullMask) {
|
|
9900
10206
|
const indices = Array.from(elGeo.getIndex().array);
|
|
9901
10207
|
elGeo.setIndex(indices.filter((_, index) => {
|
|
@@ -11399,6 +11705,7 @@ __export(index_node_exports, {
|
|
|
11399
11705
|
toRadians: () => toRadians,
|
|
11400
11706
|
toTrianglesDrawMode: () => toTrianglesDrawMode,
|
|
11401
11707
|
trimCanvas: () => trimCanvas,
|
|
11708
|
+
validateAnimationWeights: () => validateAnimationWeights,
|
|
11402
11709
|
yieldToEventLoop: () => yieldToEventLoop
|
|
11403
11710
|
});
|
|
11404
11711
|
module.exports = __toCommonJS(index_node_exports);
|
|
@@ -17687,9 +17994,9 @@ function cached(map, key, load) {
|
|
|
17687
17994
|
function compactQuads(geometry, keep) {
|
|
17688
17995
|
const quads = keep.flatMap((kept, index) => kept ? [index] : []);
|
|
17689
17996
|
const compact = new import_three41.BufferGeometry();
|
|
17690
|
-
for (const [name, size] of Object.entries({ position: 3, normal: 3, uv: 2, uvBounds: 4, color: 3 })) {
|
|
17997
|
+
for (const [name, size] of Object.entries({ position: 3, normal: 3, uv: 2, uvBounds: 4, color: 3, shade: 1 })) {
|
|
17691
17998
|
const source2 = geometry.getAttribute(name);
|
|
17692
|
-
const defaults = name === "uvBounds" ? [0, 0, 1, 1] : name === "color" ? [1, 1, 1] : void 0;
|
|
17999
|
+
const defaults = name === "uvBounds" ? [0, 0, 1, 1] : name === "color" ? [1, 1, 1] : name === "shade" ? [1] : void 0;
|
|
17693
18000
|
const values = new Float32Array(quads.length * 4 * size);
|
|
17694
18001
|
for (let q = 0; q < quads.length; q++) {
|
|
17695
18002
|
for (let vertex = 0; vertex < 4; vertex++) {
|
|
@@ -18937,7 +19244,7 @@ var LIGHT_SAMPLE_OFFSETS = [0, 1, -1, 324, -324, 18, -18];
|
|
|
18937
19244
|
|
|
18938
19245
|
// src/world/SectionGeometry.ts
|
|
18939
19246
|
function buildSectionGeometry(input) {
|
|
18940
|
-
const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;
|
|
19247
|
+
const { count, indices, templates, cullMasks, templateData, atlases: atlases2, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;
|
|
18941
19248
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
18942
19249
|
if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError("Section entry count exceeds its arrays");
|
|
18943
19250
|
if (biomeTints && biomeTints.length !== count * 3) throw new RangeError("Section biome tints must contain RGB for each placement");
|
|
@@ -18955,7 +19262,7 @@ function buildSectionGeometry(input) {
|
|
|
18955
19262
|
const cornerBrightness2 = ambientOcclusion ? new Float32Array(4) : void 0;
|
|
18956
19263
|
for (const template of templateData) {
|
|
18957
19264
|
const { quads } = template;
|
|
18958
|
-
if (template.positions.length !== quads * 12 || template.normals.length !== quads * 12 || template.uvs.length !== quads * 8 || template.uvBounds.length !== quads * 16 || template.colors.length !== quads * 12 || template.indices.length !== quads * 6 || template.cullFaces.length !== quads || template.biomeTint && template.biomeTint.length !== quads) {
|
|
19265
|
+
if (template.positions.length !== quads * 12 || template.normals.length !== quads * 12 || template.uvs.length !== quads * 8 || template.uvBounds.length !== quads * 16 || template.colors.length !== quads * 12 || template.indices.length !== quads * 6 || template.cullFaces.length !== quads || template.shade && template.shade.length !== quads * 4 || template.biomeTint && template.biomeTint.length !== quads) {
|
|
18959
19266
|
throw new RangeError("Section template arrays do not match its quad count");
|
|
18960
19267
|
}
|
|
18961
19268
|
}
|
|
@@ -18972,8 +19279,8 @@ function buildSectionGeometry(input) {
|
|
|
18972
19279
|
const locations = /* @__PURE__ */ new Map();
|
|
18973
19280
|
for (const [layer, layerAtlases] of [...visibleAtlases].sort(([a], [b]) => a - b)) {
|
|
18974
19281
|
const firstPage = pages.length;
|
|
18975
|
-
for (const atlas of [...layerAtlases].sort((a, b) => Number(
|
|
18976
|
-
const { width, height, animated } =
|
|
19282
|
+
for (const atlas of [...layerAtlases].sort((a, b) => Number(atlases2[a].animated) - Number(atlases2[b].animated) || (atlases2[a].animated ? a - b : atlases2[b].height - atlases2[a].height))) {
|
|
19283
|
+
const { width, height, animated } = atlases2[atlas];
|
|
18977
19284
|
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
18978
19285
|
let selected = -1;
|
|
18979
19286
|
for (let i = firstPage; !animated && i < pages.length; i++) {
|
|
@@ -19016,7 +19323,7 @@ function buildSectionGeometry(input) {
|
|
|
19016
19323
|
});
|
|
19017
19324
|
if (!quads.sprites.length) continue;
|
|
19018
19325
|
if (!fluidPages.has(fluid)) {
|
|
19019
|
-
const { width, height } =
|
|
19326
|
+
const { width, height } = atlases2[data.atlas];
|
|
19020
19327
|
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
19021
19328
|
fluidPages.set(fluid, {
|
|
19022
19329
|
layer: 2,
|
|
@@ -19034,7 +19341,7 @@ function buildSectionGeometry(input) {
|
|
|
19034
19341
|
const tint = fluid === "water" && fluids.waterTints ? fluids.waterTints.subarray(tintIndex, tintIndex + 3) : data.tint;
|
|
19035
19342
|
fluidPages.get(fluid).fluids.push({ quads, x, y, z, data, tint });
|
|
19036
19343
|
}
|
|
19037
|
-
pages.push(...[...fluidPages.values()].sort((a, b) => Number(
|
|
19344
|
+
pages.push(...[...fluidPages.values()].sort((a, b) => Number(atlases2[a.placements[0].atlas].animated) - Number(atlases2[b.placements[0].atlas].animated) || a.placements[0].atlas - b.placements[0].atlas));
|
|
19038
19345
|
}
|
|
19039
19346
|
return pages.map((page) => {
|
|
19040
19347
|
let faces = page.fluids.reduce((sum, fluid) => sum + fluid.quads.sprites.length, 0);
|
|
@@ -19046,12 +19353,13 @@ function buildSectionGeometry(input) {
|
|
|
19046
19353
|
}
|
|
19047
19354
|
const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);
|
|
19048
19355
|
const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);
|
|
19356
|
+
const shade = new Float32Array(faces * 4).fill(1);
|
|
19049
19357
|
const outputIndices = new Uint32Array(faces * 6);
|
|
19050
19358
|
const blockIndices = new Uint16Array(faces);
|
|
19051
19359
|
let vertex = 0, indexOffset = 0;
|
|
19052
19360
|
for (const entry of page.entries) {
|
|
19053
19361
|
const template = templateData[templates[entry]];
|
|
19054
|
-
const atlas =
|
|
19362
|
+
const atlas = atlases2[template.atlas];
|
|
19055
19363
|
const placement = locations.get(template.atlas);
|
|
19056
19364
|
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
19057
19365
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
@@ -19075,6 +19383,7 @@ function buildSectionGeometry(input) {
|
|
|
19075
19383
|
normals[vertex * 3] = template.normals[source * 3];
|
|
19076
19384
|
normals[vertex * 3 + 1] = template.normals[source * 3 + 1];
|
|
19077
19385
|
normals[vertex * 3 + 2] = template.normals[source * 3 + 2];
|
|
19386
|
+
shade[vertex] = template.shade?.[source] ?? 1;
|
|
19078
19387
|
uvs[vertex * 2] = mapU(template.uvs[source * 2]);
|
|
19079
19388
|
uvs[vertex * 2 + 1] = mapV(template.uvs[source * 2 + 1]);
|
|
19080
19389
|
uvBounds[vertex * 4] = mapU(template.uvBounds[source * 4]);
|
|
@@ -19090,7 +19399,7 @@ function buildSectionGeometry(input) {
|
|
|
19090
19399
|
}
|
|
19091
19400
|
}
|
|
19092
19401
|
for (const { quads, x, y, z, data, tint } of page.fluids) {
|
|
19093
|
-
const atlas =
|
|
19402
|
+
const atlas = atlases2[data.atlas];
|
|
19094
19403
|
const placement = page.placements[0];
|
|
19095
19404
|
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
19096
19405
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
@@ -19127,11 +19436,11 @@ function buildSectionGeometry(input) {
|
|
|
19127
19436
|
indexOffset += 6;
|
|
19128
19437
|
}
|
|
19129
19438
|
}
|
|
19130
|
-
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices, blockIndices };
|
|
19439
|
+
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, shade, indices: outputIndices, blockIndices };
|
|
19131
19440
|
});
|
|
19132
19441
|
}
|
|
19133
19442
|
function sectionGeometryTransferables(pages) {
|
|
19134
|
-
return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer, page.blockIndices.buffer]);
|
|
19443
|
+
return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.shade.buffer, page.indices.buffer, page.blockIndices.buffer]);
|
|
19135
19444
|
}
|
|
19136
19445
|
|
|
19137
19446
|
// src/world/SectionWorker.ts
|
|
@@ -19192,7 +19501,7 @@ var templateCache = /* @__PURE__ */ new WeakMap();
|
|
|
19192
19501
|
var WATER_TINT = new import_three46.Color(4159204).toArray();
|
|
19193
19502
|
function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
19194
19503
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
19195
|
-
const
|
|
19504
|
+
const atlases2 = [];
|
|
19196
19505
|
const atlasIds = /* @__PURE__ */ new Map();
|
|
19197
19506
|
const templateIds = /* @__PURE__ */ new Map();
|
|
19198
19507
|
const input = {
|
|
@@ -19215,9 +19524,9 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19215
19524
|
if (id === void 0) {
|
|
19216
19525
|
let atlas = atlasIds.get(template.atlas);
|
|
19217
19526
|
if (atlas === void 0) {
|
|
19218
|
-
atlas =
|
|
19527
|
+
atlas = atlases2.length;
|
|
19219
19528
|
atlasIds.set(template.atlas, atlas);
|
|
19220
|
-
|
|
19529
|
+
atlases2.push(template.atlas);
|
|
19221
19530
|
input.atlases.push({ width: template.atlas.image.width, height: template.atlas.image.height, animated: template.atlas.hasAnimation });
|
|
19222
19531
|
}
|
|
19223
19532
|
let data = templateCache.get(template);
|
|
@@ -19235,6 +19544,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19235
19544
|
uvs: new Float32Array(quads * 8),
|
|
19236
19545
|
uvBounds: new Float32Array(quads * 16),
|
|
19237
19546
|
colors: new Float32Array(quads * 12),
|
|
19547
|
+
shade: new Float32Array(quads * 4),
|
|
19238
19548
|
indices: new Uint16Array(quads * 6),
|
|
19239
19549
|
cullFaces: new Uint8Array(template.cullFaces),
|
|
19240
19550
|
biomeTint: template.biomeTint ? new Uint8Array(template.biomeTint) : void 0,
|
|
@@ -19246,6 +19556,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19246
19556
|
const uv = template.geometry.getAttribute("uv");
|
|
19247
19557
|
const bounds = template.geometry.getAttribute("uvBounds");
|
|
19248
19558
|
const color2 = template.geometry.getAttribute("color");
|
|
19559
|
+
const shade = template.geometry.getAttribute("shade");
|
|
19249
19560
|
for (let vertex = 0; vertex < quads * 4; vertex++) {
|
|
19250
19561
|
data.positions.set([position.getX(vertex), position.getY(vertex), position.getZ(vertex)], vertex * 3);
|
|
19251
19562
|
data.normals.set([normal.getX(vertex), normal.getY(vertex), normal.getZ(vertex)], vertex * 3);
|
|
@@ -19257,6 +19568,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19257
19568
|
bounds?.getW(vertex) ?? 1
|
|
19258
19569
|
], vertex * 4);
|
|
19259
19570
|
data.colors.set([color2?.getX(vertex) ?? 1, color2?.getY(vertex) ?? 1, color2?.getZ(vertex) ?? 1], vertex * 3);
|
|
19571
|
+
data.shade[vertex] = shade?.getX(vertex) ?? 1;
|
|
19260
19572
|
}
|
|
19261
19573
|
for (let i2 = 0; i2 < data.indices.length; i2++) data.indices[i2] = indices.getX(i2) - 4 * Math.floor(i2 / 6);
|
|
19262
19574
|
templateCache.set(template, data);
|
|
@@ -19276,9 +19588,9 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19276
19588
|
if (!atlas) continue;
|
|
19277
19589
|
let id = atlasIds.get(atlas);
|
|
19278
19590
|
if (id === void 0) {
|
|
19279
|
-
id =
|
|
19591
|
+
id = atlases2.length;
|
|
19280
19592
|
atlasIds.set(atlas, id);
|
|
19281
|
-
|
|
19593
|
+
atlases2.push(atlas);
|
|
19282
19594
|
input.atlases.push({ width: atlas.image.width, height: atlas.image.height, animated: atlas.hasAnimation });
|
|
19283
19595
|
}
|
|
19284
19596
|
input.fluids[kind] = {
|
|
@@ -19289,7 +19601,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19289
19601
|
};
|
|
19290
19602
|
}
|
|
19291
19603
|
}
|
|
19292
|
-
return { input, atlases };
|
|
19604
|
+
return { input, atlases: atlases2 };
|
|
19293
19605
|
}
|
|
19294
19606
|
var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
19295
19607
|
constructor() {
|
|
@@ -19304,23 +19616,23 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19304
19616
|
}
|
|
19305
19617
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
19306
19618
|
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
19307
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19308
|
-
return this.fromPages(buildSectionGeometry(input),
|
|
19619
|
+
const { input, atlases: atlases2 } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19620
|
+
return this.fromPages(buildSectionGeometry(input), atlases2);
|
|
19309
19621
|
}
|
|
19310
19622
|
/** Builds section-local meshes in a browser worker when available, with synchronous fallback. */
|
|
19311
19623
|
static async buildAsync(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
19312
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19624
|
+
const { input, atlases: atlases2 } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19313
19625
|
const worker = SectionWorker.shared();
|
|
19314
19626
|
const pages = worker ? await worker.build(input).catch(() => buildSectionGeometry(input)) : buildSectionGeometry(input);
|
|
19315
|
-
return this.fromPages(pages,
|
|
19627
|
+
return this.fromPages(pages, atlases2);
|
|
19316
19628
|
}
|
|
19317
|
-
static fromPages(pages,
|
|
19629
|
+
static fromPages(pages, atlases2) {
|
|
19318
19630
|
const section = new _SectionMesh();
|
|
19319
19631
|
for (const page of pages) {
|
|
19320
19632
|
const canvas = createCanvas2(page.width, page.height);
|
|
19321
19633
|
const context = canvas.getContext("2d");
|
|
19322
19634
|
for (const { atlas, x, y } of page.placements) {
|
|
19323
|
-
context.drawImage(
|
|
19635
|
+
context.drawImage(atlases2[atlas].image.canvas, x, y);
|
|
19324
19636
|
}
|
|
19325
19637
|
const geometry = new import_three46.BufferGeometry();
|
|
19326
19638
|
geometry.setAttribute("position", new import_three46.Float32BufferAttribute(page.positions.buffer, 3));
|
|
@@ -19328,10 +19640,11 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19328
19640
|
geometry.setAttribute("uv", new import_three46.Float32BufferAttribute(page.uvs.buffer, 2));
|
|
19329
19641
|
geometry.setAttribute("uvBounds", new import_three46.Float32BufferAttribute(page.uvBounds.buffer, 4));
|
|
19330
19642
|
geometry.setAttribute("color", new import_three46.Float32BufferAttribute(page.colors.buffer, 3));
|
|
19643
|
+
geometry.setAttribute("shade", new import_three46.Float32BufferAttribute(page.shade.buffer, 1));
|
|
19331
19644
|
geometry.setIndex(new import_three46.Uint32BufferAttribute(page.indices.buffer, 1));
|
|
19332
19645
|
geometry.computeBoundingBox();
|
|
19333
19646
|
geometry.computeBoundingSphere();
|
|
19334
|
-
const transparent = page.layer === 2 ?
|
|
19647
|
+
const transparent = page.layer === 2 ? atlases2[page.placements[0].atlas].hasTranslucency : page.layer === 1;
|
|
19335
19648
|
const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
|
|
19336
19649
|
material.side = import_three46.FrontSide;
|
|
19337
19650
|
if (page.layer === 2) {
|
|
@@ -19346,7 +19659,7 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19346
19659
|
section.blockIndices.set(mesh, page.blockIndices);
|
|
19347
19660
|
const unsubscribe = [];
|
|
19348
19661
|
for (const { atlas: id, x, y } of page.placements) {
|
|
19349
|
-
const atlas =
|
|
19662
|
+
const atlas = atlases2[id];
|
|
19350
19663
|
if (!atlas.hasAnimation) continue;
|
|
19351
19664
|
unsubscribe.push(atlas.subscribe(() => {
|
|
19352
19665
|
context.clearRect(x, y, atlas.image.width, atlas.image.height);
|
|
@@ -20690,6 +21003,7 @@ var NodeRenderer = class _NodeRenderer extends Renderer {
|
|
|
20690
21003
|
toRadians,
|
|
20691
21004
|
toTrianglesDrawMode,
|
|
20692
21005
|
trimCanvas,
|
|
21006
|
+
validateAnimationWeights,
|
|
20693
21007
|
yieldToEventLoop
|
|
20694
21008
|
});
|
|
20695
21009
|
//# sourceMappingURL=index.js.map
|