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.
@@ -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. Unsupported Unihex and TrueType providers are skipped. */
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
- provided = (await this.load(this.relatedKey("font", provider.id, key), [...parents, serialized])).glyphs;
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(atlases[a].animated) - Number(atlases[b].animated) || (atlases[a].animated ? a - b : atlases[b].height - atlases[a].height))) {
19060
- const { width, height, animated } = atlases[atlas];
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 } = atlases[data.atlas];
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(atlases[a.placements[0].atlas].animated) - Number(atlases[b.placements[0].atlas].animated) || a.placements[0].atlas - b.placements[0].atlas));
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 = atlases[template.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 = atlases[data.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 atlases = [];
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 = atlases.length;
19520
+ atlas = atlases2.length;
19303
19521
  atlasIds.set(template.atlas, atlas);
19304
- atlases.push(template.atlas);
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 = atlases.length;
19581
+ id = atlases2.length;
19364
19582
  atlasIds.set(atlas, id);
19365
- atlases.push(atlas);
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), atlases);
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, atlases);
19617
+ return this.fromPages(pages, atlases2);
19400
19618
  }
19401
- static fromPages(pages, atlases) {
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(atlases[atlas].image.canvas, x, y);
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 ? atlases[page.placements[0].atlas].hasTranslucency : page.layer === 1;
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 = atlases[id];
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);