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/bundle.js
CHANGED
|
@@ -35632,6 +35632,7 @@ void main() {
|
|
|
35632
35632
|
this.entityAnimationCache,
|
|
35633
35633
|
this.blockEntityIndexCache,
|
|
35634
35634
|
this.fontCache,
|
|
35635
|
+
this.unihexCache,
|
|
35635
35636
|
this.bannerPatternCache,
|
|
35636
35637
|
this.mineRenderDataCache,
|
|
35637
35638
|
this.usernameUuidCache,
|
|
@@ -35685,6 +35686,7 @@ void main() {
|
|
|
35685
35686
|
_Caching.entityTextureCache = _Caching.createAssetCache();
|
|
35686
35687
|
_Caching.entityAnimationCache = _Caching.createAssetCache();
|
|
35687
35688
|
_Caching.blockEntityIndexCache = _Caching.createAssetCache();
|
|
35689
|
+
_Caching.unihexCache = _Caching.createAssetCache();
|
|
35688
35690
|
_Caching.fontCache = _Caching.createAssetCache();
|
|
35689
35691
|
_Caching.bannerPatternCache = _Caching.createAssetCache();
|
|
35690
35692
|
_Caching.mineRenderDataCache = _Caching.createAssetCache();
|
|
@@ -36796,6 +36798,7 @@ void main() {
|
|
|
36796
36798
|
static createShadedCanvasMaterial(canvas, transparent = false, shade = false, boundUvs = false) {
|
|
36797
36799
|
const vertShader = `
|
|
36798
36800
|
uniform bool SHADE;
|
|
36801
|
+
attribute float shade;
|
|
36799
36802
|
|
|
36800
36803
|
// Keep MSAA edge pixels from sampling outside the face's atlas region.
|
|
36801
36804
|
#if __VERSION__ >= 300
|
|
@@ -36818,7 +36821,7 @@ void main() {
|
|
|
36818
36821
|
void main()
|
|
36819
36822
|
{
|
|
36820
36823
|
|
|
36821
|
-
if (SHADE) {
|
|
36824
|
+
if (SHADE && shade > 0.5) {
|
|
36822
36825
|
|
|
36823
36826
|
#ifdef USE_INSTANCING
|
|
36824
36827
|
vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );
|
|
@@ -36927,7 +36930,7 @@ void main() {
|
|
|
36927
36930
|
side: transparent ? DoubleSide : FrontSide,
|
|
36928
36931
|
alphaTest: 0.5
|
|
36929
36932
|
});
|
|
36930
|
-
Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
|
|
36933
|
+
Object.assign(material.defaultAttributeValues, { shade: [1], uvBounds: [0, 0, 1, 1] });
|
|
36931
36934
|
return material;
|
|
36932
36935
|
} catch (e6) {
|
|
36933
36936
|
console.warn(e6);
|
|
@@ -37098,6 +37101,7 @@ void main() {
|
|
|
37098
37101
|
AssetParser2["IMAGE"] = "image";
|
|
37099
37102
|
AssetParser2["LIST"] = "list";
|
|
37100
37103
|
AssetParser2["JSON"] = "json";
|
|
37104
|
+
AssetParser2["BINARY"] = "binary";
|
|
37101
37105
|
return AssetParser2;
|
|
37102
37106
|
})(AssetParser || {});
|
|
37103
37107
|
}
|
|
@@ -38432,13 +38436,13 @@ ${key}` : key, async () => {
|
|
|
38432
38436
|
break;
|
|
38433
38437
|
}
|
|
38434
38438
|
if (rotation.rescale) {
|
|
38435
|
-
|
|
38436
|
-
|
|
38437
|
-
|
|
38438
|
-
|
|
38439
|
-
|
|
38440
|
-
|
|
38441
|
-
|
|
38439
|
+
const angle = toRadians(rotation.angle);
|
|
38440
|
+
const s4 = 1 / Math.max(Math.abs(Math.cos(angle)), Math.abs(Math.sin(angle)));
|
|
38441
|
+
geometry.scale(
|
|
38442
|
+
rotation.axis === "x" /* X */ ? 1 : s4,
|
|
38443
|
+
rotation.axis === "y" /* Y */ ? 1 : s4,
|
|
38444
|
+
rotation.axis === "z" /* Z */ ? 1 : s4
|
|
38445
|
+
);
|
|
38442
38446
|
}
|
|
38443
38447
|
geometry.translate(origin.x, origin.y, origin.z);
|
|
38444
38448
|
}
|
|
@@ -73063,7 +73067,7 @@ return ${compiler2.callType("value", tagType)}
|
|
|
73063
73067
|
});
|
|
73064
73068
|
|
|
73065
73069
|
// src/assets/source/HostedAssetSource.ts
|
|
73066
|
-
var p7, DEFAULT_OPTIONS2, _HostedAssetSource, HostedAssetSource;
|
|
73070
|
+
var BINARY_TIMEOUT, p7, DEFAULT_OPTIONS2, _HostedAssetSource, HostedAssetSource;
|
|
73067
73071
|
var init_HostedAssetSource = __esm({
|
|
73068
73072
|
"src/assets/source/HostedAssetSource.ts"() {
|
|
73069
73073
|
init_dirname();
|
|
@@ -73079,6 +73083,7 @@ return ${compiler2.callType("value", tagType)}
|
|
|
73079
73083
|
init_AssetLoader();
|
|
73080
73084
|
init_parser();
|
|
73081
73085
|
init_merge();
|
|
73086
|
+
BINARY_TIMEOUT = 6e4;
|
|
73082
73087
|
p7 = prefix("HostedAssetSource");
|
|
73083
73088
|
DEFAULT_OPTIONS2 = {
|
|
73084
73089
|
retryDefaults: true
|
|
@@ -73219,6 +73224,15 @@ return ${compiler2.callType("value", tagType)}
|
|
|
73219
73224
|
return response.data;
|
|
73220
73225
|
}
|
|
73221
73226
|
};
|
|
73227
|
+
_HostedAssetSource.BINARY = {
|
|
73228
|
+
config(request) {
|
|
73229
|
+
request.timeout = BINARY_TIMEOUT;
|
|
73230
|
+
request.responseType = "arraybuffer";
|
|
73231
|
+
},
|
|
73232
|
+
parse(response) {
|
|
73233
|
+
return { data: new Uint8Array(response.data) };
|
|
73234
|
+
}
|
|
73235
|
+
};
|
|
73222
73236
|
_HostedAssetSource.PARSER_MAP = /* @__PURE__ */ new Map([
|
|
73223
73237
|
["model" /* MODEL */, _HostedAssetSource.MODEL],
|
|
73224
73238
|
["blockstate" /* BLOCKSTATE */, _HostedAssetSource.BLOCKSTATE],
|
|
@@ -73226,7 +73240,8 @@ return ${compiler2.callType("value", tagType)}
|
|
|
73226
73240
|
["nbt" /* NBT */, _HostedAssetSource.NBT],
|
|
73227
73241
|
["image" /* IMAGE */, _HostedAssetSource.IMAGE],
|
|
73228
73242
|
["list" /* LIST */, _HostedAssetSource.LIST],
|
|
73229
|
-
["json" /* JSON */, _HostedAssetSource.JSON]
|
|
73243
|
+
["json" /* JSON */, _HostedAssetSource.JSON],
|
|
73244
|
+
["binary" /* BINARY */, _HostedAssetSource.BINARY]
|
|
73230
73245
|
]);
|
|
73231
73246
|
HostedAssetSource = _HostedAssetSource;
|
|
73232
73247
|
}
|
|
@@ -81841,7 +81856,7 @@ return ${compiler2.callType("value", tagType)}
|
|
|
81841
81856
|
function readUint8Array(reader, offset, size, diskNumber) {
|
|
81842
81857
|
return reader.readUint8Array(offset, size, diskNumber);
|
|
81843
81858
|
}
|
|
81844
|
-
var ERR_ITERATOR_COMPLETED_TOO_SOON, HTTP_HEADER_CONTENT_TYPE, DEFAULT_CHUNK_SIZE, PROPERTY_NAME_WRITABLE, Stream, Reader, BlobReader, BlobWriter, SplitDataReader, SplitDataWriter;
|
|
81859
|
+
var ERR_ITERATOR_COMPLETED_TOO_SOON, HTTP_HEADER_CONTENT_TYPE, DEFAULT_CHUNK_SIZE, PROPERTY_NAME_WRITABLE, Stream, Reader, BlobReader, BlobWriter, TextWriter, Uint8ArrayReader, SplitDataReader, SplitDataWriter;
|
|
81845
81860
|
var init_io = __esm({
|
|
81846
81861
|
"../../node_modules/@zip.js/zip.js/lib/core/io.js"() {
|
|
81847
81862
|
init_dirname();
|
|
@@ -81924,6 +81939,46 @@ return ${compiler2.callType("value", tagType)}
|
|
|
81924
81939
|
return this.blob;
|
|
81925
81940
|
}
|
|
81926
81941
|
};
|
|
81942
|
+
TextWriter = class extends BlobWriter {
|
|
81943
|
+
constructor(encoding) {
|
|
81944
|
+
super(encoding);
|
|
81945
|
+
Object.assign(this, {
|
|
81946
|
+
encoding,
|
|
81947
|
+
utf8: !encoding || encoding.toLowerCase() == "utf-8"
|
|
81948
|
+
});
|
|
81949
|
+
}
|
|
81950
|
+
async getData() {
|
|
81951
|
+
const {
|
|
81952
|
+
encoding,
|
|
81953
|
+
utf8
|
|
81954
|
+
} = this;
|
|
81955
|
+
const blob = await super.getData();
|
|
81956
|
+
if (blob.text && utf8) {
|
|
81957
|
+
return blob.text();
|
|
81958
|
+
} else {
|
|
81959
|
+
const reader = new FileReader();
|
|
81960
|
+
return new Promise((resolve, reject) => {
|
|
81961
|
+
Object.assign(reader, {
|
|
81962
|
+
onload: ({ target }) => resolve(target.result),
|
|
81963
|
+
onerror: () => reject(reader.error)
|
|
81964
|
+
});
|
|
81965
|
+
reader.readAsText(blob, encoding);
|
|
81966
|
+
});
|
|
81967
|
+
}
|
|
81968
|
+
}
|
|
81969
|
+
};
|
|
81970
|
+
Uint8ArrayReader = class extends Reader {
|
|
81971
|
+
constructor(array) {
|
|
81972
|
+
super();
|
|
81973
|
+
Object.assign(this, {
|
|
81974
|
+
array,
|
|
81975
|
+
size: array.length
|
|
81976
|
+
});
|
|
81977
|
+
}
|
|
81978
|
+
readUint8Array(index, length) {
|
|
81979
|
+
return this.array.slice(index, index + length);
|
|
81980
|
+
}
|
|
81981
|
+
};
|
|
81927
81982
|
SplitDataReader = class extends Reader {
|
|
81928
81983
|
constructor(readers) {
|
|
81929
81984
|
super();
|
|
@@ -84682,6 +84737,181 @@ ${key}` : key;
|
|
|
84682
84737
|
}
|
|
84683
84738
|
});
|
|
84684
84739
|
|
|
84740
|
+
// src/assets/_fonts/Unihex.ts
|
|
84741
|
+
var Unihex_exports = {};
|
|
84742
|
+
__export(Unihex_exports, {
|
|
84743
|
+
loadUnihex: () => loadUnihex
|
|
84744
|
+
});
|
|
84745
|
+
function readHex(text2, filename, glyphs) {
|
|
84746
|
+
const lines = text2.split("\n");
|
|
84747
|
+
if (lines[lines.length - 1] === "") lines.pop();
|
|
84748
|
+
lines.forEach((line, index) => {
|
|
84749
|
+
const match = /^([0-9A-F]{4,6}):([0-9A-F]+)$/.exec(line);
|
|
84750
|
+
if (!match || ![32, 64, 96, 128].includes(match[2].length)) {
|
|
84751
|
+
throw new Error(`Invalid Unihex record in ${filename} at line ${index + 1}`);
|
|
84752
|
+
}
|
|
84753
|
+
const codepoint = parseInt(match[1], 16);
|
|
84754
|
+
if (codepoint > 1114111) throw new Error(`Invalid Unihex codepoint in ${filename} at line ${index + 1}`);
|
|
84755
|
+
const bitWidth = match[2].length / 4;
|
|
84756
|
+
const rowLength = bitWidth / 4;
|
|
84757
|
+
const rows = new Uint32Array(GLYPH_HEIGHT);
|
|
84758
|
+
let mask = 0;
|
|
84759
|
+
for (let y5 = 0; y5 < GLYPH_HEIGHT; y5++) {
|
|
84760
|
+
rows[y5] = parseInt(match[2].slice(y5 * rowLength, (y5 + 1) * rowLength), 16);
|
|
84761
|
+
mask |= rows[y5];
|
|
84762
|
+
}
|
|
84763
|
+
let left = 0, right = bitWidth;
|
|
84764
|
+
if (mask) {
|
|
84765
|
+
while (!(mask >>> bitWidth - left - 1 & 1)) left++;
|
|
84766
|
+
right = bitWidth - 1;
|
|
84767
|
+
while (!(mask >>> bitWidth - right - 1 & 1)) right--;
|
|
84768
|
+
}
|
|
84769
|
+
glyphs.set(codepoint, { rows, bitWidth, left, right });
|
|
84770
|
+
});
|
|
84771
|
+
}
|
|
84772
|
+
async function parseUnihex(key) {
|
|
84773
|
+
try {
|
|
84774
|
+
const asset2 = await AssetLoader.get(key, "binary" /* BINARY */);
|
|
84775
|
+
if (!asset2) throw new Error(`Could not load Unihex archive ${key.toNamespacedString()}`);
|
|
84776
|
+
const records = /* @__PURE__ */ new Map();
|
|
84777
|
+
const reader = new ZipReader(new Uint8ArrayReader(asset2.data), { useWebWorkers: false, useCompressionStream: false });
|
|
84778
|
+
try {
|
|
84779
|
+
for (const entry of await reader.getEntries()) {
|
|
84780
|
+
if (!entry.directory && entry.filename.endsWith(".hex")) {
|
|
84781
|
+
readHex(await entry.getData(new TextWriter(), { checkSignature: true }), entry.filename, records);
|
|
84782
|
+
}
|
|
84783
|
+
}
|
|
84784
|
+
} finally {
|
|
84785
|
+
await reader.close();
|
|
84786
|
+
}
|
|
84787
|
+
const indices = new Int32Array(1114112).fill(-1);
|
|
84788
|
+
const rows = new Uint32Array(records.size * GLYPH_HEIGHT), metrics = new Uint8Array(records.size * 3);
|
|
84789
|
+
let index = 0;
|
|
84790
|
+
for (const [codepoint, record] of records) {
|
|
84791
|
+
indices[codepoint] = index;
|
|
84792
|
+
rows.set(record.rows, index * GLYPH_HEIGHT);
|
|
84793
|
+
metrics.set([record.bitWidth, record.left, record.right], index * 3);
|
|
84794
|
+
index++;
|
|
84795
|
+
}
|
|
84796
|
+
return { indices, rows, metrics };
|
|
84797
|
+
} catch (error2) {
|
|
84798
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error2);
|
|
84799
|
+
return void 0;
|
|
84800
|
+
}
|
|
84801
|
+
}
|
|
84802
|
+
async function loadUnihex(provider, fontKey, characters) {
|
|
84803
|
+
const origin = new AssetKey(DEFAULT_NAMESPACE, "", void 0, void 0, "assets", "", fontKey.root);
|
|
84804
|
+
const key = AssetKey.parse("font", provider.hex_file, origin);
|
|
84805
|
+
key.assetType = void 0;
|
|
84806
|
+
const glyphs = /* @__PURE__ */ new Map();
|
|
84807
|
+
let overrides;
|
|
84808
|
+
try {
|
|
84809
|
+
overrides = (provider.size_overrides ?? []).map((override) => {
|
|
84810
|
+
const from = override.from.codePointAt(0), to = override.to.codePointAt(0);
|
|
84811
|
+
if ([...override.from].length !== 1 || [...override.to].length !== 1 || from >= to || !Number.isInteger(override.left) || !Number.isInteger(override.right) || override.right < override.left) {
|
|
84812
|
+
throw new Error(`Invalid Unihex size override in font ${fontKey.toNamespacedString()}`);
|
|
84813
|
+
}
|
|
84814
|
+
return { ...override, from, to };
|
|
84815
|
+
});
|
|
84816
|
+
} catch (error2) {
|
|
84817
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error2);
|
|
84818
|
+
return glyphs;
|
|
84819
|
+
}
|
|
84820
|
+
const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));
|
|
84821
|
+
if (!file) return glyphs;
|
|
84822
|
+
let atlas = atlases.get(provider);
|
|
84823
|
+
if (!atlas) {
|
|
84824
|
+
atlas = new UnihexAtlas();
|
|
84825
|
+
atlases.set(provider, atlas);
|
|
84826
|
+
}
|
|
84827
|
+
for (const character of characters) {
|
|
84828
|
+
const codepoint = character.codePointAt(0), index = file.indices[codepoint];
|
|
84829
|
+
if (index < 0) continue;
|
|
84830
|
+
const record = {
|
|
84831
|
+
rows: file.rows.subarray(index * GLYPH_HEIGHT, (index + 1) * GLYPH_HEIGHT),
|
|
84832
|
+
bitWidth: file.metrics[index * 3],
|
|
84833
|
+
left: file.metrics[index * 3 + 1],
|
|
84834
|
+
right: file.metrics[index * 3 + 2]
|
|
84835
|
+
};
|
|
84836
|
+
const override = overrides.find((range) => codepoint >= range.from && codepoint <= range.to);
|
|
84837
|
+
if (override) {
|
|
84838
|
+
record.left = override.left;
|
|
84839
|
+
record.right = override.right;
|
|
84840
|
+
}
|
|
84841
|
+
const width = record.right - record.left + 1;
|
|
84842
|
+
let rendered;
|
|
84843
|
+
const render = () => rendered ?? (rendered = atlas.draw(record));
|
|
84844
|
+
glyphs.set(character, {
|
|
84845
|
+
get image() {
|
|
84846
|
+
return render().image;
|
|
84847
|
+
},
|
|
84848
|
+
get x() {
|
|
84849
|
+
return render().x;
|
|
84850
|
+
},
|
|
84851
|
+
get y() {
|
|
84852
|
+
return render().y;
|
|
84853
|
+
},
|
|
84854
|
+
width,
|
|
84855
|
+
height: GLYPH_HEIGHT,
|
|
84856
|
+
scale: 0.5,
|
|
84857
|
+
ascent: 7,
|
|
84858
|
+
advance: Math.floor(width / 2) + 1,
|
|
84859
|
+
boldOffset: 0.5,
|
|
84860
|
+
shadowOffset: 0.5
|
|
84861
|
+
});
|
|
84862
|
+
}
|
|
84863
|
+
return glyphs;
|
|
84864
|
+
}
|
|
84865
|
+
var ATLAS_SIZE, GLYPH_HEIGHT, UnihexAtlas, atlases;
|
|
84866
|
+
var init_Unihex = __esm({
|
|
84867
|
+
"src/assets/_fonts/Unihex.ts"() {
|
|
84868
|
+
init_dirname();
|
|
84869
|
+
init_buffer2();
|
|
84870
|
+
init_process2();
|
|
84871
|
+
init_zip();
|
|
84872
|
+
init_AssetKey();
|
|
84873
|
+
init_AssetLoader();
|
|
84874
|
+
init_Assets();
|
|
84875
|
+
init_Caching();
|
|
84876
|
+
init_AssetParsers();
|
|
84877
|
+
init_CanvasCompat();
|
|
84878
|
+
ATLAS_SIZE = 512;
|
|
84879
|
+
GLYPH_HEIGHT = 16;
|
|
84880
|
+
UnihexAtlas = class {
|
|
84881
|
+
constructor() {
|
|
84882
|
+
this.x = 0;
|
|
84883
|
+
this.y = 0;
|
|
84884
|
+
}
|
|
84885
|
+
draw(glyph) {
|
|
84886
|
+
const width = glyph.right - glyph.left + 1;
|
|
84887
|
+
if (this.image && this.x + width > this.image.width) {
|
|
84888
|
+
this.x = 0;
|
|
84889
|
+
this.y += GLYPH_HEIGHT;
|
|
84890
|
+
}
|
|
84891
|
+
if (!this.image || this.y + GLYPH_HEIGHT > this.image.height || width > this.image.width) {
|
|
84892
|
+
this.image = createCanvas(Math.max(ATLAS_SIZE, width), ATLAS_SIZE);
|
|
84893
|
+
this.x = 0;
|
|
84894
|
+
this.y = 0;
|
|
84895
|
+
}
|
|
84896
|
+
const context = this.image.getContext("2d");
|
|
84897
|
+
const pixels = context.createImageData(width, GLYPH_HEIGHT);
|
|
84898
|
+
for (let y5 = 0; y5 < GLYPH_HEIGHT; y5++) {
|
|
84899
|
+
for (let x4 = 0; x4 < width; x4++) {
|
|
84900
|
+
const column = glyph.left + x4;
|
|
84901
|
+
if (column < 0 || column >= glyph.bitWidth || !(glyph.rows[y5] >>> glyph.bitWidth - column - 1 & 1)) continue;
|
|
84902
|
+
pixels.data.fill(255, (y5 * width + x4) * 4, (y5 * width + x4 + 1) * 4);
|
|
84903
|
+
}
|
|
84904
|
+
}
|
|
84905
|
+
const result = { image: this.image, x: this.x, y: this.y };
|
|
84906
|
+
context.putImageData(pixels, this.x, this.y);
|
|
84907
|
+
this.x += width;
|
|
84908
|
+
return result;
|
|
84909
|
+
}
|
|
84910
|
+
};
|
|
84911
|
+
atlases = /* @__PURE__ */ new WeakMap();
|
|
84912
|
+
}
|
|
84913
|
+
});
|
|
84914
|
+
|
|
84685
84915
|
// src/assets/Fonts.ts
|
|
84686
84916
|
var Fonts;
|
|
84687
84917
|
var init_Fonts = __esm({
|
|
@@ -84695,7 +84925,7 @@ ${key}` : key;
|
|
|
84695
84925
|
init_ModelTextures();
|
|
84696
84926
|
init_Caching();
|
|
84697
84927
|
Fonts = class {
|
|
84698
|
-
/** Combines font definitions in source-priority order.
|
|
84928
|
+
/** Combines font definitions in source-priority order. TrueType providers are skipped. */
|
|
84699
84929
|
static async get(key = "minecraft:default") {
|
|
84700
84930
|
const fontKey = typeof key === "string" ? AssetKey.parse("font", key) : key;
|
|
84701
84931
|
return await Caching.fontCache.get(fontKey.serialize(), () => this.load(fontKey, []));
|
|
@@ -84711,6 +84941,7 @@ ${key}` : key;
|
|
|
84711
84941
|
const stack = await AssetLoader.getAll(key, "json" /* JSON */);
|
|
84712
84942
|
if (stack.length === 0) throw new Error(`Could not load font ${key.toNamespacedString()}`);
|
|
84713
84943
|
const glyphs = /* @__PURE__ */ new Map();
|
|
84944
|
+
const providers = [];
|
|
84714
84945
|
for (const asset2 of stack) {
|
|
84715
84946
|
for (const provider of asset2.providers) {
|
|
84716
84947
|
if (provider.filter?.uniform || provider.filter?.jp) continue;
|
|
@@ -84729,17 +84960,43 @@ ${key}` : key;
|
|
|
84729
84960
|
break;
|
|
84730
84961
|
case "reference":
|
|
84731
84962
|
case "minecraft:reference":
|
|
84732
|
-
|
|
84963
|
+
const reference = await this.load(this.relatedKey("font", provider.id, key), [...parents, serialized]);
|
|
84964
|
+
if (reference.resolve) {
|
|
84965
|
+
providers.push(async (characters) => {
|
|
84966
|
+
await reference.resolve(characters);
|
|
84967
|
+
return reference.glyphs;
|
|
84968
|
+
});
|
|
84969
|
+
continue;
|
|
84970
|
+
}
|
|
84971
|
+
provided = reference.glyphs;
|
|
84733
84972
|
break;
|
|
84973
|
+
case "unihex":
|
|
84974
|
+
case "minecraft:unihex":
|
|
84975
|
+
providers.push(async (characters) => (await Promise.resolve().then(() => (init_Unihex(), Unihex_exports))).loadUnihex(provider, key, characters));
|
|
84976
|
+
continue;
|
|
84734
84977
|
default:
|
|
84735
84978
|
continue;
|
|
84736
84979
|
}
|
|
84737
|
-
for (const [character, glyph] of provided) {
|
|
84980
|
+
if (providers.every((provider2) => provider2 instanceof Map)) for (const [character, glyph] of provided) {
|
|
84738
84981
|
if (character !== "\0" && !glyphs.has(character)) glyphs.set(character, glyph);
|
|
84739
84982
|
}
|
|
84983
|
+
providers.push(provided);
|
|
84740
84984
|
}
|
|
84741
84985
|
}
|
|
84742
|
-
return { glyphs
|
|
84986
|
+
return { glyphs, resolve: providers.every((provider) => provider instanceof Map) ? void 0 : async (characters) => {
|
|
84987
|
+
const remaining = new Set([...characters].filter((character) => character !== "\0" && character !== "\n" && character !== "\r" && !glyphs.has(character)));
|
|
84988
|
+
for (const provider of providers) {
|
|
84989
|
+
if (!remaining.size) break;
|
|
84990
|
+
const provided = provider instanceof Map ? provider : await provider([...remaining].join(""));
|
|
84991
|
+
for (const character of remaining) {
|
|
84992
|
+
const glyph = provided.get(character);
|
|
84993
|
+
if (glyph) {
|
|
84994
|
+
glyphs.set(character, glyph);
|
|
84995
|
+
remaining.delete(character);
|
|
84996
|
+
}
|
|
84997
|
+
}
|
|
84998
|
+
}
|
|
84999
|
+
} };
|
|
84743
85000
|
}
|
|
84744
85001
|
static async bitmap(provider, fontKey) {
|
|
84745
85002
|
const rows = provider.chars.map((row) => [...row]);
|
|
@@ -84835,6 +85092,13 @@ ${key}` : key;
|
|
|
84835
85092
|
});
|
|
84836
85093
|
|
|
84837
85094
|
// src/entity/scene/EntityAnimationPlayer.ts
|
|
85095
|
+
function validateAnimationWeights(weights, count) {
|
|
85096
|
+
const values = Array.from(weights);
|
|
85097
|
+
if (values.length !== count || values.some((weight) => !Number.isFinite(weight) || weight < 0)) {
|
|
85098
|
+
throw new Error("Animation weights must match the clip count and contain only finite nonnegative numbers");
|
|
85099
|
+
}
|
|
85100
|
+
return values;
|
|
85101
|
+
}
|
|
84838
85102
|
var ZERO, EntityAnimationPlayer;
|
|
84839
85103
|
var init_EntityAnimationPlayer = __esm({
|
|
84840
85104
|
"src/entity/scene/EntityAnimationPlayer.ts"() {
|
|
@@ -84847,12 +85111,20 @@ ${key}` : key;
|
|
|
84847
85111
|
EntityAnimationPlayer = class {
|
|
84848
85112
|
constructor() {
|
|
84849
85113
|
this.parts = [];
|
|
85114
|
+
this._animations = [];
|
|
85115
|
+
this._weights = [];
|
|
85116
|
+
this.loops = [];
|
|
84850
85117
|
this._time = 0;
|
|
84851
|
-
this.loop = false;
|
|
84852
85118
|
this.speed = 1;
|
|
84853
85119
|
}
|
|
84854
85120
|
get animation() {
|
|
84855
|
-
return this.
|
|
85121
|
+
return this._animations[0];
|
|
85122
|
+
}
|
|
85123
|
+
get animations() {
|
|
85124
|
+
return this._animations.slice();
|
|
85125
|
+
}
|
|
85126
|
+
get weights() {
|
|
85127
|
+
return this._weights.slice();
|
|
84856
85128
|
}
|
|
84857
85129
|
get time() {
|
|
84858
85130
|
return this._time;
|
|
@@ -84862,10 +85134,20 @@ ${key}` : key;
|
|
|
84862
85134
|
* without them, the current pose is used. Stopping restores the pose from before playback.
|
|
84863
85135
|
*/
|
|
84864
85136
|
play(layers, animation, options = {}, poses) {
|
|
85137
|
+
this.playAnimations(layers, [animation], options, poses);
|
|
85138
|
+
}
|
|
85139
|
+
/**
|
|
85140
|
+
* Starts clips on matching parts with a shared clock. Weighted offsets add to the supplied baked poses
|
|
85141
|
+
* or, without poses, to each animated part's pose when playback starts.
|
|
85142
|
+
*/
|
|
85143
|
+
playAnimations(layers, animations, options = {}, poses) {
|
|
85144
|
+
const weights = validateAnimationWeights(options.weights ?? animations.map(() => 1), animations.length);
|
|
84865
85145
|
this.stop();
|
|
84866
|
-
this.
|
|
85146
|
+
this._animations = animations.slice();
|
|
85147
|
+
this._weights = weights;
|
|
85148
|
+
if (!animations.length) return;
|
|
84867
85149
|
this._time = options.time ?? 0;
|
|
84868
|
-
this.
|
|
85150
|
+
this.loops = animations.map((animation) => options.loop ?? animation.loop);
|
|
84869
85151
|
this.speed = options.speed ?? 1;
|
|
84870
85152
|
for (const layer of layers) {
|
|
84871
85153
|
const objects = [];
|
|
@@ -84874,7 +85156,8 @@ ${key}` : key;
|
|
|
84874
85156
|
if (poses.has(object4)) objects.push(object4);
|
|
84875
85157
|
});
|
|
84876
85158
|
} else {
|
|
84877
|
-
|
|
85159
|
+
const bones = new Set(animations.flatMap((animation) => Object.keys(animation.bones)));
|
|
85160
|
+
for (const bone of bones) {
|
|
84878
85161
|
const object4 = layer.getObjectByName(`group:${bone}`);
|
|
84879
85162
|
if (object4) objects.push(object4);
|
|
84880
85163
|
}
|
|
@@ -84898,7 +85181,7 @@ ${key}` : key;
|
|
|
84898
85181
|
}
|
|
84899
85182
|
/** Restores the poses from before playback. Returns whether an animation was active. */
|
|
84900
85183
|
stop() {
|
|
84901
|
-
if (!this.
|
|
85184
|
+
if (!this._animations.length) return false;
|
|
84902
85185
|
for (const part of this.parts) {
|
|
84903
85186
|
part.object.position.copy(part.position);
|
|
84904
85187
|
part.object.rotation.copy(part.rotation);
|
|
@@ -84910,12 +85193,14 @@ ${key}` : key;
|
|
|
84910
85193
|
/** Forgets the animation without touching the parts, for parts that no longer exist. */
|
|
84911
85194
|
clear() {
|
|
84912
85195
|
this.parts = [];
|
|
84913
|
-
this.
|
|
85196
|
+
this._animations = [];
|
|
85197
|
+
this._weights = [];
|
|
85198
|
+
this.loops = [];
|
|
84914
85199
|
this._time = 0;
|
|
84915
85200
|
}
|
|
84916
85201
|
/** Applies the pose at an absolute playback time. Returns `false` when no clip is active. */
|
|
84917
85202
|
setTime(seconds) {
|
|
84918
|
-
if (!this.
|
|
85203
|
+
if (!this._animations.length) return false;
|
|
84919
85204
|
this._time = seconds;
|
|
84920
85205
|
this.apply();
|
|
84921
85206
|
return true;
|
|
@@ -84924,8 +85209,30 @@ ${key}` : key;
|
|
|
84924
85209
|
advance(deltaSeconds) {
|
|
84925
85210
|
return this.setTime(this._time + deltaSeconds * this.speed);
|
|
84926
85211
|
}
|
|
85212
|
+
/** Changes weights in clip order and reapplies the current time without restarting playback. */
|
|
85213
|
+
setWeights(weights) {
|
|
85214
|
+
if (!this._animations.length) return false;
|
|
85215
|
+
const validated = validateAnimationWeights(weights, this._animations.length);
|
|
85216
|
+
this._weights = validated;
|
|
85217
|
+
this.apply();
|
|
85218
|
+
return true;
|
|
85219
|
+
}
|
|
84927
85220
|
apply() {
|
|
84928
|
-
const pose =
|
|
85221
|
+
const pose = /* @__PURE__ */ Object.create(null);
|
|
85222
|
+
for (let i4 = 0; i4 < this._animations.length; i4++) {
|
|
85223
|
+
const weight = this._weights[i4];
|
|
85224
|
+
if (weight === 0) continue;
|
|
85225
|
+
const sampled = sampleEntityAnimation(this._animations[i4], this._time, this.loops[i4]);
|
|
85226
|
+
for (const [bone, channels] of Object.entries(sampled)) {
|
|
85227
|
+
const blended = pose[bone] ?? (pose[bone] = {});
|
|
85228
|
+
for (const channel of ENTITY_ANIMATION_CHANNELS) {
|
|
85229
|
+
const value = channels[channel];
|
|
85230
|
+
if (!value) continue;
|
|
85231
|
+
const target = blended[channel] ?? (blended[channel] = [0, 0, 0]);
|
|
85232
|
+
for (let axis = 0; axis < 3; axis++) target[axis] += value[axis] * weight;
|
|
85233
|
+
}
|
|
85234
|
+
}
|
|
85235
|
+
}
|
|
84929
85236
|
for (const part of this.parts) {
|
|
84930
85237
|
const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone] ?? {};
|
|
84931
85238
|
part.object.position.set(part.basePosition.x + position[0], part.basePosition.y + position[1], part.basePosition.z + position[2]);
|
|
@@ -85554,7 +85861,7 @@ ${key}` : key;
|
|
|
85554
85861
|
for (const geometry of this.geometries) geometry.dispose();
|
|
85555
85862
|
this.geometries.clear();
|
|
85556
85863
|
for (const dispose of this.disposeWireframes.splice(0)) dispose();
|
|
85557
|
-
for (const player of this.animationPlayers.splice(0)) player.clear();
|
|
85864
|
+
for (const { player } of this.animationPlayers.splice(0)) player.clear();
|
|
85558
85865
|
this.partPoses.clear();
|
|
85559
85866
|
super.disposeAndRemoveAllChildren();
|
|
85560
85867
|
}
|
|
@@ -85589,15 +85896,31 @@ ${key}` : key;
|
|
|
85589
85896
|
//<editor-fold desc="ANIMATION">
|
|
85590
85897
|
/** The first active clip, until playback is stopped or the object is disposed. */
|
|
85591
85898
|
get animation() {
|
|
85592
|
-
return this.animationPlayers[0]?.animation;
|
|
85899
|
+
return this.animationPlayers[0]?.player.animation;
|
|
85593
85900
|
}
|
|
85594
|
-
/** Clips playing together,
|
|
85901
|
+
/** Clips playing together, in the order passed to {@link playAnimations}. */
|
|
85595
85902
|
get activeAnimations() {
|
|
85596
|
-
|
|
85903
|
+
const animations = [];
|
|
85904
|
+
for (const { player, indices } of this.animationPlayers) {
|
|
85905
|
+
player.animations.forEach((animation, i4) => {
|
|
85906
|
+
animations[indices[i4]] = animation;
|
|
85907
|
+
});
|
|
85908
|
+
}
|
|
85909
|
+
return animations;
|
|
85910
|
+
}
|
|
85911
|
+
/** Weights of the active clips, in the same order as {@link activeAnimations}. */
|
|
85912
|
+
get animationWeights() {
|
|
85913
|
+
const weights = [];
|
|
85914
|
+
for (const { player, indices } of this.animationPlayers) {
|
|
85915
|
+
player.weights.forEach((weight, i4) => {
|
|
85916
|
+
weights[indices[i4]] = weight;
|
|
85917
|
+
});
|
|
85918
|
+
}
|
|
85919
|
+
return weights;
|
|
85597
85920
|
}
|
|
85598
85921
|
/** Seconds since the animation started, before looping. */
|
|
85599
85922
|
get animationTime() {
|
|
85600
|
-
return this.animationPlayers[0]?.time ?? 0;
|
|
85923
|
+
return this.animationPlayers[0]?.player.time ?? 0;
|
|
85601
85924
|
}
|
|
85602
85925
|
/**
|
|
85603
85926
|
* Plays a clip from {@link Entities.getAnimations}, replacing all active clips.
|
|
@@ -85608,42 +85931,59 @@ ${key}` : key;
|
|
|
85608
85931
|
playAnimation(animation, options) {
|
|
85609
85932
|
this.playAnimations([animation], options);
|
|
85610
85933
|
}
|
|
85611
|
-
/**
|
|
85934
|
+
/**
|
|
85935
|
+
* Plays clips with a shared clock, adding their weighted offsets within each geometry layer.
|
|
85936
|
+
* Weights default to 1 and are not normalized. Selected layers without their own clip follow `main`.
|
|
85937
|
+
*/
|
|
85612
85938
|
playAnimations(animations, options) {
|
|
85613
|
-
const
|
|
85614
|
-
const selections =
|
|
85939
|
+
const weights = validateAnimationWeights(options?.weights ?? animations.map(() => 1), animations.length);
|
|
85940
|
+
const selections = /* @__PURE__ */ new Map();
|
|
85941
|
+
animations.forEach((animation, index) => {
|
|
85615
85942
|
const layer = animation.layer ?? "main";
|
|
85616
|
-
if (targets.has(layer)) throw new Error(`Multiple animations target layer "${layer}"`);
|
|
85617
|
-
targets.add(layer);
|
|
85618
85943
|
const names = Object.keys(this.entityLayers).filter((name2) => name2.split("#")[0] === layer);
|
|
85619
85944
|
if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer "${layer}"`);
|
|
85620
|
-
|
|
85945
|
+
let selection = selections.get(layer);
|
|
85946
|
+
if (!selection) selections.set(layer, selection = { animations: [], names, indices: [] });
|
|
85947
|
+
selection.animations.push(animation);
|
|
85948
|
+
selection.indices.push(index);
|
|
85621
85949
|
});
|
|
85622
|
-
const main = selections.
|
|
85623
|
-
if (main) main.names.push(...Object.keys(this.entityLayers).filter((name2) => !
|
|
85950
|
+
const main = selections.get("main");
|
|
85951
|
+
if (main) main.names.push(...Object.keys(this.entityLayers).filter((name2) => !selections.has(name2.split("#")[0])));
|
|
85624
85952
|
this.createMeshes();
|
|
85625
85953
|
this.stopAnimation();
|
|
85626
|
-
for (const {
|
|
85954
|
+
for (const { animations: clips, names, indices } of selections.values()) {
|
|
85627
85955
|
const player = new EntityAnimationPlayer();
|
|
85628
|
-
player.
|
|
85629
|
-
|
|
85956
|
+
player.playAnimations(
|
|
85957
|
+
names.map((name2) => this.getLayerGroup(name2)),
|
|
85958
|
+
clips,
|
|
85959
|
+
{ ...options, weights: indices.map((index) => weights[index]) },
|
|
85960
|
+
this.partPoses
|
|
85961
|
+
);
|
|
85962
|
+
this.animationPlayers.push({ player, indices });
|
|
85630
85963
|
}
|
|
85631
85964
|
this.notifyDirty();
|
|
85632
85965
|
}
|
|
85966
|
+
/** Changes weights in active clip order, notifying the scene without restarting the shared clock. Has no effect without an animation. */
|
|
85967
|
+
setAnimationWeights(weights) {
|
|
85968
|
+
if (!this.animationPlayers.length) return;
|
|
85969
|
+
const values = validateAnimationWeights(weights, this.activeAnimations.length);
|
|
85970
|
+
for (const { player, indices } of this.animationPlayers) player.setWeights(indices.map((index) => values[index]));
|
|
85971
|
+
this.notifyDirty();
|
|
85972
|
+
}
|
|
85633
85973
|
/** Stops all clips and restores the poses from before playback. */
|
|
85634
85974
|
stopAnimation() {
|
|
85635
85975
|
const players = this.animationPlayers.splice(0);
|
|
85636
|
-
for (const player of players) player.stop();
|
|
85976
|
+
for (const { player } of players) player.stop();
|
|
85637
85977
|
if (players.length) this.notifyDirty();
|
|
85638
85978
|
}
|
|
85639
85979
|
/** Poses the object at an explicit time in seconds. Has no effect without an animation. */
|
|
85640
85980
|
setAnimationTime(seconds) {
|
|
85641
|
-
for (const player of this.animationPlayers) player.setTime(seconds);
|
|
85981
|
+
for (const { player } of this.animationPlayers) player.setTime(seconds);
|
|
85642
85982
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
85643
85983
|
}
|
|
85644
85984
|
/** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
|
|
85645
85985
|
advanceAnimation(deltaSeconds) {
|
|
85646
|
-
for (const player of this.animationPlayers) player.advance(deltaSeconds);
|
|
85986
|
+
for (const { player } of this.animationPlayers) player.advance(deltaSeconds);
|
|
85647
85987
|
if (this.animationPlayers.length) this.notifyDirty();
|
|
85648
85988
|
}
|
|
85649
85989
|
//</editor-fold>
|
|
@@ -87881,6 +88221,7 @@ ${key}` : key;
|
|
|
87881
88221
|
}
|
|
87882
88222
|
const font = await Fonts.get(options.font);
|
|
87883
88223
|
const runs = typeof text2 === "string" ? [{ text: text2 }] : text2;
|
|
88224
|
+
await font.resolve?.(runs.map((run) => run.text).join(""));
|
|
87884
88225
|
const glyphs = [], lineWidths = [];
|
|
87885
88226
|
let line = [], width = 0;
|
|
87886
88227
|
let trailingNewline = false;
|
|
@@ -87907,7 +88248,7 @@ ${key}` : key;
|
|
|
87907
88248
|
continue;
|
|
87908
88249
|
}
|
|
87909
88250
|
const glyph = font.glyphs.get(character);
|
|
87910
|
-
const advance = (glyph?.advance ?? 6) + (style.bold ? 1 : 0);
|
|
88251
|
+
const advance = (glyph?.advance ?? 6) + (style.bold ? glyph?.boldOffset ?? 1 : 0);
|
|
87911
88252
|
line.push({ character, glyph, advance, style, x: 0, y: 0 });
|
|
87912
88253
|
width += advance;
|
|
87913
88254
|
while (width > maxWidth && line.length > 1) {
|
|
@@ -87935,7 +88276,7 @@ ${key}` : key;
|
|
|
87935
88276
|
batches.push(batch);
|
|
87936
88277
|
}
|
|
87937
88278
|
const color3 = new Color(isShadow ? (style.color & 16579836) >> 2 : style.color);
|
|
87938
|
-
const offset = isShadow ? 1 : 0;
|
|
88279
|
+
const offset = isShadow ? glyph?.shadowOffset ?? 1 : 0;
|
|
87939
88280
|
const top = glyph ? 7 - glyph.ascent : 0;
|
|
87940
88281
|
const height = glyph ? glyph.height * glyph.scale : 8;
|
|
87941
88282
|
const width = glyph ? glyph.width * glyph.scale : 5;
|
|
@@ -87965,7 +88306,7 @@ ${key}` : key;
|
|
|
87965
88306
|
for (let i4 = 0; i4 < 4; i4++) batch.colors.push(color3.r, color3.g, color3.b);
|
|
87966
88307
|
batch.indices.push(base, base + 2, base + 1, base + 2, base + 3, base + 1);
|
|
87967
88308
|
};
|
|
87968
|
-
for (const boldOffset of style.bold ? [0, 1] : [0]) {
|
|
88309
|
+
for (const boldOffset of style.bold ? [0, glyph?.boldOffset ?? 1] : [0]) {
|
|
87969
88310
|
if (glyph) quad(0, top, width, top + height, boldOffset);
|
|
87970
88311
|
else {
|
|
87971
88312
|
quad(0, 0, 5, 1, boldOffset);
|
|
@@ -92503,6 +92844,10 @@ ${shader.fragmentShader}`.replace(
|
|
|
92503
92844
|
this.atlas.model.elements?.forEach((el) => {
|
|
92504
92845
|
const elGeo = this._getBoxGeometryFromElement(el).clone();
|
|
92505
92846
|
this.geometries.add(elGeo);
|
|
92847
|
+
elGeo.setAttribute("shade", new BufferAttribute(
|
|
92848
|
+
new Float32Array(elGeo.getAttribute("position").count).fill(!this.originalModel.itemId && el.shade === false ? 0 : 1),
|
|
92849
|
+
1
|
|
92850
|
+
));
|
|
92506
92851
|
if (this.options.cullMask) {
|
|
92507
92852
|
const indices = Array.from(elGeo.getIndex().array);
|
|
92508
92853
|
elGeo.setIndex(indices.filter((_4, index) => {
|
|
@@ -94105,6 +94450,7 @@ ${shader.fragmentShader}`.replace(
|
|
|
94105
94450
|
toRadians: () => toRadians,
|
|
94106
94451
|
toTrianglesDrawMode: () => toTrianglesDrawMode,
|
|
94107
94452
|
trimCanvas: () => trimCanvas,
|
|
94453
|
+
validateAnimationWeights: () => validateAnimationWeights,
|
|
94108
94454
|
yieldToEventLoop: () => yieldToEventLoop
|
|
94109
94455
|
});
|
|
94110
94456
|
init_dirname();
|
|
@@ -102794,9 +103140,9 @@ gl_FragDepth=readDepth(vUv);
|
|
|
102794
103140
|
function compactQuads(geometry, keep) {
|
|
102795
103141
|
const quads = keep.flatMap((kept, index) => kept ? [index] : []);
|
|
102796
103142
|
const compact = new BufferGeometry();
|
|
102797
|
-
for (const [name2, size] of Object.entries({ position: 3, normal: 3, uv: 2, uvBounds: 4, color: 3 })) {
|
|
103143
|
+
for (const [name2, size] of Object.entries({ position: 3, normal: 3, uv: 2, uvBounds: 4, color: 3, shade: 1 })) {
|
|
102798
103144
|
const source2 = geometry.getAttribute(name2);
|
|
102799
|
-
const defaults = name2 === "uvBounds" ? [0, 0, 1, 1] : name2 === "color" ? [1, 1, 1] : void 0;
|
|
103145
|
+
const defaults = name2 === "uvBounds" ? [0, 0, 1, 1] : name2 === "color" ? [1, 1, 1] : name2 === "shade" ? [1] : void 0;
|
|
102800
103146
|
const values = new Float32Array(quads.length * 4 * size);
|
|
102801
103147
|
for (let q3 = 0; q3 < quads.length; q3++) {
|
|
102802
103148
|
for (let vertex2 = 0; vertex2 < 4; vertex2++) {
|
|
@@ -104074,7 +104420,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104074
104420
|
|
|
104075
104421
|
// src/world/SectionGeometry.ts
|
|
104076
104422
|
function buildSectionGeometry(input) {
|
|
104077
|
-
const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;
|
|
104423
|
+
const { count, indices, templates, cullMasks, templateData, atlases: atlases2, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;
|
|
104078
104424
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
104079
104425
|
if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError("Section entry count exceeds its arrays");
|
|
104080
104426
|
if (biomeTints && biomeTints.length !== count * 3) throw new RangeError("Section biome tints must contain RGB for each placement");
|
|
@@ -104092,7 +104438,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104092
104438
|
const cornerBrightness2 = ambientOcclusion ? new Float32Array(4) : void 0;
|
|
104093
104439
|
for (const template of templateData) {
|
|
104094
104440
|
const { quads } = template;
|
|
104095
|
-
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) {
|
|
104441
|
+
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) {
|
|
104096
104442
|
throw new RangeError("Section template arrays do not match its quad count");
|
|
104097
104443
|
}
|
|
104098
104444
|
}
|
|
@@ -104109,8 +104455,8 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104109
104455
|
const locations = /* @__PURE__ */ new Map();
|
|
104110
104456
|
for (const [layer, layerAtlases] of [...visibleAtlases].sort(([a4], [b4]) => a4 - b4)) {
|
|
104111
104457
|
const firstPage = pages.length;
|
|
104112
|
-
for (const atlas of [...layerAtlases].sort((a4, b4) => Number(
|
|
104113
|
-
const { width, height, animated } =
|
|
104458
|
+
for (const atlas of [...layerAtlases].sort((a4, b4) => Number(atlases2[a4].animated) - Number(atlases2[b4].animated) || (atlases2[a4].animated ? a4 - b4 : atlases2[b4].height - atlases2[a4].height))) {
|
|
104459
|
+
const { width, height, animated } = atlases2[atlas];
|
|
104114
104460
|
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
104115
104461
|
let selected = -1;
|
|
104116
104462
|
for (let i4 = firstPage; !animated && i4 < pages.length; i4++) {
|
|
@@ -104153,7 +104499,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104153
104499
|
});
|
|
104154
104500
|
if (!quads.sprites.length) continue;
|
|
104155
104501
|
if (!fluidPages.has(fluid)) {
|
|
104156
|
-
const { width, height } =
|
|
104502
|
+
const { width, height } = atlases2[data.atlas];
|
|
104157
104503
|
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
104158
104504
|
fluidPages.set(fluid, {
|
|
104159
104505
|
layer: 2,
|
|
@@ -104171,7 +104517,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104171
104517
|
const tint = fluid === "water" && fluids.waterTints ? fluids.waterTints.subarray(tintIndex, tintIndex + 3) : data.tint;
|
|
104172
104518
|
fluidPages.get(fluid).fluids.push({ quads, x: x4, y: y5, z: z4, data, tint });
|
|
104173
104519
|
}
|
|
104174
|
-
pages.push(...[...fluidPages.values()].sort((a4, b4) => Number(
|
|
104520
|
+
pages.push(...[...fluidPages.values()].sort((a4, b4) => Number(atlases2[a4.placements[0].atlas].animated) - Number(atlases2[b4.placements[0].atlas].animated) || a4.placements[0].atlas - b4.placements[0].atlas));
|
|
104175
104521
|
}
|
|
104176
104522
|
return pages.map((page) => {
|
|
104177
104523
|
let faces = page.fluids.reduce((sum, fluid) => sum + fluid.quads.sprites.length, 0);
|
|
@@ -104183,12 +104529,13 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104183
104529
|
}
|
|
104184
104530
|
const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);
|
|
104185
104531
|
const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);
|
|
104532
|
+
const shade = new Float32Array(faces * 4).fill(1);
|
|
104186
104533
|
const outputIndices = new Uint32Array(faces * 6);
|
|
104187
104534
|
const blockIndices = new Uint16Array(faces);
|
|
104188
104535
|
let vertex2 = 0, indexOffset = 0;
|
|
104189
104536
|
for (const entry of page.entries) {
|
|
104190
104537
|
const template = templateData[templates[entry]];
|
|
104191
|
-
const atlas =
|
|
104538
|
+
const atlas = atlases2[template.atlas];
|
|
104192
104539
|
const placement = locations.get(template.atlas);
|
|
104193
104540
|
const mapU = (u4) => (placement.x + u4 * atlas.width) / page.width;
|
|
104194
104541
|
const mapV = (v5) => 1 - (placement.y + (1 - v5) * atlas.height) / page.height;
|
|
@@ -104212,6 +104559,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104212
104559
|
normals[vertex2 * 3] = template.normals[source * 3];
|
|
104213
104560
|
normals[vertex2 * 3 + 1] = template.normals[source * 3 + 1];
|
|
104214
104561
|
normals[vertex2 * 3 + 2] = template.normals[source * 3 + 2];
|
|
104562
|
+
shade[vertex2] = template.shade?.[source] ?? 1;
|
|
104215
104563
|
uvs[vertex2 * 2] = mapU(template.uvs[source * 2]);
|
|
104216
104564
|
uvs[vertex2 * 2 + 1] = mapV(template.uvs[source * 2 + 1]);
|
|
104217
104565
|
uvBounds[vertex2 * 4] = mapU(template.uvBounds[source * 4]);
|
|
@@ -104227,7 +104575,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104227
104575
|
}
|
|
104228
104576
|
}
|
|
104229
104577
|
for (const { quads, x: x4, y: y5, z: z4, data, tint } of page.fluids) {
|
|
104230
|
-
const atlas =
|
|
104578
|
+
const atlas = atlases2[data.atlas];
|
|
104231
104579
|
const placement = page.placements[0];
|
|
104232
104580
|
const mapU = (u4) => (placement.x + u4 * atlas.width) / page.width;
|
|
104233
104581
|
const mapV = (v5) => 1 - (placement.y + (1 - v5) * atlas.height) / page.height;
|
|
@@ -104264,11 +104612,11 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104264
104612
|
indexOffset += 6;
|
|
104265
104613
|
}
|
|
104266
104614
|
}
|
|
104267
|
-
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices, blockIndices };
|
|
104615
|
+
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, shade, indices: outputIndices, blockIndices };
|
|
104268
104616
|
});
|
|
104269
104617
|
}
|
|
104270
104618
|
function sectionGeometryTransferables(pages) {
|
|
104271
|
-
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]);
|
|
104619
|
+
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]);
|
|
104272
104620
|
}
|
|
104273
104621
|
|
|
104274
104622
|
// src/world/SectionWorker.ts
|
|
@@ -104331,7 +104679,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104331
104679
|
var WATER_TINT = new Color(4159204).toArray();
|
|
104332
104680
|
function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
104333
104681
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
104334
|
-
const
|
|
104682
|
+
const atlases2 = [];
|
|
104335
104683
|
const atlasIds = /* @__PURE__ */ new Map();
|
|
104336
104684
|
const templateIds = /* @__PURE__ */ new Map();
|
|
104337
104685
|
const input = {
|
|
@@ -104354,9 +104702,9 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104354
104702
|
if (id === void 0) {
|
|
104355
104703
|
let atlas = atlasIds.get(template.atlas);
|
|
104356
104704
|
if (atlas === void 0) {
|
|
104357
|
-
atlas =
|
|
104705
|
+
atlas = atlases2.length;
|
|
104358
104706
|
atlasIds.set(template.atlas, atlas);
|
|
104359
|
-
|
|
104707
|
+
atlases2.push(template.atlas);
|
|
104360
104708
|
input.atlases.push({ width: template.atlas.image.width, height: template.atlas.image.height, animated: template.atlas.hasAnimation });
|
|
104361
104709
|
}
|
|
104362
104710
|
let data = templateCache.get(template);
|
|
@@ -104374,6 +104722,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104374
104722
|
uvs: new Float32Array(quads * 8),
|
|
104375
104723
|
uvBounds: new Float32Array(quads * 16),
|
|
104376
104724
|
colors: new Float32Array(quads * 12),
|
|
104725
|
+
shade: new Float32Array(quads * 4),
|
|
104377
104726
|
indices: new Uint16Array(quads * 6),
|
|
104378
104727
|
cullFaces: new Uint8Array(template.cullFaces),
|
|
104379
104728
|
biomeTint: template.biomeTint ? new Uint8Array(template.biomeTint) : void 0,
|
|
@@ -104385,6 +104734,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104385
104734
|
const uv = template.geometry.getAttribute("uv");
|
|
104386
104735
|
const bounds = template.geometry.getAttribute("uvBounds");
|
|
104387
104736
|
const color3 = template.geometry.getAttribute("color");
|
|
104737
|
+
const shade = template.geometry.getAttribute("shade");
|
|
104388
104738
|
for (let vertex2 = 0; vertex2 < quads * 4; vertex2++) {
|
|
104389
104739
|
data.positions.set([position.getX(vertex2), position.getY(vertex2), position.getZ(vertex2)], vertex2 * 3);
|
|
104390
104740
|
data.normals.set([normal.getX(vertex2), normal.getY(vertex2), normal.getZ(vertex2)], vertex2 * 3);
|
|
@@ -104396,6 +104746,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104396
104746
|
bounds?.getW(vertex2) ?? 1
|
|
104397
104747
|
], vertex2 * 4);
|
|
104398
104748
|
data.colors.set([color3?.getX(vertex2) ?? 1, color3?.getY(vertex2) ?? 1, color3?.getZ(vertex2) ?? 1], vertex2 * 3);
|
|
104749
|
+
data.shade[vertex2] = shade?.getX(vertex2) ?? 1;
|
|
104399
104750
|
}
|
|
104400
104751
|
for (let i5 = 0; i5 < data.indices.length; i5++) data.indices[i5] = indices.getX(i5) - 4 * Math.floor(i5 / 6);
|
|
104401
104752
|
templateCache.set(template, data);
|
|
@@ -104415,9 +104766,9 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104415
104766
|
if (!atlas) continue;
|
|
104416
104767
|
let id = atlasIds.get(atlas);
|
|
104417
104768
|
if (id === void 0) {
|
|
104418
|
-
id =
|
|
104769
|
+
id = atlases2.length;
|
|
104419
104770
|
atlasIds.set(atlas, id);
|
|
104420
|
-
|
|
104771
|
+
atlases2.push(atlas);
|
|
104421
104772
|
input.atlases.push({ width: atlas.image.width, height: atlas.image.height, animated: atlas.hasAnimation });
|
|
104422
104773
|
}
|
|
104423
104774
|
input.fluids[kind] = {
|
|
@@ -104428,7 +104779,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104428
104779
|
};
|
|
104429
104780
|
}
|
|
104430
104781
|
}
|
|
104431
|
-
return { input, atlases };
|
|
104782
|
+
return { input, atlases: atlases2 };
|
|
104432
104783
|
}
|
|
104433
104784
|
var SectionMesh = class _SectionMesh extends Group {
|
|
104434
104785
|
constructor() {
|
|
@@ -104443,23 +104794,23 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104443
104794
|
}
|
|
104444
104795
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
104445
104796
|
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
104446
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
104447
|
-
return this.fromPages(buildSectionGeometry(input),
|
|
104797
|
+
const { input, atlases: atlases2 } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
104798
|
+
return this.fromPages(buildSectionGeometry(input), atlases2);
|
|
104448
104799
|
}
|
|
104449
104800
|
/** Builds section-local meshes in a browser worker when available, with synchronous fallback. */
|
|
104450
104801
|
static async buildAsync(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
104451
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
104802
|
+
const { input, atlases: atlases2 } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
104452
104803
|
const worker = SectionWorker.shared();
|
|
104453
104804
|
const pages = worker ? await worker.build(input).catch(() => buildSectionGeometry(input)) : buildSectionGeometry(input);
|
|
104454
|
-
return this.fromPages(pages,
|
|
104805
|
+
return this.fromPages(pages, atlases2);
|
|
104455
104806
|
}
|
|
104456
|
-
static fromPages(pages,
|
|
104807
|
+
static fromPages(pages, atlases2) {
|
|
104457
104808
|
const section = new _SectionMesh();
|
|
104458
104809
|
for (const page of pages) {
|
|
104459
104810
|
const canvas = createCanvas(page.width, page.height);
|
|
104460
104811
|
const context = canvas.getContext("2d");
|
|
104461
104812
|
for (const { atlas, x: x4, y: y5 } of page.placements) {
|
|
104462
|
-
context.drawImage(
|
|
104813
|
+
context.drawImage(atlases2[atlas].image.canvas, x4, y5);
|
|
104463
104814
|
}
|
|
104464
104815
|
const geometry = new BufferGeometry();
|
|
104465
104816
|
geometry.setAttribute("position", new Float32BufferAttribute(page.positions.buffer, 3));
|
|
@@ -104467,10 +104818,11 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104467
104818
|
geometry.setAttribute("uv", new Float32BufferAttribute(page.uvs.buffer, 2));
|
|
104468
104819
|
geometry.setAttribute("uvBounds", new Float32BufferAttribute(page.uvBounds.buffer, 4));
|
|
104469
104820
|
geometry.setAttribute("color", new Float32BufferAttribute(page.colors.buffer, 3));
|
|
104821
|
+
geometry.setAttribute("shade", new Float32BufferAttribute(page.shade.buffer, 1));
|
|
104470
104822
|
geometry.setIndex(new Uint32BufferAttribute(page.indices.buffer, 1));
|
|
104471
104823
|
geometry.computeBoundingBox();
|
|
104472
104824
|
geometry.computeBoundingSphere();
|
|
104473
|
-
const transparent = page.layer === 2 ?
|
|
104825
|
+
const transparent = page.layer === 2 ? atlases2[page.placements[0].atlas].hasTranslucency : page.layer === 1;
|
|
104474
104826
|
const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
|
|
104475
104827
|
material.side = FrontSide;
|
|
104476
104828
|
if (page.layer === 2) {
|
|
@@ -104485,7 +104837,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
104485
104837
|
section.blockIndices.set(mesh, page.blockIndices);
|
|
104486
104838
|
const unsubscribe = [];
|
|
104487
104839
|
for (const { atlas: id, x: x4, y: y5 } of page.placements) {
|
|
104488
|
-
const atlas =
|
|
104840
|
+
const atlas = atlases2[id];
|
|
104489
104841
|
if (!atlas.hasAnimation) continue;
|
|
104490
104842
|
unsubscribe.push(atlas.subscribe(() => {
|
|
104491
104843
|
context.clearRect(x4, y5, atlas.image.width, atlas.image.height);
|