minerender 2.1.0-alpha.132 → 2.1.0-alpha.133
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/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/gui/GuiText.mjs +4 -3
- package/dist/browser/esm/gui/GuiText.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +23 -4
- package/dist/browser/index.d.ts +23 -4
- package/dist/browser/index.js +245 -31
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +288 -31
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +23 -4
- package/dist/node/index.d.ts +23 -4
- package/dist/node/index.js +249 -31
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +249 -31
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser/index.js
CHANGED
|
@@ -286,6 +286,7 @@ var init_Caching = __esm({
|
|
|
286
286
|
this.entityAnimationCache,
|
|
287
287
|
this.blockEntityIndexCache,
|
|
288
288
|
this.fontCache,
|
|
289
|
+
this.unihexCache,
|
|
289
290
|
this.bannerPatternCache,
|
|
290
291
|
this.mineRenderDataCache,
|
|
291
292
|
this.usernameUuidCache,
|
|
@@ -339,6 +340,7 @@ var init_Caching = __esm({
|
|
|
339
340
|
_Caching.entityTextureCache = _Caching.createAssetCache();
|
|
340
341
|
_Caching.entityAnimationCache = _Caching.createAssetCache();
|
|
341
342
|
_Caching.blockEntityIndexCache = _Caching.createAssetCache();
|
|
343
|
+
_Caching.unihexCache = _Caching.createAssetCache();
|
|
342
344
|
_Caching.fontCache = _Caching.createAssetCache();
|
|
343
345
|
_Caching.bannerPatternCache = _Caching.createAssetCache();
|
|
344
346
|
_Caching.mineRenderDataCache = _Caching.createAssetCache();
|
|
@@ -1351,6 +1353,7 @@ var init_AssetParsers = __esm({
|
|
|
1351
1353
|
AssetParser2["IMAGE"] = "image";
|
|
1352
1354
|
AssetParser2["LIST"] = "list";
|
|
1353
1355
|
AssetParser2["JSON"] = "json";
|
|
1356
|
+
AssetParser2["BINARY"] = "binary";
|
|
1354
1357
|
return AssetParser2;
|
|
1355
1358
|
})(AssetParser || {});
|
|
1356
1359
|
}
|
|
@@ -2821,7 +2824,7 @@ var init_parser = __esm({
|
|
|
2821
2824
|
});
|
|
2822
2825
|
|
|
2823
2826
|
// src/assets/source/HostedAssetSource.ts
|
|
2824
|
-
var p4, DEFAULT_OPTIONS, _HostedAssetSource, HostedAssetSource;
|
|
2827
|
+
var BINARY_TIMEOUT, p4, DEFAULT_OPTIONS, _HostedAssetSource, HostedAssetSource;
|
|
2825
2828
|
var init_HostedAssetSource = __esm({
|
|
2826
2829
|
"src/assets/source/HostedAssetSource.ts"() {
|
|
2827
2830
|
init_AssetSource();
|
|
@@ -2834,6 +2837,7 @@ var init_HostedAssetSource = __esm({
|
|
|
2834
2837
|
init_AssetLoader();
|
|
2835
2838
|
init_parser();
|
|
2836
2839
|
init_merge();
|
|
2840
|
+
BINARY_TIMEOUT = 6e4;
|
|
2837
2841
|
p4 = prefix("HostedAssetSource");
|
|
2838
2842
|
DEFAULT_OPTIONS = {
|
|
2839
2843
|
retryDefaults: true
|
|
@@ -2974,6 +2978,15 @@ var init_HostedAssetSource = __esm({
|
|
|
2974
2978
|
return response.data;
|
|
2975
2979
|
}
|
|
2976
2980
|
};
|
|
2981
|
+
_HostedAssetSource.BINARY = {
|
|
2982
|
+
config(request) {
|
|
2983
|
+
request.timeout = BINARY_TIMEOUT;
|
|
2984
|
+
request.responseType = "arraybuffer";
|
|
2985
|
+
},
|
|
2986
|
+
parse(response) {
|
|
2987
|
+
return { data: new Uint8Array(response.data) };
|
|
2988
|
+
}
|
|
2989
|
+
};
|
|
2977
2990
|
_HostedAssetSource.PARSER_MAP = /* @__PURE__ */ new Map([
|
|
2978
2991
|
["model" /* MODEL */, _HostedAssetSource.MODEL],
|
|
2979
2992
|
["blockstate" /* BLOCKSTATE */, _HostedAssetSource.BLOCKSTATE],
|
|
@@ -2981,7 +2994,8 @@ var init_HostedAssetSource = __esm({
|
|
|
2981
2994
|
["nbt" /* NBT */, _HostedAssetSource.NBT],
|
|
2982
2995
|
["image" /* IMAGE */, _HostedAssetSource.IMAGE],
|
|
2983
2996
|
["list" /* LIST */, _HostedAssetSource.LIST],
|
|
2984
|
-
["json" /* JSON */, _HostedAssetSource.JSON]
|
|
2997
|
+
["json" /* JSON */, _HostedAssetSource.JSON],
|
|
2998
|
+
["binary" /* BINARY */, _HostedAssetSource.BINARY]
|
|
2985
2999
|
]);
|
|
2986
3000
|
HostedAssetSource = _HostedAssetSource;
|
|
2987
3001
|
}
|
|
@@ -4762,6 +4776,178 @@ var init_Entities = __esm({
|
|
|
4762
4776
|
}
|
|
4763
4777
|
});
|
|
4764
4778
|
|
|
4779
|
+
// src/assets/_fonts/Unihex.ts
|
|
4780
|
+
var Unihex_exports = {};
|
|
4781
|
+
__export(Unihex_exports, {
|
|
4782
|
+
loadUnihex: () => loadUnihex
|
|
4783
|
+
});
|
|
4784
|
+
function readHex(text2, filename, glyphs) {
|
|
4785
|
+
const lines = text2.split("\n");
|
|
4786
|
+
if (lines[lines.length - 1] === "") lines.pop();
|
|
4787
|
+
lines.forEach((line, index) => {
|
|
4788
|
+
const match = /^([0-9A-F]{4,6}):([0-9A-F]+)$/.exec(line);
|
|
4789
|
+
if (!match || ![32, 64, 96, 128].includes(match[2].length)) {
|
|
4790
|
+
throw new Error(`Invalid Unihex record in ${filename} at line ${index + 1}`);
|
|
4791
|
+
}
|
|
4792
|
+
const codepoint = parseInt(match[1], 16);
|
|
4793
|
+
if (codepoint > 1114111) throw new Error(`Invalid Unihex codepoint in ${filename} at line ${index + 1}`);
|
|
4794
|
+
const bitWidth = match[2].length / 4;
|
|
4795
|
+
const rowLength = bitWidth / 4;
|
|
4796
|
+
const rows = new Uint32Array(GLYPH_HEIGHT);
|
|
4797
|
+
let mask = 0;
|
|
4798
|
+
for (let y = 0; y < GLYPH_HEIGHT; y++) {
|
|
4799
|
+
rows[y] = parseInt(match[2].slice(y * rowLength, (y + 1) * rowLength), 16);
|
|
4800
|
+
mask |= rows[y];
|
|
4801
|
+
}
|
|
4802
|
+
let left = 0, right = bitWidth;
|
|
4803
|
+
if (mask) {
|
|
4804
|
+
while (!(mask >>> bitWidth - left - 1 & 1)) left++;
|
|
4805
|
+
right = bitWidth - 1;
|
|
4806
|
+
while (!(mask >>> bitWidth - right - 1 & 1)) right--;
|
|
4807
|
+
}
|
|
4808
|
+
glyphs.set(codepoint, { rows, bitWidth, left, right });
|
|
4809
|
+
});
|
|
4810
|
+
}
|
|
4811
|
+
async function parseUnihex(key) {
|
|
4812
|
+
try {
|
|
4813
|
+
const asset2 = await AssetLoader.get(key, "binary" /* BINARY */);
|
|
4814
|
+
if (!asset2) throw new Error(`Could not load Unihex archive ${key.toNamespacedString()}`);
|
|
4815
|
+
const records = /* @__PURE__ */ new Map();
|
|
4816
|
+
const reader = new import_zip2.ZipReader(new import_zip2.Uint8ArrayReader(asset2.data), { useWebWorkers: false, useCompressionStream: false });
|
|
4817
|
+
try {
|
|
4818
|
+
for (const entry of await reader.getEntries()) {
|
|
4819
|
+
if (!entry.directory && entry.filename.endsWith(".hex")) {
|
|
4820
|
+
readHex(await entry.getData(new import_zip2.TextWriter(), { checkSignature: true }), entry.filename, records);
|
|
4821
|
+
}
|
|
4822
|
+
}
|
|
4823
|
+
} finally {
|
|
4824
|
+
await reader.close();
|
|
4825
|
+
}
|
|
4826
|
+
const indices = new Int32Array(1114112).fill(-1);
|
|
4827
|
+
const rows = new Uint32Array(records.size * GLYPH_HEIGHT), metrics = new Uint8Array(records.size * 3);
|
|
4828
|
+
let index = 0;
|
|
4829
|
+
for (const [codepoint, record] of records) {
|
|
4830
|
+
indices[codepoint] = index;
|
|
4831
|
+
rows.set(record.rows, index * GLYPH_HEIGHT);
|
|
4832
|
+
metrics.set([record.bitWidth, record.left, record.right], index * 3);
|
|
4833
|
+
index++;
|
|
4834
|
+
}
|
|
4835
|
+
return { indices, rows, metrics };
|
|
4836
|
+
} catch (error) {
|
|
4837
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
|
|
4838
|
+
return void 0;
|
|
4839
|
+
}
|
|
4840
|
+
}
|
|
4841
|
+
async function loadUnihex(provider, fontKey, characters) {
|
|
4842
|
+
const origin = new AssetKey(DEFAULT_NAMESPACE, "", void 0, void 0, "assets", "", fontKey.root);
|
|
4843
|
+
const key = AssetKey.parse("font", provider.hex_file, origin);
|
|
4844
|
+
key.assetType = void 0;
|
|
4845
|
+
const glyphs = /* @__PURE__ */ new Map();
|
|
4846
|
+
let overrides;
|
|
4847
|
+
try {
|
|
4848
|
+
overrides = (provider.size_overrides ?? []).map((override) => {
|
|
4849
|
+
const from = override.from.codePointAt(0), to = override.to.codePointAt(0);
|
|
4850
|
+
if ([...override.from].length !== 1 || [...override.to].length !== 1 || from >= to || !Number.isInteger(override.left) || !Number.isInteger(override.right) || override.right < override.left) {
|
|
4851
|
+
throw new Error(`Invalid Unihex size override in font ${fontKey.toNamespacedString()}`);
|
|
4852
|
+
}
|
|
4853
|
+
return { ...override, from, to };
|
|
4854
|
+
});
|
|
4855
|
+
} catch (error) {
|
|
4856
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
|
|
4857
|
+
return glyphs;
|
|
4858
|
+
}
|
|
4859
|
+
const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));
|
|
4860
|
+
if (!file) return glyphs;
|
|
4861
|
+
let atlas = atlases.get(provider);
|
|
4862
|
+
if (!atlas) {
|
|
4863
|
+
atlas = new UnihexAtlas();
|
|
4864
|
+
atlases.set(provider, atlas);
|
|
4865
|
+
}
|
|
4866
|
+
for (const character of characters) {
|
|
4867
|
+
const codepoint = character.codePointAt(0), index = file.indices[codepoint];
|
|
4868
|
+
if (index < 0) continue;
|
|
4869
|
+
const record = {
|
|
4870
|
+
rows: file.rows.subarray(index * GLYPH_HEIGHT, (index + 1) * GLYPH_HEIGHT),
|
|
4871
|
+
bitWidth: file.metrics[index * 3],
|
|
4872
|
+
left: file.metrics[index * 3 + 1],
|
|
4873
|
+
right: file.metrics[index * 3 + 2]
|
|
4874
|
+
};
|
|
4875
|
+
const override = overrides.find((range) => codepoint >= range.from && codepoint <= range.to);
|
|
4876
|
+
if (override) {
|
|
4877
|
+
record.left = override.left;
|
|
4878
|
+
record.right = override.right;
|
|
4879
|
+
}
|
|
4880
|
+
const width = record.right - record.left + 1;
|
|
4881
|
+
let rendered;
|
|
4882
|
+
const render = () => rendered ?? (rendered = atlas.draw(record));
|
|
4883
|
+
glyphs.set(character, {
|
|
4884
|
+
get image() {
|
|
4885
|
+
return render().image;
|
|
4886
|
+
},
|
|
4887
|
+
get x() {
|
|
4888
|
+
return render().x;
|
|
4889
|
+
},
|
|
4890
|
+
get y() {
|
|
4891
|
+
return render().y;
|
|
4892
|
+
},
|
|
4893
|
+
width,
|
|
4894
|
+
height: GLYPH_HEIGHT,
|
|
4895
|
+
scale: 0.5,
|
|
4896
|
+
ascent: 7,
|
|
4897
|
+
advance: Math.floor(width / 2) + 1,
|
|
4898
|
+
boldOffset: 0.5,
|
|
4899
|
+
shadowOffset: 0.5
|
|
4900
|
+
});
|
|
4901
|
+
}
|
|
4902
|
+
return glyphs;
|
|
4903
|
+
}
|
|
4904
|
+
var import_zip2, ATLAS_SIZE, GLYPH_HEIGHT, UnihexAtlas, atlases;
|
|
4905
|
+
var init_Unihex = __esm({
|
|
4906
|
+
"src/assets/_fonts/Unihex.ts"() {
|
|
4907
|
+
import_zip2 = require("@zip.js/zip.js");
|
|
4908
|
+
init_AssetKey();
|
|
4909
|
+
init_AssetLoader();
|
|
4910
|
+
init_Assets();
|
|
4911
|
+
init_Caching();
|
|
4912
|
+
init_AssetParsers();
|
|
4913
|
+
init_CanvasCompat();
|
|
4914
|
+
ATLAS_SIZE = 512;
|
|
4915
|
+
GLYPH_HEIGHT = 16;
|
|
4916
|
+
UnihexAtlas = class {
|
|
4917
|
+
constructor() {
|
|
4918
|
+
this.x = 0;
|
|
4919
|
+
this.y = 0;
|
|
4920
|
+
}
|
|
4921
|
+
draw(glyph) {
|
|
4922
|
+
const width = glyph.right - glyph.left + 1;
|
|
4923
|
+
if (this.image && this.x + width > this.image.width) {
|
|
4924
|
+
this.x = 0;
|
|
4925
|
+
this.y += GLYPH_HEIGHT;
|
|
4926
|
+
}
|
|
4927
|
+
if (!this.image || this.y + GLYPH_HEIGHT > this.image.height || width > this.image.width) {
|
|
4928
|
+
this.image = createCanvas(Math.max(ATLAS_SIZE, width), ATLAS_SIZE);
|
|
4929
|
+
this.x = 0;
|
|
4930
|
+
this.y = 0;
|
|
4931
|
+
}
|
|
4932
|
+
const context = this.image.getContext("2d");
|
|
4933
|
+
const pixels = context.createImageData(width, GLYPH_HEIGHT);
|
|
4934
|
+
for (let y = 0; y < GLYPH_HEIGHT; y++) {
|
|
4935
|
+
for (let x = 0; x < width; x++) {
|
|
4936
|
+
const column = glyph.left + x;
|
|
4937
|
+
if (column < 0 || column >= glyph.bitWidth || !(glyph.rows[y] >>> glyph.bitWidth - column - 1 & 1)) continue;
|
|
4938
|
+
pixels.data.fill(255, (y * width + x) * 4, (y * width + x + 1) * 4);
|
|
4939
|
+
}
|
|
4940
|
+
}
|
|
4941
|
+
const result = { image: this.image, x: this.x, y: this.y };
|
|
4942
|
+
context.putImageData(pixels, this.x, this.y);
|
|
4943
|
+
this.x += width;
|
|
4944
|
+
return result;
|
|
4945
|
+
}
|
|
4946
|
+
};
|
|
4947
|
+
atlases = /* @__PURE__ */ new WeakMap();
|
|
4948
|
+
}
|
|
4949
|
+
});
|
|
4950
|
+
|
|
4765
4951
|
// src/assets/Fonts.ts
|
|
4766
4952
|
var Fonts;
|
|
4767
4953
|
var init_Fonts = __esm({
|
|
@@ -4772,7 +4958,7 @@ var init_Fonts = __esm({
|
|
|
4772
4958
|
init_ModelTextures();
|
|
4773
4959
|
init_Caching();
|
|
4774
4960
|
Fonts = class {
|
|
4775
|
-
/** Combines font definitions in source-priority order.
|
|
4961
|
+
/** Combines font definitions in source-priority order. TrueType providers are skipped. */
|
|
4776
4962
|
static async get(key = "minecraft:default") {
|
|
4777
4963
|
const fontKey = typeof key === "string" ? AssetKey.parse("font", key) : key;
|
|
4778
4964
|
return await Caching.fontCache.get(fontKey.serialize(), () => this.load(fontKey, []));
|
|
@@ -4788,6 +4974,7 @@ var init_Fonts = __esm({
|
|
|
4788
4974
|
const stack = await AssetLoader.getAll(key, "json" /* JSON */);
|
|
4789
4975
|
if (stack.length === 0) throw new Error(`Could not load font ${key.toNamespacedString()}`);
|
|
4790
4976
|
const glyphs = /* @__PURE__ */ new Map();
|
|
4977
|
+
const providers = [];
|
|
4791
4978
|
for (const asset2 of stack) {
|
|
4792
4979
|
for (const provider of asset2.providers) {
|
|
4793
4980
|
if (provider.filter?.uniform || provider.filter?.jp) continue;
|
|
@@ -4806,17 +4993,43 @@ var init_Fonts = __esm({
|
|
|
4806
4993
|
break;
|
|
4807
4994
|
case "reference":
|
|
4808
4995
|
case "minecraft:reference":
|
|
4809
|
-
|
|
4996
|
+
const reference = await this.load(this.relatedKey("font", provider.id, key), [...parents, serialized]);
|
|
4997
|
+
if (reference.resolve) {
|
|
4998
|
+
providers.push(async (characters) => {
|
|
4999
|
+
await reference.resolve(characters);
|
|
5000
|
+
return reference.glyphs;
|
|
5001
|
+
});
|
|
5002
|
+
continue;
|
|
5003
|
+
}
|
|
5004
|
+
provided = reference.glyphs;
|
|
4810
5005
|
break;
|
|
5006
|
+
case "unihex":
|
|
5007
|
+
case "minecraft:unihex":
|
|
5008
|
+
providers.push(async (characters) => (await Promise.resolve().then(() => (init_Unihex(), Unihex_exports))).loadUnihex(provider, key, characters));
|
|
5009
|
+
continue;
|
|
4811
5010
|
default:
|
|
4812
5011
|
continue;
|
|
4813
5012
|
}
|
|
4814
|
-
for (const [character, glyph] of provided) {
|
|
5013
|
+
if (providers.every((provider2) => provider2 instanceof Map)) for (const [character, glyph] of provided) {
|
|
4815
5014
|
if (character !== "\0" && !glyphs.has(character)) glyphs.set(character, glyph);
|
|
4816
5015
|
}
|
|
5016
|
+
providers.push(provided);
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
return { glyphs, resolve: providers.every((provider) => provider instanceof Map) ? void 0 : async (characters) => {
|
|
5020
|
+
const remaining = new Set([...characters].filter((character) => character !== "\0" && character !== "\n" && character !== "\r" && !glyphs.has(character)));
|
|
5021
|
+
for (const provider of providers) {
|
|
5022
|
+
if (!remaining.size) break;
|
|
5023
|
+
const provided = provider instanceof Map ? provider : await provider([...remaining].join(""));
|
|
5024
|
+
for (const character of remaining) {
|
|
5025
|
+
const glyph = provided.get(character);
|
|
5026
|
+
if (glyph) {
|
|
5027
|
+
glyphs.set(character, glyph);
|
|
5028
|
+
remaining.delete(character);
|
|
5029
|
+
}
|
|
5030
|
+
}
|
|
4817
5031
|
}
|
|
4818
|
-
}
|
|
4819
|
-
return { glyphs };
|
|
5032
|
+
} };
|
|
4820
5033
|
}
|
|
4821
5034
|
static async bitmap(provider, fontKey) {
|
|
4822
5035
|
const rows = provider.chars.map((row) => [...row]);
|
|
@@ -8023,6 +8236,7 @@ async function layoutGuiText(text2, options = {}) {
|
|
|
8023
8236
|
}
|
|
8024
8237
|
const font = await Fonts.get(options.font);
|
|
8025
8238
|
const runs = typeof text2 === "string" ? [{ text: text2 }] : text2;
|
|
8239
|
+
await font.resolve?.(runs.map((run) => run.text).join(""));
|
|
8026
8240
|
const glyphs = [], lineWidths = [];
|
|
8027
8241
|
let line = [], width = 0;
|
|
8028
8242
|
let trailingNewline = false;
|
|
@@ -8049,7 +8263,7 @@ async function layoutGuiText(text2, options = {}) {
|
|
|
8049
8263
|
continue;
|
|
8050
8264
|
}
|
|
8051
8265
|
const glyph = font.glyphs.get(character);
|
|
8052
|
-
const advance = (glyph?.advance ?? 6) + (style.bold ? 1 : 0);
|
|
8266
|
+
const advance = (glyph?.advance ?? 6) + (style.bold ? glyph?.boldOffset ?? 1 : 0);
|
|
8053
8267
|
line.push({ character, glyph, advance, style, x: 0, y: 0 });
|
|
8054
8268
|
width += advance;
|
|
8055
8269
|
while (width > maxWidth && line.length > 1) {
|
|
@@ -8077,7 +8291,7 @@ function createGuiTextGeometry(layout, shadow = true) {
|
|
|
8077
8291
|
batches.push(batch);
|
|
8078
8292
|
}
|
|
8079
8293
|
const color2 = new import_three20.Color(isShadow ? (style.color & 16579836) >> 2 : style.color);
|
|
8080
|
-
const offset = isShadow ? 1 : 0;
|
|
8294
|
+
const offset = isShadow ? glyph?.shadowOffset ?? 1 : 0;
|
|
8081
8295
|
const top = glyph ? 7 - glyph.ascent : 0;
|
|
8082
8296
|
const height = glyph ? glyph.height * glyph.scale : 8;
|
|
8083
8297
|
const width = glyph ? glyph.width * glyph.scale : 5;
|
|
@@ -8107,7 +8321,7 @@ function createGuiTextGeometry(layout, shadow = true) {
|
|
|
8107
8321
|
for (let i = 0; i < 4; i++) batch.colors.push(color2.r, color2.g, color2.b);
|
|
8108
8322
|
batch.indices.push(base, base + 2, base + 1, base + 2, base + 3, base + 1);
|
|
8109
8323
|
};
|
|
8110
|
-
for (const boldOffset of style.bold ? [0, 1] : [0]) {
|
|
8324
|
+
for (const boldOffset of style.bold ? [0, glyph?.boldOffset ?? 1] : [0]) {
|
|
8111
8325
|
if (glyph) quad(0, top, width, top + height, boldOffset);
|
|
8112
8326
|
else {
|
|
8113
8327
|
quad(0, 0, 5, 1, boldOffset);
|
|
@@ -19000,7 +19214,7 @@ var LIGHT_SAMPLE_OFFSETS = [0, 1, -1, 324, -324, 18, -18];
|
|
|
19000
19214
|
|
|
19001
19215
|
// src/world/SectionGeometry.ts
|
|
19002
19216
|
function buildSectionGeometry(input) {
|
|
19003
|
-
const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;
|
|
19217
|
+
const { count, indices, templates, cullMasks, templateData, atlases: atlases2, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;
|
|
19004
19218
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
19005
19219
|
if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError("Section entry count exceeds its arrays");
|
|
19006
19220
|
if (biomeTints && biomeTints.length !== count * 3) throw new RangeError("Section biome tints must contain RGB for each placement");
|
|
@@ -19035,8 +19249,8 @@ function buildSectionGeometry(input) {
|
|
|
19035
19249
|
const locations = /* @__PURE__ */ new Map();
|
|
19036
19250
|
for (const [layer, layerAtlases] of [...visibleAtlases].sort(([a], [b]) => a - b)) {
|
|
19037
19251
|
const firstPage = pages.length;
|
|
19038
|
-
for (const atlas of [...layerAtlases].sort((a, b) => Number(
|
|
19039
|
-
const { width, height, animated } =
|
|
19252
|
+
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))) {
|
|
19253
|
+
const { width, height, animated } = atlases2[atlas];
|
|
19040
19254
|
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
19041
19255
|
let selected = -1;
|
|
19042
19256
|
for (let i = firstPage; !animated && i < pages.length; i++) {
|
|
@@ -19079,7 +19293,7 @@ function buildSectionGeometry(input) {
|
|
|
19079
19293
|
});
|
|
19080
19294
|
if (!quads.sprites.length) continue;
|
|
19081
19295
|
if (!fluidPages.has(fluid)) {
|
|
19082
|
-
const { width, height } =
|
|
19296
|
+
const { width, height } = atlases2[data.atlas];
|
|
19083
19297
|
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
19084
19298
|
fluidPages.set(fluid, {
|
|
19085
19299
|
layer: 2,
|
|
@@ -19097,7 +19311,7 @@ function buildSectionGeometry(input) {
|
|
|
19097
19311
|
const tint = fluid === "water" && fluids.waterTints ? fluids.waterTints.subarray(tintIndex, tintIndex + 3) : data.tint;
|
|
19098
19312
|
fluidPages.get(fluid).fluids.push({ quads, x, y, z, data, tint });
|
|
19099
19313
|
}
|
|
19100
|
-
pages.push(...[...fluidPages.values()].sort((a, b) => Number(
|
|
19314
|
+
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));
|
|
19101
19315
|
}
|
|
19102
19316
|
return pages.map((page) => {
|
|
19103
19317
|
let faces = page.fluids.reduce((sum, fluid) => sum + fluid.quads.sprites.length, 0);
|
|
@@ -19114,7 +19328,7 @@ function buildSectionGeometry(input) {
|
|
|
19114
19328
|
let vertex = 0, indexOffset = 0;
|
|
19115
19329
|
for (const entry of page.entries) {
|
|
19116
19330
|
const template = templateData[templates[entry]];
|
|
19117
|
-
const atlas =
|
|
19331
|
+
const atlas = atlases2[template.atlas];
|
|
19118
19332
|
const placement = locations.get(template.atlas);
|
|
19119
19333
|
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
19120
19334
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
@@ -19153,7 +19367,7 @@ function buildSectionGeometry(input) {
|
|
|
19153
19367
|
}
|
|
19154
19368
|
}
|
|
19155
19369
|
for (const { quads, x, y, z, data, tint } of page.fluids) {
|
|
19156
|
-
const atlas =
|
|
19370
|
+
const atlas = atlases2[data.atlas];
|
|
19157
19371
|
const placement = page.placements[0];
|
|
19158
19372
|
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
19159
19373
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
@@ -19254,7 +19468,7 @@ var templateCache = /* @__PURE__ */ new WeakMap();
|
|
|
19254
19468
|
var WATER_TINT = new import_three46.Color(4159204).toArray();
|
|
19255
19469
|
function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
19256
19470
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
19257
|
-
const
|
|
19471
|
+
const atlases2 = [];
|
|
19258
19472
|
const atlasIds = /* @__PURE__ */ new Map();
|
|
19259
19473
|
const templateIds = /* @__PURE__ */ new Map();
|
|
19260
19474
|
const input = {
|
|
@@ -19277,9 +19491,9 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19277
19491
|
if (id === void 0) {
|
|
19278
19492
|
let atlas = atlasIds.get(template.atlas);
|
|
19279
19493
|
if (atlas === void 0) {
|
|
19280
|
-
atlas =
|
|
19494
|
+
atlas = atlases2.length;
|
|
19281
19495
|
atlasIds.set(template.atlas, atlas);
|
|
19282
|
-
|
|
19496
|
+
atlases2.push(template.atlas);
|
|
19283
19497
|
input.atlases.push({ width: template.atlas.image.width, height: template.atlas.image.height, animated: template.atlas.hasAnimation });
|
|
19284
19498
|
}
|
|
19285
19499
|
let data = templateCache.get(template);
|
|
@@ -19338,9 +19552,9 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19338
19552
|
if (!atlas) continue;
|
|
19339
19553
|
let id = atlasIds.get(atlas);
|
|
19340
19554
|
if (id === void 0) {
|
|
19341
|
-
id =
|
|
19555
|
+
id = atlases2.length;
|
|
19342
19556
|
atlasIds.set(atlas, id);
|
|
19343
|
-
|
|
19557
|
+
atlases2.push(atlas);
|
|
19344
19558
|
input.atlases.push({ width: atlas.image.width, height: atlas.image.height, animated: atlas.hasAnimation });
|
|
19345
19559
|
}
|
|
19346
19560
|
input.fluids[kind] = {
|
|
@@ -19351,7 +19565,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19351
19565
|
};
|
|
19352
19566
|
}
|
|
19353
19567
|
}
|
|
19354
|
-
return { input, atlases };
|
|
19568
|
+
return { input, atlases: atlases2 };
|
|
19355
19569
|
}
|
|
19356
19570
|
var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
19357
19571
|
constructor() {
|
|
@@ -19366,23 +19580,23 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19366
19580
|
}
|
|
19367
19581
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
19368
19582
|
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
19369
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19370
|
-
return this.fromPages(buildSectionGeometry(input),
|
|
19583
|
+
const { input, atlases: atlases2 } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19584
|
+
return this.fromPages(buildSectionGeometry(input), atlases2);
|
|
19371
19585
|
}
|
|
19372
19586
|
/** Builds section-local meshes in a browser worker when available, with synchronous fallback. */
|
|
19373
19587
|
static async buildAsync(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
19374
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19588
|
+
const { input, atlases: atlases2 } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19375
19589
|
const worker = SectionWorker.shared();
|
|
19376
19590
|
const pages = worker ? await worker.build(input).catch(() => buildSectionGeometry(input)) : buildSectionGeometry(input);
|
|
19377
|
-
return this.fromPages(pages,
|
|
19591
|
+
return this.fromPages(pages, atlases2);
|
|
19378
19592
|
}
|
|
19379
|
-
static fromPages(pages,
|
|
19593
|
+
static fromPages(pages, atlases2) {
|
|
19380
19594
|
const section = new _SectionMesh();
|
|
19381
19595
|
for (const page of pages) {
|
|
19382
19596
|
const canvas = createCanvas(page.width, page.height);
|
|
19383
19597
|
const context = canvas.getContext("2d");
|
|
19384
19598
|
for (const { atlas, x, y } of page.placements) {
|
|
19385
|
-
context.drawImage(
|
|
19599
|
+
context.drawImage(atlases2[atlas].image.canvas, x, y);
|
|
19386
19600
|
}
|
|
19387
19601
|
const geometry = new import_three46.BufferGeometry();
|
|
19388
19602
|
geometry.setAttribute("position", new import_three46.Float32BufferAttribute(page.positions.buffer, 3));
|
|
@@ -19393,7 +19607,7 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19393
19607
|
geometry.setIndex(new import_three46.Uint32BufferAttribute(page.indices.buffer, 1));
|
|
19394
19608
|
geometry.computeBoundingBox();
|
|
19395
19609
|
geometry.computeBoundingSphere();
|
|
19396
|
-
const transparent = page.layer === 2 ?
|
|
19610
|
+
const transparent = page.layer === 2 ? atlases2[page.placements[0].atlas].hasTranslucency : page.layer === 1;
|
|
19397
19611
|
const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
|
|
19398
19612
|
material.side = import_three46.FrontSide;
|
|
19399
19613
|
if (page.layer === 2) {
|
|
@@ -19408,7 +19622,7 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19408
19622
|
section.blockIndices.set(mesh, page.blockIndices);
|
|
19409
19623
|
const unsubscribe = [];
|
|
19410
19624
|
for (const { atlas: id, x, y } of page.placements) {
|
|
19411
|
-
const atlas =
|
|
19625
|
+
const atlas = atlases2[id];
|
|
19412
19626
|
if (!atlas.hasAnimation) continue;
|
|
19413
19627
|
unsubscribe.push(atlas.subscribe(() => {
|
|
19414
19628
|
context.clearRect(x, y, atlas.image.width, atlas.image.height);
|