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/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,
|
|
@@ -1409,6 +1413,7 @@ var init_AssetParsers = __esm({
|
|
|
1409
1413
|
AssetParser2["IMAGE"] = "image";
|
|
1410
1414
|
AssetParser2["LIST"] = "list";
|
|
1411
1415
|
AssetParser2["JSON"] = "json";
|
|
1416
|
+
AssetParser2["BINARY"] = "binary";
|
|
1412
1417
|
return AssetParser2;
|
|
1413
1418
|
})(AssetParser || {});
|
|
1414
1419
|
}
|
|
@@ -2881,7 +2886,7 @@ var init_parser = __esm({
|
|
|
2881
2886
|
});
|
|
2882
2887
|
|
|
2883
2888
|
// src/assets/source/HostedAssetSource.ts
|
|
2884
|
-
var p3, DEFAULT_OPTIONS, HostedAssetSource;
|
|
2889
|
+
var BINARY_TIMEOUT, p3, DEFAULT_OPTIONS, HostedAssetSource;
|
|
2885
2890
|
var init_HostedAssetSource = __esm({
|
|
2886
2891
|
"src/assets/source/HostedAssetSource.ts"() {
|
|
2887
2892
|
init_AssetSource();
|
|
@@ -2894,6 +2899,7 @@ var init_HostedAssetSource = __esm({
|
|
|
2894
2899
|
init_AssetLoader();
|
|
2895
2900
|
init_parser();
|
|
2896
2901
|
init_merge();
|
|
2902
|
+
BINARY_TIMEOUT = 6e4;
|
|
2897
2903
|
p3 = prefix("HostedAssetSource");
|
|
2898
2904
|
DEFAULT_OPTIONS = {
|
|
2899
2905
|
retryDefaults: true
|
|
@@ -2964,6 +2970,17 @@ var init_HostedAssetSource = __esm({
|
|
|
2964
2970
|
}
|
|
2965
2971
|
};
|
|
2966
2972
|
}
|
|
2973
|
+
static {
|
|
2974
|
+
this.BINARY = {
|
|
2975
|
+
config(request) {
|
|
2976
|
+
request.timeout = BINARY_TIMEOUT;
|
|
2977
|
+
request.responseType = "arraybuffer";
|
|
2978
|
+
},
|
|
2979
|
+
parse(response) {
|
|
2980
|
+
return { data: new Uint8Array(response.data) };
|
|
2981
|
+
}
|
|
2982
|
+
};
|
|
2983
|
+
}
|
|
2967
2984
|
static {
|
|
2968
2985
|
this.PARSER_MAP = /* @__PURE__ */ new Map([
|
|
2969
2986
|
["model" /* MODEL */, _HostedAssetSource.MODEL],
|
|
@@ -2972,7 +2989,8 @@ var init_HostedAssetSource = __esm({
|
|
|
2972
2989
|
["nbt" /* NBT */, _HostedAssetSource.NBT],
|
|
2973
2990
|
["image" /* IMAGE */, _HostedAssetSource.IMAGE],
|
|
2974
2991
|
["list" /* LIST */, _HostedAssetSource.LIST],
|
|
2975
|
-
["json" /* JSON */, _HostedAssetSource.JSON]
|
|
2992
|
+
["json" /* JSON */, _HostedAssetSource.JSON],
|
|
2993
|
+
["binary" /* BINARY */, _HostedAssetSource.BINARY]
|
|
2976
2994
|
]);
|
|
2977
2995
|
}
|
|
2978
2996
|
/** Retries missing assets with the `minecraft` namespace and default root. Other failures reject. */
|
|
@@ -4858,6 +4876,178 @@ var init_Entities = __esm({
|
|
|
4858
4876
|
}
|
|
4859
4877
|
});
|
|
4860
4878
|
|
|
4879
|
+
// src/assets/_fonts/Unihex.ts
|
|
4880
|
+
var Unihex_exports = {};
|
|
4881
|
+
__export(Unihex_exports, {
|
|
4882
|
+
loadUnihex: () => loadUnihex
|
|
4883
|
+
});
|
|
4884
|
+
function readHex(text2, filename, glyphs) {
|
|
4885
|
+
const lines = text2.split("\n");
|
|
4886
|
+
if (lines[lines.length - 1] === "") lines.pop();
|
|
4887
|
+
lines.forEach((line, index) => {
|
|
4888
|
+
const match = /^([0-9A-F]{4,6}):([0-9A-F]+)$/.exec(line);
|
|
4889
|
+
if (!match || ![32, 64, 96, 128].includes(match[2].length)) {
|
|
4890
|
+
throw new Error(`Invalid Unihex record in ${filename} at line ${index + 1}`);
|
|
4891
|
+
}
|
|
4892
|
+
const codepoint = parseInt(match[1], 16);
|
|
4893
|
+
if (codepoint > 1114111) throw new Error(`Invalid Unihex codepoint in ${filename} at line ${index + 1}`);
|
|
4894
|
+
const bitWidth = match[2].length / 4;
|
|
4895
|
+
const rowLength = bitWidth / 4;
|
|
4896
|
+
const rows = new Uint32Array(GLYPH_HEIGHT);
|
|
4897
|
+
let mask = 0;
|
|
4898
|
+
for (let y = 0; y < GLYPH_HEIGHT; y++) {
|
|
4899
|
+
rows[y] = parseInt(match[2].slice(y * rowLength, (y + 1) * rowLength), 16);
|
|
4900
|
+
mask |= rows[y];
|
|
4901
|
+
}
|
|
4902
|
+
let left = 0, right = bitWidth;
|
|
4903
|
+
if (mask) {
|
|
4904
|
+
while (!(mask >>> bitWidth - left - 1 & 1)) left++;
|
|
4905
|
+
right = bitWidth - 1;
|
|
4906
|
+
while (!(mask >>> bitWidth - right - 1 & 1)) right--;
|
|
4907
|
+
}
|
|
4908
|
+
glyphs.set(codepoint, { rows, bitWidth, left, right });
|
|
4909
|
+
});
|
|
4910
|
+
}
|
|
4911
|
+
async function parseUnihex(key) {
|
|
4912
|
+
try {
|
|
4913
|
+
const asset2 = await AssetLoader.get(key, "binary" /* BINARY */);
|
|
4914
|
+
if (!asset2) throw new Error(`Could not load Unihex archive ${key.toNamespacedString()}`);
|
|
4915
|
+
const records = /* @__PURE__ */ new Map();
|
|
4916
|
+
const reader = new import_zip2.ZipReader(new import_zip2.Uint8ArrayReader(asset2.data), { useWebWorkers: false, useCompressionStream: false });
|
|
4917
|
+
try {
|
|
4918
|
+
for (const entry of await reader.getEntries()) {
|
|
4919
|
+
if (!entry.directory && entry.filename.endsWith(".hex")) {
|
|
4920
|
+
readHex(await entry.getData(new import_zip2.TextWriter(), { checkSignature: true }), entry.filename, records);
|
|
4921
|
+
}
|
|
4922
|
+
}
|
|
4923
|
+
} finally {
|
|
4924
|
+
await reader.close();
|
|
4925
|
+
}
|
|
4926
|
+
const indices = new Int32Array(1114112).fill(-1);
|
|
4927
|
+
const rows = new Uint32Array(records.size * GLYPH_HEIGHT), metrics = new Uint8Array(records.size * 3);
|
|
4928
|
+
let index = 0;
|
|
4929
|
+
for (const [codepoint, record] of records) {
|
|
4930
|
+
indices[codepoint] = index;
|
|
4931
|
+
rows.set(record.rows, index * GLYPH_HEIGHT);
|
|
4932
|
+
metrics.set([record.bitWidth, record.left, record.right], index * 3);
|
|
4933
|
+
index++;
|
|
4934
|
+
}
|
|
4935
|
+
return { indices, rows, metrics };
|
|
4936
|
+
} catch (error) {
|
|
4937
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
|
|
4938
|
+
return void 0;
|
|
4939
|
+
}
|
|
4940
|
+
}
|
|
4941
|
+
async function loadUnihex(provider, fontKey, characters) {
|
|
4942
|
+
const origin = new AssetKey(DEFAULT_NAMESPACE, "", void 0, void 0, "assets", "", fontKey.root);
|
|
4943
|
+
const key = AssetKey.parse("font", provider.hex_file, origin);
|
|
4944
|
+
key.assetType = void 0;
|
|
4945
|
+
const glyphs = /* @__PURE__ */ new Map();
|
|
4946
|
+
let overrides;
|
|
4947
|
+
try {
|
|
4948
|
+
overrides = (provider.size_overrides ?? []).map((override) => {
|
|
4949
|
+
const from = override.from.codePointAt(0), to = override.to.codePointAt(0);
|
|
4950
|
+
if ([...override.from].length !== 1 || [...override.to].length !== 1 || from >= to || !Number.isInteger(override.left) || !Number.isInteger(override.right) || override.right < override.left) {
|
|
4951
|
+
throw new Error(`Invalid Unihex size override in font ${fontKey.toNamespacedString()}`);
|
|
4952
|
+
}
|
|
4953
|
+
return { ...override, from, to };
|
|
4954
|
+
});
|
|
4955
|
+
} catch (error) {
|
|
4956
|
+
console.warn(`Could not load Unihex file ${key.toNamespacedString()}`, error);
|
|
4957
|
+
return glyphs;
|
|
4958
|
+
}
|
|
4959
|
+
const file = await Caching.unihexCache.get(key.serialize(), () => parseUnihex(key));
|
|
4960
|
+
if (!file) return glyphs;
|
|
4961
|
+
let atlas = atlases.get(provider);
|
|
4962
|
+
if (!atlas) {
|
|
4963
|
+
atlas = new UnihexAtlas();
|
|
4964
|
+
atlases.set(provider, atlas);
|
|
4965
|
+
}
|
|
4966
|
+
for (const character of characters) {
|
|
4967
|
+
const codepoint = character.codePointAt(0), index = file.indices[codepoint];
|
|
4968
|
+
if (index < 0) continue;
|
|
4969
|
+
const record = {
|
|
4970
|
+
rows: file.rows.subarray(index * GLYPH_HEIGHT, (index + 1) * GLYPH_HEIGHT),
|
|
4971
|
+
bitWidth: file.metrics[index * 3],
|
|
4972
|
+
left: file.metrics[index * 3 + 1],
|
|
4973
|
+
right: file.metrics[index * 3 + 2]
|
|
4974
|
+
};
|
|
4975
|
+
const override = overrides.find((range) => codepoint >= range.from && codepoint <= range.to);
|
|
4976
|
+
if (override) {
|
|
4977
|
+
record.left = override.left;
|
|
4978
|
+
record.right = override.right;
|
|
4979
|
+
}
|
|
4980
|
+
const width = record.right - record.left + 1;
|
|
4981
|
+
let rendered;
|
|
4982
|
+
const render = () => rendered ??= atlas.draw(record);
|
|
4983
|
+
glyphs.set(character, {
|
|
4984
|
+
get image() {
|
|
4985
|
+
return render().image;
|
|
4986
|
+
},
|
|
4987
|
+
get x() {
|
|
4988
|
+
return render().x;
|
|
4989
|
+
},
|
|
4990
|
+
get y() {
|
|
4991
|
+
return render().y;
|
|
4992
|
+
},
|
|
4993
|
+
width,
|
|
4994
|
+
height: GLYPH_HEIGHT,
|
|
4995
|
+
scale: 0.5,
|
|
4996
|
+
ascent: 7,
|
|
4997
|
+
advance: Math.floor(width / 2) + 1,
|
|
4998
|
+
boldOffset: 0.5,
|
|
4999
|
+
shadowOffset: 0.5
|
|
5000
|
+
});
|
|
5001
|
+
}
|
|
5002
|
+
return glyphs;
|
|
5003
|
+
}
|
|
5004
|
+
var import_zip2, ATLAS_SIZE, GLYPH_HEIGHT, UnihexAtlas, atlases;
|
|
5005
|
+
var init_Unihex = __esm({
|
|
5006
|
+
"src/assets/_fonts/Unihex.ts"() {
|
|
5007
|
+
import_zip2 = require("@zip.js/zip.js");
|
|
5008
|
+
init_AssetKey();
|
|
5009
|
+
init_AssetLoader();
|
|
5010
|
+
init_Assets();
|
|
5011
|
+
init_Caching();
|
|
5012
|
+
init_AssetParsers();
|
|
5013
|
+
init_CanvasCompat();
|
|
5014
|
+
ATLAS_SIZE = 512;
|
|
5015
|
+
GLYPH_HEIGHT = 16;
|
|
5016
|
+
UnihexAtlas = class {
|
|
5017
|
+
constructor() {
|
|
5018
|
+
this.x = 0;
|
|
5019
|
+
this.y = 0;
|
|
5020
|
+
}
|
|
5021
|
+
draw(glyph) {
|
|
5022
|
+
const width = glyph.right - glyph.left + 1;
|
|
5023
|
+
if (this.image && this.x + width > this.image.width) {
|
|
5024
|
+
this.x = 0;
|
|
5025
|
+
this.y += GLYPH_HEIGHT;
|
|
5026
|
+
}
|
|
5027
|
+
if (!this.image || this.y + GLYPH_HEIGHT > this.image.height || width > this.image.width) {
|
|
5028
|
+
this.image = createCanvas2(Math.max(ATLAS_SIZE, width), ATLAS_SIZE);
|
|
5029
|
+
this.x = 0;
|
|
5030
|
+
this.y = 0;
|
|
5031
|
+
}
|
|
5032
|
+
const context = this.image.getContext("2d");
|
|
5033
|
+
const pixels = context.createImageData(width, GLYPH_HEIGHT);
|
|
5034
|
+
for (let y = 0; y < GLYPH_HEIGHT; y++) {
|
|
5035
|
+
for (let x = 0; x < width; x++) {
|
|
5036
|
+
const column = glyph.left + x;
|
|
5037
|
+
if (column < 0 || column >= glyph.bitWidth || !(glyph.rows[y] >>> glyph.bitWidth - column - 1 & 1)) continue;
|
|
5038
|
+
pixels.data.fill(255, (y * width + x) * 4, (y * width + x + 1) * 4);
|
|
5039
|
+
}
|
|
5040
|
+
}
|
|
5041
|
+
const result = { image: this.image, x: this.x, y: this.y };
|
|
5042
|
+
context.putImageData(pixels, this.x, this.y);
|
|
5043
|
+
this.x += width;
|
|
5044
|
+
return result;
|
|
5045
|
+
}
|
|
5046
|
+
};
|
|
5047
|
+
atlases = /* @__PURE__ */ new WeakMap();
|
|
5048
|
+
}
|
|
5049
|
+
});
|
|
5050
|
+
|
|
4861
5051
|
// src/assets/Fonts.ts
|
|
4862
5052
|
var Fonts;
|
|
4863
5053
|
var init_Fonts = __esm({
|
|
@@ -4868,7 +5058,7 @@ var init_Fonts = __esm({
|
|
|
4868
5058
|
init_ModelTextures();
|
|
4869
5059
|
init_Caching();
|
|
4870
5060
|
Fonts = class {
|
|
4871
|
-
/** Combines font definitions in source-priority order.
|
|
5061
|
+
/** Combines font definitions in source-priority order. TrueType providers are skipped. */
|
|
4872
5062
|
static async get(key = "minecraft:default") {
|
|
4873
5063
|
const fontKey = typeof key === "string" ? AssetKey.parse("font", key) : key;
|
|
4874
5064
|
return await Caching.fontCache.get(fontKey.serialize(), () => this.load(fontKey, []));
|
|
@@ -4884,6 +5074,7 @@ var init_Fonts = __esm({
|
|
|
4884
5074
|
const stack = await AssetLoader.getAll(key, "json" /* JSON */);
|
|
4885
5075
|
if (stack.length === 0) throw new Error(`Could not load font ${key.toNamespacedString()}`);
|
|
4886
5076
|
const glyphs = /* @__PURE__ */ new Map();
|
|
5077
|
+
const providers = [];
|
|
4887
5078
|
for (const asset2 of stack) {
|
|
4888
5079
|
for (const provider of asset2.providers) {
|
|
4889
5080
|
if (provider.filter?.uniform || provider.filter?.jp) continue;
|
|
@@ -4902,17 +5093,43 @@ var init_Fonts = __esm({
|
|
|
4902
5093
|
break;
|
|
4903
5094
|
case "reference":
|
|
4904
5095
|
case "minecraft:reference":
|
|
4905
|
-
|
|
5096
|
+
const reference = await this.load(this.relatedKey("font", provider.id, key), [...parents, serialized]);
|
|
5097
|
+
if (reference.resolve) {
|
|
5098
|
+
providers.push(async (characters) => {
|
|
5099
|
+
await reference.resolve(characters);
|
|
5100
|
+
return reference.glyphs;
|
|
5101
|
+
});
|
|
5102
|
+
continue;
|
|
5103
|
+
}
|
|
5104
|
+
provided = reference.glyphs;
|
|
4906
5105
|
break;
|
|
5106
|
+
case "unihex":
|
|
5107
|
+
case "minecraft:unihex":
|
|
5108
|
+
providers.push(async (characters) => (await Promise.resolve().then(() => (init_Unihex(), Unihex_exports))).loadUnihex(provider, key, characters));
|
|
5109
|
+
continue;
|
|
4907
5110
|
default:
|
|
4908
5111
|
continue;
|
|
4909
5112
|
}
|
|
4910
|
-
for (const [character, glyph] of provided) {
|
|
5113
|
+
if (providers.every((provider2) => provider2 instanceof Map)) for (const [character, glyph] of provided) {
|
|
4911
5114
|
if (character !== "\0" && !glyphs.has(character)) glyphs.set(character, glyph);
|
|
4912
5115
|
}
|
|
5116
|
+
providers.push(provided);
|
|
5117
|
+
}
|
|
5118
|
+
}
|
|
5119
|
+
return { glyphs, resolve: providers.every((provider) => provider instanceof Map) ? void 0 : async (characters) => {
|
|
5120
|
+
const remaining = new Set([...characters].filter((character) => character !== "\0" && character !== "\n" && character !== "\r" && !glyphs.has(character)));
|
|
5121
|
+
for (const provider of providers) {
|
|
5122
|
+
if (!remaining.size) break;
|
|
5123
|
+
const provided = provider instanceof Map ? provider : await provider([...remaining].join(""));
|
|
5124
|
+
for (const character of remaining) {
|
|
5125
|
+
const glyph = provided.get(character);
|
|
5126
|
+
if (glyph) {
|
|
5127
|
+
glyphs.set(character, glyph);
|
|
5128
|
+
remaining.delete(character);
|
|
5129
|
+
}
|
|
5130
|
+
}
|
|
4913
5131
|
}
|
|
4914
|
-
}
|
|
4915
|
-
return { glyphs };
|
|
5132
|
+
} };
|
|
4916
5133
|
}
|
|
4917
5134
|
static async bitmap(provider, fontKey) {
|
|
4918
5135
|
const rows = provider.chars.map((row) => [...row]);
|
|
@@ -8121,6 +8338,7 @@ async function layoutGuiText(text2, options = {}) {
|
|
|
8121
8338
|
}
|
|
8122
8339
|
const font = await Fonts.get(options.font);
|
|
8123
8340
|
const runs = typeof text2 === "string" ? [{ text: text2 }] : text2;
|
|
8341
|
+
await font.resolve?.(runs.map((run) => run.text).join(""));
|
|
8124
8342
|
const glyphs = [], lineWidths = [];
|
|
8125
8343
|
let line = [], width = 0;
|
|
8126
8344
|
let trailingNewline = false;
|
|
@@ -8147,7 +8365,7 @@ async function layoutGuiText(text2, options = {}) {
|
|
|
8147
8365
|
continue;
|
|
8148
8366
|
}
|
|
8149
8367
|
const glyph = font.glyphs.get(character);
|
|
8150
|
-
const advance = (glyph?.advance ?? 6) + (style.bold ? 1 : 0);
|
|
8368
|
+
const advance = (glyph?.advance ?? 6) + (style.bold ? glyph?.boldOffset ?? 1 : 0);
|
|
8151
8369
|
line.push({ character, glyph, advance, style, x: 0, y: 0 });
|
|
8152
8370
|
width += advance;
|
|
8153
8371
|
while (width > maxWidth && line.length > 1) {
|
|
@@ -8175,7 +8393,7 @@ function createGuiTextGeometry(layout, shadow = true) {
|
|
|
8175
8393
|
batches.push(batch);
|
|
8176
8394
|
}
|
|
8177
8395
|
const color2 = new import_three20.Color(isShadow ? (style.color & 16579836) >> 2 : style.color);
|
|
8178
|
-
const offset = isShadow ? 1 : 0;
|
|
8396
|
+
const offset = isShadow ? glyph?.shadowOffset ?? 1 : 0;
|
|
8179
8397
|
const top = glyph ? 7 - glyph.ascent : 0;
|
|
8180
8398
|
const height = glyph ? glyph.height * glyph.scale : 8;
|
|
8181
8399
|
const width = glyph ? glyph.width * glyph.scale : 5;
|
|
@@ -8205,7 +8423,7 @@ function createGuiTextGeometry(layout, shadow = true) {
|
|
|
8205
8423
|
for (let i = 0; i < 4; i++) batch.colors.push(color2.r, color2.g, color2.b);
|
|
8206
8424
|
batch.indices.push(base, base + 2, base + 1, base + 2, base + 3, base + 1);
|
|
8207
8425
|
};
|
|
8208
|
-
for (const boldOffset of style.bold ? [0, 1] : [0]) {
|
|
8426
|
+
for (const boldOffset of style.bold ? [0, glyph?.boldOffset ?? 1] : [0]) {
|
|
8209
8427
|
if (glyph) quad(0, top, width, top + height, boldOffset);
|
|
8210
8428
|
else {
|
|
8211
8429
|
quad(0, 0, 5, 1, boldOffset);
|
|
@@ -19021,7 +19239,7 @@ var LIGHT_SAMPLE_OFFSETS = [0, 1, -1, 324, -324, 18, -18];
|
|
|
19021
19239
|
|
|
19022
19240
|
// src/world/SectionGeometry.ts
|
|
19023
19241
|
function buildSectionGeometry(input) {
|
|
19024
|
-
const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;
|
|
19242
|
+
const { count, indices, templates, cullMasks, templateData, atlases: atlases2, maxAtlasSize, fluids, light, ambientLight, ambientOcclusion, biomeTints } = input;
|
|
19025
19243
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
19026
19244
|
if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError("Section entry count exceeds its arrays");
|
|
19027
19245
|
if (biomeTints && biomeTints.length !== count * 3) throw new RangeError("Section biome tints must contain RGB for each placement");
|
|
@@ -19056,8 +19274,8 @@ function buildSectionGeometry(input) {
|
|
|
19056
19274
|
const locations = /* @__PURE__ */ new Map();
|
|
19057
19275
|
for (const [layer, layerAtlases] of [...visibleAtlases].sort(([a], [b]) => a - b)) {
|
|
19058
19276
|
const firstPage = pages.length;
|
|
19059
|
-
for (const atlas of [...layerAtlases].sort((a, b) => Number(
|
|
19060
|
-
const { width, height, animated } =
|
|
19277
|
+
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))) {
|
|
19278
|
+
const { width, height, animated } = atlases2[atlas];
|
|
19061
19279
|
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
19062
19280
|
let selected = -1;
|
|
19063
19281
|
for (let i = firstPage; !animated && i < pages.length; i++) {
|
|
@@ -19100,7 +19318,7 @@ function buildSectionGeometry(input) {
|
|
|
19100
19318
|
});
|
|
19101
19319
|
if (!quads.sprites.length) continue;
|
|
19102
19320
|
if (!fluidPages.has(fluid)) {
|
|
19103
|
-
const { width, height } =
|
|
19321
|
+
const { width, height } = atlases2[data.atlas];
|
|
19104
19322
|
if (width > maxAtlasSize || height > maxAtlasSize) throw new RangeError("Model atlas exceeds the section atlas size limit");
|
|
19105
19323
|
fluidPages.set(fluid, {
|
|
19106
19324
|
layer: 2,
|
|
@@ -19118,7 +19336,7 @@ function buildSectionGeometry(input) {
|
|
|
19118
19336
|
const tint = fluid === "water" && fluids.waterTints ? fluids.waterTints.subarray(tintIndex, tintIndex + 3) : data.tint;
|
|
19119
19337
|
fluidPages.get(fluid).fluids.push({ quads, x, y, z, data, tint });
|
|
19120
19338
|
}
|
|
19121
|
-
pages.push(...[...fluidPages.values()].sort((a, b) => Number(
|
|
19339
|
+
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));
|
|
19122
19340
|
}
|
|
19123
19341
|
return pages.map((page) => {
|
|
19124
19342
|
let faces = page.fluids.reduce((sum, fluid) => sum + fluid.quads.sprites.length, 0);
|
|
@@ -19135,7 +19353,7 @@ function buildSectionGeometry(input) {
|
|
|
19135
19353
|
let vertex = 0, indexOffset = 0;
|
|
19136
19354
|
for (const entry of page.entries) {
|
|
19137
19355
|
const template = templateData[templates[entry]];
|
|
19138
|
-
const atlas =
|
|
19356
|
+
const atlas = atlases2[template.atlas];
|
|
19139
19357
|
const placement = locations.get(template.atlas);
|
|
19140
19358
|
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
19141
19359
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
@@ -19174,7 +19392,7 @@ function buildSectionGeometry(input) {
|
|
|
19174
19392
|
}
|
|
19175
19393
|
}
|
|
19176
19394
|
for (const { quads, x, y, z, data, tint } of page.fluids) {
|
|
19177
|
-
const atlas =
|
|
19395
|
+
const atlas = atlases2[data.atlas];
|
|
19178
19396
|
const placement = page.placements[0];
|
|
19179
19397
|
const mapU = (u) => (placement.x + u * atlas.width) / page.width;
|
|
19180
19398
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
@@ -19276,7 +19494,7 @@ var templateCache = /* @__PURE__ */ new WeakMap();
|
|
|
19276
19494
|
var WATER_TINT = new import_three46.Color(4159204).toArray();
|
|
19277
19495
|
function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
19278
19496
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
19279
|
-
const
|
|
19497
|
+
const atlases2 = [];
|
|
19280
19498
|
const atlasIds = /* @__PURE__ */ new Map();
|
|
19281
19499
|
const templateIds = /* @__PURE__ */ new Map();
|
|
19282
19500
|
const input = {
|
|
@@ -19299,9 +19517,9 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19299
19517
|
if (id === void 0) {
|
|
19300
19518
|
let atlas = atlasIds.get(template.atlas);
|
|
19301
19519
|
if (atlas === void 0) {
|
|
19302
|
-
atlas =
|
|
19520
|
+
atlas = atlases2.length;
|
|
19303
19521
|
atlasIds.set(template.atlas, atlas);
|
|
19304
|
-
|
|
19522
|
+
atlases2.push(template.atlas);
|
|
19305
19523
|
input.atlases.push({ width: template.atlas.image.width, height: template.atlas.image.height, animated: template.atlas.hasAnimation });
|
|
19306
19524
|
}
|
|
19307
19525
|
let data = templateCache.get(template);
|
|
@@ -19360,9 +19578,9 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19360
19578
|
if (!atlas) continue;
|
|
19361
19579
|
let id = atlasIds.get(atlas);
|
|
19362
19580
|
if (id === void 0) {
|
|
19363
|
-
id =
|
|
19581
|
+
id = atlases2.length;
|
|
19364
19582
|
atlasIds.set(atlas, id);
|
|
19365
|
-
|
|
19583
|
+
atlases2.push(atlas);
|
|
19366
19584
|
input.atlases.push({ width: atlas.image.width, height: atlas.image.height, animated: atlas.hasAnimation });
|
|
19367
19585
|
}
|
|
19368
19586
|
input.fluids[kind] = {
|
|
@@ -19373,7 +19591,7 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
19373
19591
|
};
|
|
19374
19592
|
}
|
|
19375
19593
|
}
|
|
19376
|
-
return { input, atlases };
|
|
19594
|
+
return { input, atlases: atlases2 };
|
|
19377
19595
|
}
|
|
19378
19596
|
var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
19379
19597
|
constructor() {
|
|
@@ -19388,23 +19606,23 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19388
19606
|
}
|
|
19389
19607
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
19390
19608
|
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
19391
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19392
|
-
return this.fromPages(buildSectionGeometry(input),
|
|
19609
|
+
const { input, atlases: atlases2 } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19610
|
+
return this.fromPages(buildSectionGeometry(input), atlases2);
|
|
19393
19611
|
}
|
|
19394
19612
|
/** Builds section-local meshes in a browser worker when available, with synchronous fallback. */
|
|
19395
19613
|
static async buildAsync(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
19396
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19614
|
+
const { input, atlases: atlases2 } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
19397
19615
|
const worker = SectionWorker.shared();
|
|
19398
19616
|
const pages = worker ? await worker.build(input).catch(() => buildSectionGeometry(input)) : buildSectionGeometry(input);
|
|
19399
|
-
return this.fromPages(pages,
|
|
19617
|
+
return this.fromPages(pages, atlases2);
|
|
19400
19618
|
}
|
|
19401
|
-
static fromPages(pages,
|
|
19619
|
+
static fromPages(pages, atlases2) {
|
|
19402
19620
|
const section = new _SectionMesh();
|
|
19403
19621
|
for (const page of pages) {
|
|
19404
19622
|
const canvas = createCanvas2(page.width, page.height);
|
|
19405
19623
|
const context = canvas.getContext("2d");
|
|
19406
19624
|
for (const { atlas, x, y } of page.placements) {
|
|
19407
|
-
context.drawImage(
|
|
19625
|
+
context.drawImage(atlases2[atlas].image.canvas, x, y);
|
|
19408
19626
|
}
|
|
19409
19627
|
const geometry = new import_three46.BufferGeometry();
|
|
19410
19628
|
geometry.setAttribute("position", new import_three46.Float32BufferAttribute(page.positions.buffer, 3));
|
|
@@ -19415,7 +19633,7 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19415
19633
|
geometry.setIndex(new import_three46.Uint32BufferAttribute(page.indices.buffer, 1));
|
|
19416
19634
|
geometry.computeBoundingBox();
|
|
19417
19635
|
geometry.computeBoundingSphere();
|
|
19418
|
-
const transparent = page.layer === 2 ?
|
|
19636
|
+
const transparent = page.layer === 2 ? atlases2[page.placements[0].atlas].hasTranslucency : page.layer === 1;
|
|
19419
19637
|
const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
|
|
19420
19638
|
material.side = import_three46.FrontSide;
|
|
19421
19639
|
if (page.layer === 2) {
|
|
@@ -19430,7 +19648,7 @@ var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
|
19430
19648
|
section.blockIndices.set(mesh, page.blockIndices);
|
|
19431
19649
|
const unsubscribe = [];
|
|
19432
19650
|
for (const { atlas: id, x, y } of page.placements) {
|
|
19433
|
-
const atlas =
|
|
19651
|
+
const atlas = atlases2[id];
|
|
19434
19652
|
if (!atlas.hasAnimation) continue;
|
|
19435
19653
|
unsubscribe.push(atlas.subscribe(() => {
|
|
19436
19654
|
context.clearRect(x, y, atlas.image.width, atlas.image.height);
|