minerender 2.1.0-alpha.3 → 2.1.0-alpha.31

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.
@@ -28,14 +28,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  mod
29
29
  ));
30
30
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
- var __decorateClass = (decorators, target, key, kind) => {
32
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
33
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
34
- if (decorator = decorators[i])
35
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
36
- if (kind && result) __defProp(target, key, result);
37
- return result;
38
- };
39
31
 
40
32
  // ../../node_modules/ts-deepmerge/dist/index.js
41
33
  var require_dist = __commonJS({
@@ -45,8 +37,8 @@ var require_dist = __commonJS({
45
37
  __assign = Object.assign || function(t) {
46
38
  for (var s, i = 1, n = arguments.length; i < n; i++) {
47
39
  s = arguments[i];
48
- for (var p13 in s) if (Object.prototype.hasOwnProperty.call(s, p13))
49
- t[p13] = s[p13];
40
+ for (var p12 in s) if (Object.prototype.hasOwnProperty.call(s, p12))
41
+ t[p12] = s[p12];
50
42
  }
51
43
  return t;
52
44
  };
@@ -90,7 +82,7 @@ var require_dist = __commonJS({
90
82
  return false;
91
83
  };
92
84
  var PROTECTED_KEYS = ["__proto__"];
93
- var merge11 = function() {
85
+ var merge10 = function() {
94
86
  var objects = [];
95
87
  for (var _i = 0; _i < arguments.length; _i++) {
96
88
  objects[_i] = arguments[_i];
@@ -101,9 +93,9 @@ var require_dist = __commonJS({
101
93
  return;
102
94
  }
103
95
  if (Array.isArray(result[key]) && Array.isArray(current[key])) {
104
- result[key] = merge11.options.mergeArrays ? Array.from(new Set(result[key].concat(current[key]))) : current[key];
96
+ result[key] = merge10.options.mergeArrays ? Array.from(new Set(result[key].concat(current[key]))) : current[key];
105
97
  } else if (isObject(result[key]) && isObject(current[key])) {
106
- result[key] = merge11(result[key], current[key]);
98
+ result[key] = merge10(result[key], current[key]);
107
99
  } else {
108
100
  result[key] = current[key];
109
101
  }
@@ -114,18 +106,18 @@ var require_dist = __commonJS({
114
106
  var defaultOptions = {
115
107
  mergeArrays: true
116
108
  };
117
- merge11.options = defaultOptions;
118
- merge11.withOptions = function(options) {
109
+ merge10.options = defaultOptions;
110
+ merge10.withOptions = function(options) {
119
111
  var objects = [];
120
112
  for (var _i = 1; _i < arguments.length; _i++) {
121
113
  objects[_i - 1] = arguments[_i];
122
114
  }
123
- merge11.options = __assign({ mergeArrays: true }, options);
124
- var result = merge11.apply(void 0, __spreadArray([], __read(objects), false));
125
- merge11.options = defaultOptions;
115
+ merge10.options = __assign({ mergeArrays: true }, options);
116
+ var result = merge10.apply(void 0, __spreadArray([], __read(objects), false));
117
+ merge10.options = defaultOptions;
126
118
  return result;
127
119
  };
128
- exports2.default = merge11;
120
+ exports2.default = merge10;
129
121
  }
130
122
  });
131
123
 
@@ -135,6 +127,7 @@ __export(index_node_exports, {
135
127
  AXES: () => AXES,
136
128
  ArchiveAssetSource: () => ArchiveAssetSource,
137
129
  AssetKey: () => AssetKey,
130
+ AssetLoadError: () => AssetLoadError,
138
131
  AssetLoader: () => AssetLoader,
139
132
  AssetParser: () => AssetParser,
140
133
  AssetSource: () => AssetSource,
@@ -144,9 +137,9 @@ __export(index_node_exports, {
144
137
  BUILTIN_GENERATED: () => BUILTIN_GENERATED,
145
138
  BasicAssetKey: () => BasicAssetKey,
146
139
  BatchedExecutor: () => BatchedExecutor,
147
- BlockEntityModels: () => BlockEntityModels,
148
140
  BlockObject: () => BlockObject,
149
141
  BlockStates: () => BlockStates,
142
+ BlockTints: () => BlockTints,
150
143
  BrowserArchiveProxy: () => BrowserArchiveProxy,
151
144
  CUBE_FACES: () => CUBE_FACES,
152
145
  Caching: () => Caching,
@@ -161,8 +154,8 @@ __export(index_node_exports, {
161
154
  DISPLAY_POSITIONS: () => DISPLAY_POSITIONS,
162
155
  DefaultBlockStates: () => DefaultBlockStates,
163
156
  DisplayPosition: () => DisplayPosition,
157
+ DisplayTransforms: () => DisplayTransforms,
164
158
  Entities: () => Entities,
165
- EntityModels: () => EntityModels,
166
159
  EntityObject: () => EntityObject,
167
160
  Env: () => Env,
168
161
  Geometries: () => Geometries,
@@ -192,6 +185,7 @@ __export(index_node_exports, {
192
185
  OrbitControls: () => OrbitControls,
193
186
  PersistentCache: () => PersistentCache,
194
187
  Renderer: () => Renderer,
188
+ RequestError: () => RequestError,
195
189
  Requests: () => Requests,
196
190
  SKIN_PARTS: () => SKIN_PARTS,
197
191
  SceneInspector: () => SceneInspector,
@@ -199,8 +193,10 @@ __export(index_node_exports, {
199
193
  SceneStats: () => SceneStats,
200
194
  SceneStatsDisplay: () => SceneStatsDisplay,
201
195
  SchematicParser: () => SchematicParser,
196
+ SkinImage: () => SkinImage,
202
197
  SkinObject: () => SkinObject,
203
198
  SkinPart: () => SkinPart,
199
+ SkinTextures: () => SkinTextures,
204
200
  Skins: () => Skins,
205
201
  StructureParser: () => StructureParser,
206
202
  TextureAtlas: () => TextureAtlas,
@@ -215,10 +211,10 @@ __export(index_node_exports, {
215
211
  addWireframeToObject: () => addWireframeToObject,
216
212
  applyElementRotation: () => applyElementRotation,
217
213
  applyGenericRotation: () => applyGenericRotation,
218
- applyModelPartRotation: () => applyModelPartRotation,
219
214
  axisToVec3: () => axisToVec3,
220
215
  base64decode: () => base64decode,
221
216
  base64encode: () => base64encode,
217
+ capeTextureSizes: () => capeTextureSizes,
222
218
  captureException: () => captureException,
223
219
  changeEvent: () => changeEvent,
224
220
  clampRotationDegrees: () => clampRotationDegrees,
@@ -302,25 +298,29 @@ var Env = class {
302
298
  };
303
299
 
304
300
  // src/cache/PersistentCache.ts
305
- var _PersistentCache = class _PersistentCache {
301
+ var PersistentCache = class _PersistentCache {
306
302
  constructor(backing) {
307
303
  this.backing = backing;
308
304
  }
305
+ static {
306
+ /** Bump to invalidate every persisted entry. */
307
+ this.VERSION = 2;
308
+ }
309
309
  static open(name) {
310
310
  return Env.provider.openCache(name, _PersistentCache.VERSION);
311
311
  }
312
+ /** Loads a missing entry and stores only non-nullish results. */
312
313
  async getOrLoad(key, loader) {
313
314
  let v = await this.get(key);
314
315
  if (typeof v === "undefined" || v === null) {
315
316
  v = await loader(key);
316
- await this.put(key, v);
317
+ if (typeof v !== "undefined" && v !== null) {
318
+ await this.put(key, v);
319
+ }
317
320
  }
318
321
  return v;
319
322
  }
320
323
  };
321
- /** Bump to invalidate every persisted entry. */
322
- _PersistentCache.VERSION = 1;
323
- var PersistentCache = _PersistentCache;
324
324
 
325
325
  // src/env/node/NodeCache.ts
326
326
  var NodeCache = class extends PersistentCache {
@@ -398,7 +398,7 @@ registerNodeEnv();
398
398
  // src/Axis.ts
399
399
  var import_three = require("three");
400
400
  var Axis = /* @__PURE__ */ ((Axis3) => {
401
- Axis3["X"] = "X";
401
+ Axis3["X"] = "x";
402
402
  Axis3["Y"] = "y";
403
403
  Axis3["Z"] = "z";
404
404
  return Axis3;
@@ -406,7 +406,7 @@ var Axis = /* @__PURE__ */ ((Axis3) => {
406
406
  var AXES = Object.values(Axis);
407
407
  function axisToVec3(axis) {
408
408
  switch (axis) {
409
- case "X" /* X */:
409
+ case "x" /* X */:
410
410
  return new import_three.Vector3(1, 0, 0);
411
411
  case "y" /* Y */:
412
412
  return new import_three.Vector3(0, 1, 0);
@@ -494,8 +494,7 @@ function serializeImageKey(key) {
494
494
  return md5(key.src);
495
495
  }
496
496
  function serializeBoxGeometryKey(key) {
497
- var _a;
498
- return md5([key.width, key.height, key.depth, (_a = key.uv) == null ? void 0 : _a.join(":")].join("_"));
497
+ return md5([key.width, key.height, key.depth, key.uv?.join(":")].join("_"));
499
498
  }
500
499
  function serializeTextureKey(key) {
501
500
  return md5([key.src, key.format, key.rotation].join("$"));
@@ -510,7 +509,67 @@ function serializeMeshKey(key) {
510
509
  // src/cache/Caching.ts
511
510
  var import_loading_cache = require("@inventivetalent/loading-cache");
512
511
  var import_time = require("@inventivetalent/time");
513
- var Caching = class {
512
+ var Caching = class _Caching {
513
+ static {
514
+ this.rawImageCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(5)).buildAsync();
515
+ }
516
+ static {
517
+ this.imageDataCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
518
+ }
519
+ static {
520
+ this.canvasImageDataCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
521
+ }
522
+ static {
523
+ this.wrappedImageCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
524
+ }
525
+ static {
526
+ this.boxGeometryCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(20)).build();
527
+ }
528
+ static {
529
+ this.textureCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
530
+ }
531
+ static {
532
+ this.materialCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
533
+ }
534
+ static {
535
+ this.boxMeshCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
536
+ }
537
+ static {
538
+ this.textureAssetCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
539
+ }
540
+ static {
541
+ this.textureMetaCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
542
+ }
543
+ static {
544
+ this.rawModelCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
545
+ }
546
+ static {
547
+ this.mergedModelCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
548
+ }
549
+ static {
550
+ this.modelTextureAtlasCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
551
+ }
552
+ static {
553
+ this.blockStateCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
554
+ }
555
+ static {
556
+ this.listAssetCache = _Caching.createAssetCache();
557
+ }
558
+ static {
559
+ this.defaultBlockStatesCache = _Caching.createAssetCache();
560
+ }
561
+ static {
562
+ this.blockTintCache = _Caching.createAssetCache();
563
+ }
564
+ static {
565
+ this.entityModelCache = _Caching.createAssetCache();
566
+ }
567
+ static {
568
+ this.entityTextureCache = _Caching.createAssetCache();
569
+ }
570
+ static createAssetCache() {
571
+ return import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
572
+ }
514
573
  /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */
515
574
  static get all() {
516
575
  return [
@@ -527,7 +586,12 @@ var Caching = class {
527
586
  this.rawModelCache,
528
587
  this.mergedModelCache,
529
588
  this.modelTextureAtlasCache,
530
- this.blockStateCache
589
+ this.blockStateCache,
590
+ this.listAssetCache,
591
+ this.defaultBlockStatesCache,
592
+ this.blockTintCache,
593
+ this.entityModelCache,
594
+ this.entityTextureCache
531
595
  ];
532
596
  }
533
597
  static clear() {
@@ -538,8 +602,8 @@ var Caching = class {
538
602
  /**
539
603
  * Clears every cache and stops its expiry timer.
540
604
  *
541
- * loading-cache reschedules that timer indefinitely, so a Node process will not exit until
542
- * this is called - see {@link shutdown}.
605
+ * Expiry timers are unref'd in Node, so idle processes can exit without this cleanup.
606
+ * Use {@link shutdown} to also stop requests and the shared Ticker.
543
607
  */
544
608
  static end() {
545
609
  for (const cache of this.all) {
@@ -553,20 +617,6 @@ var Caching = class {
553
617
  };
554
618
  }
555
619
  };
556
- Caching.rawImageCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(5)).buildAsync();
557
- Caching.imageDataCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
558
- Caching.canvasImageDataCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
559
- Caching.wrappedImageCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
560
- Caching.boxGeometryCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(20)).build();
561
- Caching.textureCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
562
- Caching.materialCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
563
- Caching.boxMeshCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
564
- Caching.textureAssetCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
565
- Caching.textureMetaCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
566
- Caching.rawModelCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
567
- Caching.mergedModelCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
568
- Caching.modelTextureAtlasCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
569
- Caching.blockStateCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
570
620
 
571
621
  // src/Geometries.ts
572
622
  var Geometries = class _Geometries {
@@ -587,13 +637,14 @@ var Geometries = class _Geometries {
587
637
  };
588
638
 
589
639
  // src/Materials.ts
590
- var import_three6 = require("three");
640
+ var import_three5 = require("three");
591
641
 
592
642
  // src/texture/Textures.ts
593
- var import_three5 = require("three");
643
+ var import_three4 = require("three");
594
644
 
595
645
  // src/texture/TextureLoader.ts
596
- var import_three4 = require("three");
646
+ var import_three3 = require("three");
647
+ var THREE = __toESM(require("three"));
597
648
 
598
649
  // src/canvas/CanvasCompat.ts
599
650
  function createImage(width, height) {
@@ -604,9 +655,7 @@ function createCanvas2(width, height) {
604
655
  }
605
656
 
606
657
  // src/request/Requests.ts
607
- var import_axios = __toESM(require("axios"));
608
658
  var import_jobqu = require("jobqu");
609
- var import_time2 = require("@inventivetalent/time");
610
659
 
611
660
  // src/util/log.ts
612
661
  var Reset = "\x1B[0m";
@@ -616,198 +665,174 @@ function prefix(prefix2) {
616
665
  return `${FgGreen}MR${BgBlack}${prefix2 ?? ""}${Reset}`;
617
666
  }
618
667
 
619
- // src/util/BatchedExecutor.ts
620
- var BatchedExecutor = class {
621
- constructor(interval = 1, batch = 30) {
622
- this.interval = interval;
623
- this.batch = batch;
624
- this.queue = [];
625
- this.task = setInterval(() => this.run());
626
- }
627
- submit(task) {
628
- this.queue.push(task);
629
- }
630
- run() {
631
- for (let i = 0; i < this.batch; i++) {
632
- this.runNext();
633
- }
634
- }
635
- runNext() {
636
- let next = this.queue.shift();
637
- if (next) next();
668
+ // src/request/Requests.ts
669
+ var p = prefix("Requests");
670
+ var RequestError = class extends Error {
671
+ constructor(message, response, cause) {
672
+ super(message);
673
+ this.response = response;
674
+ this.cause = cause;
675
+ this.name = "RequestError";
638
676
  }
639
677
  };
640
-
641
- // src/util/model.ts
642
- var import_three3 = require("three");
643
- function applyElementRotation(rotation, geometry) {
644
- const origin = new import_three3.Vector3(rotation.origin[0], rotation.origin[1], rotation.origin[2]);
645
- geometry.translate(-origin.x, -origin.y, -origin.z);
646
- switch (rotation.axis) {
647
- case "X" /* X */:
648
- geometry.rotateX(toRadians(rotation.angle));
649
- break;
650
- case "y" /* Y */:
651
- geometry.rotateY(toRadians(rotation.angle));
652
- break;
653
- case "z" /* Z */:
654
- geometry.rotateZ(toRadians(rotation.angle));
655
- break;
656
- }
657
- if (rotation.rescale) {
658
- if (Math.abs(rotation.angle) === 22.5) {
659
- const s = 1 / Math.cos(0.39269909262657166);
660
- geometry.scale(s, 1, s);
661
- } else {
662
- const s = 1 / Math.cos(0.7853981852531433);
663
- geometry.scale(s, 1, s);
678
+ async function fetchRequest(config, defaultBaseURL) {
679
+ const { url, baseURL = defaultBaseURL, timeout = 5e3, responseType = "json", signal, ...options } = config;
680
+ const target = baseURL && !/^([a-z][a-z\d+.-]*:|\/\/)/i.test(url) ? `${baseURL.replace(/\/+$/, "")}/${url.replace(/^\/+/, "")}` : url;
681
+ const headers = new Headers(options.headers);
682
+ if (typeof window === "undefined" && !headers.has("User-Agent")) {
683
+ headers.set("User-Agent", "MineRender");
684
+ }
685
+ const attemptSignal = AbortSignal.any([
686
+ ...signal ? [signal] : [],
687
+ ...timeout === 0 ? [] : [AbortSignal.timeout(timeout)]
688
+ ]);
689
+ const request = new Request(target, { ...options, headers, signal: attemptSignal });
690
+ attemptSignal.throwIfAborted();
691
+ try {
692
+ const response = await fetch(request);
693
+ const result = {
694
+ data: void 0,
695
+ status: response.status,
696
+ statusText: response.statusText,
697
+ headers: response.headers,
698
+ url: response.url
699
+ };
700
+ if (!response.ok) {
701
+ await response.body?.cancel().catch(() => {
702
+ });
703
+ throw new RequestError(`Request failed with status ${response.status}`, result);
704
+ }
705
+ const emptyBody = request.method === "HEAD" || response.status === 204 || response.status === 205;
706
+ const data = responseType === "arraybuffer" ? await response.arrayBuffer() : emptyBody || response.body === null ? void 0 : await response.json();
707
+ return { ...result, data };
708
+ } catch (error) {
709
+ attemptSignal.throwIfAborted();
710
+ if (/^https?:/.test(request.url) && request.redirect !== "error" && error instanceof TypeError) {
711
+ throw new RequestError("Network request failed", void 0, error);
664
712
  }
713
+ throw error;
665
714
  }
666
- geometry.translate(origin.x, origin.y, origin.z);
667
- }
668
- function applyModelPartRotation(modelPart, geometry) {
669
- const origin = new import_three3.Vector3(modelPart.pivotX, modelPart.pivotY, modelPart.pivotZ);
670
- geometry.translate(-origin.x, -origin.y, -origin.z);
671
- geometry.rotateX(toRadians(modelPart.pitch));
672
- geometry.rotateY(toRadians(modelPart.yaw));
673
- geometry.rotateZ(toRadians(modelPart.roll));
674
- geometry.translate(origin.x, origin.y, origin.z);
675
715
  }
676
- function applyGenericRotation(axis, rotation, obj) {
677
- switch (axis) {
678
- case "X" /* X */:
679
- obj.rotateOnAxis(new import_three3.Vector3(1, 0, 0), toRadians(rotation));
680
- break;
681
- case "y" /* Y */:
682
- obj.rotateOnAxis(new import_three3.Vector3(0, 1, 0), toRadians(rotation));
683
- break;
684
- case "z" /* Z */:
685
- obj.rotateOnAxis(new import_three3.Vector3(0, 0, 1), toRadians(rotation));
686
- break;
716
+ async function abortable(promise, signal) {
717
+ if (!signal) return promise;
718
+ let abort;
719
+ const cancelled = new Promise((_, reject) => {
720
+ abort = () => reject(signal.reason);
721
+ signal.addEventListener("abort", abort, { once: true });
722
+ if (signal.aborted) abort();
723
+ });
724
+ try {
725
+ return await Promise.race([promise, cancelled]);
726
+ } finally {
727
+ signal.removeEventListener("abort", abort);
687
728
  }
688
729
  }
689
- function addBox3WireframeToObject(box, obj, color = 16777215, w = 2) {
690
- let size = new import_three3.Vector3();
691
- box.getSize(size);
692
- let boxGeo = new import_three3.BoxGeometry(size.x, size.y, size.z, 1, 1, 1);
693
- let wireGeo = new import_three3.EdgesGeometry(boxGeo);
694
- let wireMat = new import_three3.LineBasicMaterial({ color, linewidth: w });
695
- let wireframe = new import_three3.LineSegments(wireGeo, wireMat);
696
- obj.add(wireframe);
697
- let axes = new import_three3.AxesHelper(1);
698
- obj.add(axes);
699
- }
700
- function addWireframeToObject(obj, color = 16777215, w = 2) {
701
- let boxGeo = new import_three3.BoxGeometry(16, 16, 16, 1, 1, 1);
702
- let wireGeo = new import_three3.EdgesGeometry(boxGeo);
703
- let wireMat = new import_three3.LineBasicMaterial({ color, linewidth: w });
704
- let wireframe = new import_three3.LineSegments(wireGeo, wireMat);
705
- obj.add(wireframe);
706
- let axes = new import_three3.AxesHelper(1);
707
- obj.add(axes);
708
- }
709
- function addWireframeToMesh(geo, mesh, color = 16777215, w = 2) {
710
- let wireGeo = new import_three3.EdgesGeometry(geo);
711
- let wireMat = new import_three3.LineBasicMaterial({ color, linewidth: w });
712
- let wireframe = new import_three3.LineSegments(wireGeo, wireMat);
713
- mesh.add(wireframe);
714
- let axes = new import_three3.AxesHelper(1);
715
- mesh.add(axes);
716
- }
717
-
718
- // src/util/performance.ts
719
- function captureException(e, ...extra) {
720
- console.error(e, extra);
721
- }
722
- function timingStart(marker) {
723
- console.time(marker);
724
- }
725
- function timingEnd(marker) {
726
- console.timeEnd(marker);
727
- }
728
-
729
- // src/util/three.ts
730
- function isObject3D(obj) {
731
- return obj.isObject3D;
732
- }
733
- function isMesh(obj) {
734
- return obj.isMesh;
735
- }
736
- function isInstancedMesh(obj) {
737
- return obj.isInstancedMesh;
738
- }
739
- function isPerspectiveCamera(obj) {
740
- return obj.isPerspectiveCamera;
741
- }
742
- function isOrthographicCamera(obj) {
743
- return obj.isOrthographicCamera;
744
- }
745
-
746
- // src/request/Requests.ts
747
- var p = prefix("Requests");
748
- if (typeof window === "undefined") {
749
- import_axios.default.defaults.headers["User-Agent"] = "MineRender";
750
- }
751
- var _Requests = class _Requests {
752
- static genericRequest(request) {
753
- return this.genericQueue.add(request).catch(async (e) => {
754
- console.debug(p, "generic catch", e.code, e);
755
- if (this.shouldRetry(e, request)) {
756
- await sleep(100);
757
- return this.genericRequest(request);
758
- }
759
- throw e;
760
- });
761
- }
762
- static mcAssetRequest(request) {
763
- return this.mcAssetRequestQueue.add(request).catch((e) => {
764
- console.debug(p, "mcAssetRequest catch", e.code, e);
765
- throw e;
766
- });
730
+ var RequestQueue = class {
731
+ constructor() {
732
+ this.pendingRequests = 0;
733
+ this.stopped = new AbortController();
734
+ this.queue = new import_jobqu.JobQueue(
735
+ (request) => fetchRequest(request, this.baseURL),
736
+ { interval: 10, maxPerRun: 1, maxActive: 8 }
737
+ );
767
738
  }
768
- static shouldRetry(e, request) {
769
- if ("code" in e) {
770
- if ("ECONNABORTED" === e.code) {
771
- if ("minerenderRetry" in request) {
772
- if (request["minerenderRetry"] > 0) {
773
- request["minerenderRetry"]--;
774
- return true;
739
+ async request(request) {
740
+ this.pendingRequests++;
741
+ const signal = request.signal;
742
+ try {
743
+ for (let retries = 0; ; retries++) {
744
+ signal?.throwIfAborted();
745
+ try {
746
+ return await abortable(this.queue.add(request), signal);
747
+ } catch (error) {
748
+ console.debug(p, "Request failed", error);
749
+ const delay = this.retryDelay(error, request, retries);
750
+ if (delay === void 0) {
751
+ throw error;
775
752
  }
776
- } else {
777
- request["minerenderRetry"] = 3;
778
- return true;
753
+ await this.waitForRetry(delay, signal);
779
754
  }
780
755
  }
756
+ } finally {
757
+ if (signal?.aborted) {
758
+ this.queue.remove(request);
759
+ }
760
+ this.pendingRequests--;
761
+ }
762
+ }
763
+ retryDelay(error, request, retries) {
764
+ if (this.stopped.signal.aborted || retries >= 3 || (request.method ?? "get").toLowerCase() !== "get" || request.signal?.aborted) {
765
+ return void 0;
766
+ }
767
+ if (error instanceof RequestError) {
768
+ const status = error.response?.status;
769
+ if (status !== void 0 && status !== 408 && status !== 429 && !(status >= 500 && status < 600)) return void 0;
770
+ } else if (!(error instanceof DOMException && error.name === "TimeoutError")) {
771
+ return void 0;
772
+ }
773
+ let delay = 100 * 2 ** retries;
774
+ const retryAfter = error instanceof RequestError ? error.response?.headers.get("Retry-After") : void 0;
775
+ if (retryAfter !== void 0 && retryAfter !== null) {
776
+ const seconds = Number(retryAfter);
777
+ if (!retryAfter.trim() || !Number.isFinite(seconds) || seconds < 0) {
778
+ return void 0;
779
+ }
780
+ delay = Math.max(delay, seconds * 1e3);
781
+ }
782
+ return delay;
783
+ }
784
+ async waitForRetry(delay, signal) {
785
+ let timer;
786
+ const waiting = new Promise((resolve) => {
787
+ timer = setTimeout(resolve, delay);
788
+ });
789
+ try {
790
+ await abortable(waiting, AbortSignal.any([this.stopped.signal, ...signal ? [signal] : []]));
791
+ } finally {
792
+ clearTimeout(timer);
781
793
  }
782
- return false;
794
+ }
795
+ get pendingSize() {
796
+ return this.pendingRequests;
797
+ }
798
+ end() {
799
+ this.queue.end();
800
+ this.stopped.abort(new import_jobqu.JobCancelledError("ended"));
801
+ }
802
+ };
803
+ var Requests = class {
804
+ static {
805
+ this.genericQueue = new RequestQueue();
806
+ }
807
+ static {
808
+ this.mcAssetRequestQueue = new RequestQueue();
809
+ }
810
+ static genericRequest(request) {
811
+ return this.genericQueue.request(request);
812
+ }
813
+ static mcAssetRequest(request) {
814
+ return this.mcAssetRequestQueue.request(request);
783
815
  }
784
816
  static setMcAssetRoot(root) {
785
- this.mcAssetInstance.defaults.baseURL = root;
817
+ this.mcAssetRequestQueue.baseURL = root;
786
818
  }
819
+ /** Counts unsettled calls, including retry delays and requests still running after shutdown. */
787
820
  static get queueSizes() {
788
821
  return {
789
- generic: this.genericQueue.size,
790
- mcAsset: this.mcAssetRequestQueue.size
822
+ generic: this.genericQueue.pendingSize,
823
+ mcAsset: this.mcAssetRequestQueue.pendingSize
791
824
  };
792
825
  }
793
826
  /**
794
- * Stops both queue timers. jobqu reschedules itself indefinitely, so a Node process will not
795
- * exit until this is called - see {@link shutdown}.
827
+ * Permanently stops both queues and rejects waiting, retrying, and future requests.
828
+ * Requests already running can finish. Idle queues hold no timer, so Node can exit without
829
+ * this cleanup. See {@link shutdown}.
796
830
  */
797
831
  static end() {
798
832
  this.genericQueue.end();
799
833
  this.mcAssetRequestQueue.end();
800
834
  }
801
835
  };
802
- _Requests.axiosInstance = import_axios.default.create({
803
- timeout: 5e3
804
- });
805
- _Requests.mcAssetInstance = import_axios.default.create({
806
- timeout: 5e3
807
- });
808
- _Requests.genericQueue = new import_jobqu.JobQueue((request) => _Requests.axiosInstance.request(request), import_time2.Time.millis(10), 1);
809
- _Requests.mcAssetRequestQueue = new import_jobqu.JobQueue((request) => _Requests.mcAssetInstance.request(request), import_time2.Time.millis(10), 1);
810
- var Requests = _Requests;
811
836
 
812
837
  // src/WrappedImage.ts
813
838
  var WrappedImage = class {
@@ -845,10 +870,10 @@ var WrappedImage = class {
845
870
  return this.animated ? this.width : this.height;
846
871
  }
847
872
  get frameCount() {
848
- return this.height / this.width;
873
+ return this.height / this.frameHeight;
849
874
  }
850
875
  getFrameY(frame) {
851
- return this.height / this.frameCount * Math.max(0, Math.min(this.frameCount, frame));
876
+ return this.frameHeight * Math.max(0, Math.min(this.frameCount - 1, frame));
852
877
  }
853
878
  getSectionData(sx, sy, sw, sh) {
854
879
  return this.dta.data.getImageData(sx, sy, sw, sh);
@@ -858,7 +883,7 @@ var WrappedImage = class {
858
883
  }
859
884
  getFrameSectionData(frame) {
860
885
  const y = this.getFrameY(frame);
861
- return this.getSectionData(0, y, this.width, this.width + y);
886
+ return this.getSectionData(0, y, this.frameWidth, this.frameHeight);
862
887
  }
863
888
  };
864
889
 
@@ -872,29 +897,41 @@ var ImageLoader = class _ImageLoader {
872
897
  static async loadAsync(src) {
873
898
  return new Promise((resolve, reject) => {
874
899
  const image = this._createImage();
875
- image.src = src;
876
900
  image.onload = () => resolve(image);
877
- image.onerror = (err) => reject(err);
901
+ image.onerror = (err) => reject(err instanceof Error ? err : new Error("Failed to decode image"));
902
+ image.src = src;
878
903
  });
879
904
  }
880
905
  static loadElement(src, onload, onerr) {
881
906
  const image = this._createImage();
882
- image.src = src;
883
907
  if (onload)
884
908
  image.onload = onload;
885
909
  if (onerr)
886
910
  image.onerror = onerr;
911
+ image.src = src;
887
912
  return image;
888
913
  }
889
914
  static async loadData(src) {
890
915
  console.debug(p2, "loadData", src);
891
- return await this.infoToData(await this.getInfo(src));
916
+ const image = await this.loadCanvasData(src);
917
+ return image.data.getImageData(0, 0, image.width, image.height);
892
918
  }
893
919
  static async loadCanvasData(src) {
894
- return await this.infoToCanvasData(await this.getInfo(src));
920
+ const keyStr = serializeImageKey({ src });
921
+ const info = this.getInfo(src);
922
+ const cached = Caching.rawImageCache.getIfPresent(keyStr);
923
+ try {
924
+ return await this.infoToCanvasData(await info);
925
+ } catch (err) {
926
+ if (cached && Caching.rawImageCache.getIfPresent(keyStr) === cached) {
927
+ Caching.rawImageCache.invalidate(keyStr);
928
+ }
929
+ throw err;
930
+ }
895
931
  }
896
932
  static async infoToCanvasData(info) {
897
- const image = await _ImageLoader.loadAsync(info.src);
933
+ const type = info.type === "jpg" ? "jpeg" : info.type ?? "png";
934
+ const image = await _ImageLoader.loadAsync(`data:image/${type};base64,${info.data.toString("base64")}`);
898
935
  const canvas = createCanvas2(info.width, info.height);
899
936
  const context = canvas.getContext("2d");
900
937
  context.drawImage(image, 0, 0);
@@ -905,11 +942,8 @@ var ImageLoader = class _ImageLoader {
905
942
  };
906
943
  }
907
944
  static async infoToData(info) {
908
- const image = await _ImageLoader.loadAsync(info.src);
909
- const canvas = createCanvas2(info.width, info.height);
910
- const context = canvas.getContext("2d");
911
- context.drawImage(image, 0, 0);
912
- return context.getImageData(0, 0, canvas.width, canvas.height);
945
+ const image = await this.infoToCanvasData(info);
946
+ return image.data.getImageData(0, 0, image.width, image.height);
913
947
  }
914
948
  static async getData(src) {
915
949
  const keyStr = serializeImageKey({ src });
@@ -924,38 +958,25 @@ var ImageLoader = class _ImageLoader {
924
958
  });
925
959
  }
926
960
  static async processResponse(response) {
927
- const src = response.config.url;
961
+ const src = response.url;
928
962
  const data = import_buffer.Buffer.from(response.data);
929
963
  const { width, height, type } = Env.provider.imageSize(data);
964
+ if (!width || !height) {
965
+ throw new Error("Invalid or unsupported image dimensions");
966
+ }
930
967
  return {
931
968
  src,
932
- width: width || 0,
933
- height: height || 0,
969
+ width,
970
+ height,
934
971
  type,
935
972
  data
936
973
  };
937
974
  }
938
975
  static async loadInfo(src) {
939
- if (src.startsWith("data:image/png;base64")) {
940
- return this.processResponse({
941
- config: {
942
- url: src
943
- },
944
- data: import_buffer.Buffer.from(src.substr("data:image/png;base64,".length), "base64")
945
- });
946
- }
947
976
  return Requests.genericRequest({
948
977
  url: src,
949
978
  responseType: "arraybuffer"
950
- }).then(this.processResponse).catch((err) => {
951
- return {
952
- src,
953
- width: 0,
954
- height: 0,
955
- type: void 0,
956
- data: import_buffer.Buffer.from([0])
957
- };
958
- });
979
+ }).then(this.processResponse);
959
980
  }
960
981
  static async getInfo(src) {
961
982
  const keyStr = serializeImageKey({ src });
@@ -977,25 +998,39 @@ var ImageLoader = class _ImageLoader {
977
998
 
978
999
  // src/texture/TextureLoader.ts
979
1000
  var TextureLoader = class {
1001
+ static {
1002
+ this.failedTextures = /* @__PURE__ */ new WeakSet();
1003
+ }
1004
+ /** Reports whether image loading failed, so cached textures can be retried. */
1005
+ static hasFailed(texture) {
1006
+ return this.failedTextures.has(texture);
1007
+ }
980
1008
  static createTexture() {
981
- return new import_three4.Texture();
1009
+ return new import_three3.Texture();
982
1010
  }
983
- static loadInBackground(src, format = import_three4.RGBAFormat, rotation = 0) {
1011
+ static loadInBackground(src, format = import_three3.RGBAFormat, rotation = 0) {
984
1012
  const texture = this.createTexture();
985
- const image = ImageLoader.loadElement(src);
986
- image.onload = function() {
1013
+ texture.colorSpace = THREE.SRGBColorSpace;
1014
+ const image = ImageLoader.loadElement(src, () => {
987
1015
  texture.needsUpdate = true;
988
- };
1016
+ }, (error) => {
1017
+ this.failedTextures.add(texture);
1018
+ console.warn("Failed to load texture", src, error);
1019
+ });
989
1020
  texture.image = image;
990
1021
  texture.format = format;
991
1022
  texture.rotation = rotation;
992
1023
  return Textures.initTextureProps(texture);
993
1024
  }
994
- static load(src, format = import_three4.RGBAFormat, rotation = 0) {
995
- const texture = new import_three4.Texture();
1025
+ static load(src, format = import_three3.RGBAFormat, rotation = 0) {
1026
+ const texture = new import_three3.Texture();
1027
+ texture.colorSpace = THREE.SRGBColorSpace;
996
1028
  ImageLoader.getData(src).then((image) => {
997
- texture.needsUpdate = true;
998
1029
  texture.image = image;
1030
+ texture.needsUpdate = true;
1031
+ }).catch((error) => {
1032
+ this.failedTextures.add(texture);
1033
+ console.warn("Failed to load texture", src, error);
999
1034
  });
1000
1035
  texture.format = format;
1001
1036
  texture.rotation = rotation;
@@ -1004,11 +1039,11 @@ var TextureLoader = class {
1004
1039
  };
1005
1040
 
1006
1041
  // src/texture/Textures.ts
1007
- var THREE = __toESM(require("three"));
1042
+ var THREE2 = __toESM(require("three"));
1008
1043
  var Textures = class _Textures {
1009
1044
  static initTextureProps(texture) {
1010
- texture.magFilter = THREE.NearestFilter;
1011
- texture.minFilter = THREE.NearestFilter;
1045
+ texture.magFilter = THREE2.NearestFilter;
1046
+ texture.minFilter = THREE2.NearestFilter;
1012
1047
  texture.anisotropy = 0;
1013
1048
  return texture;
1014
1049
  }
@@ -1016,13 +1051,19 @@ var Textures = class _Textures {
1016
1051
  return TextureLoader.load(key.src, key.format, key.rotation);
1017
1052
  }
1018
1053
  static createAsset(key) {
1019
- return new import_three5.Texture();
1054
+ return new import_three4.Texture();
1020
1055
  }
1021
1056
  static createCanvasTexture(canvas) {
1022
- return this.initTextureProps(new import_three5.CanvasTexture(canvas));
1057
+ const texture = new import_three4.CanvasTexture(canvas);
1058
+ texture.colorSpace = THREE2.SRGBColorSpace;
1059
+ return this.initTextureProps(texture);
1023
1060
  }
1024
1061
  static getImage(key) {
1025
1062
  const keyStr = serializeTextureKey(key);
1063
+ const cached = Caching.textureCache.peek(keyStr);
1064
+ if (cached && TextureLoader.hasFailed(cached)) {
1065
+ Caching.textureCache.invalidate(keyStr);
1066
+ }
1026
1067
  return Caching.textureCache.get(keyStr, (k) => {
1027
1068
  return _Textures.createImage(key);
1028
1069
  });
@@ -1030,7 +1071,10 @@ var Textures = class _Textures {
1030
1071
  };
1031
1072
 
1032
1073
  // src/Materials.ts
1033
- var _Materials = class _Materials {
1074
+ var Materials = class _Materials {
1075
+ static {
1076
+ this.MISSING_TEXTURE_SRC = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX/AP8AAACfphTyAAAAFUlEQVQoz2MIhQKGVVAwKjIqQrwIAHRz/wFI17TEAAAAAElFTkSuQmCC";
1077
+ }
1034
1078
  // resolved lazily: as a static field this decoded an image the moment the library was
1035
1079
  // imported, which needs both a DOM and an EnvProvider to already be in place
1036
1080
  static get MISSING_TEXTURE() {
@@ -1038,26 +1082,26 @@ var _Materials = class _Materials {
1038
1082
  }
1039
1083
  static createImage(key) {
1040
1084
  const transparent = key.transparent || false;
1041
- return new import_three6.MeshBasicMaterial({
1085
+ return new import_three5.MeshBasicMaterial({
1042
1086
  map: Textures.getImage(key.texture),
1043
1087
  transparent,
1044
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1088
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1045
1089
  alphaTest: 0.5
1046
1090
  });
1047
1091
  }
1048
1092
  static createBasicCanvasMaterial(canvas, transparent = false, shade = false) {
1049
1093
  if (shade) {
1050
- return new import_three6.MeshStandardMaterial({
1094
+ return new import_three5.MeshStandardMaterial({
1051
1095
  map: Textures.createCanvasTexture(canvas),
1052
1096
  transparent,
1053
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1097
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1054
1098
  alphaTest: 0.5
1055
1099
  });
1056
1100
  }
1057
- return new import_three6.MeshBasicMaterial({
1101
+ return new import_three5.MeshBasicMaterial({
1058
1102
  map: Textures.createCanvasTexture(canvas),
1059
1103
  transparent,
1060
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1104
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1061
1105
  alphaTest: 0.5
1062
1106
  });
1063
1107
  }
@@ -1066,6 +1110,7 @@ var _Materials = class _Materials {
1066
1110
  uniform bool SHADE;
1067
1111
 
1068
1112
  varying vec2 vUv;
1113
+ varying vec3 vTint;
1069
1114
  varying float light;
1070
1115
  varying float lift;
1071
1116
 
@@ -1078,7 +1123,11 @@ var _Materials = class _Materials {
1078
1123
 
1079
1124
  if (SHADE) {
1080
1125
 
1081
- vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );
1126
+ #ifdef USE_INSTANCING
1127
+ vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );
1128
+ #else
1129
+ vec3 N = vec3( modelMatrix * vec4(normal, 0.0) );
1130
+ #endif
1082
1131
 
1083
1132
  float yLight = (1.0+N.y) * 0.5;
1084
1133
  light = yLight * (1.0-AMBIENT) + N.x*N.x * XFAC + N.z*N.z * ZFAC + AMBIENT;
@@ -1096,6 +1145,7 @@ var _Materials = class _Materials {
1096
1145
  }
1097
1146
 
1098
1147
  vUv = uv;
1148
+ vTint = color;
1099
1149
 
1100
1150
  #ifdef USE_INSTANCING
1101
1151
  gl_Position = projectionMatrix * viewMatrix * modelMatrix * instanceMatrix * vec4(position, 1.0);
@@ -1117,12 +1167,14 @@ var _Materials = class _Materials {
1117
1167
  uniform float BRIGHTNESS;
1118
1168
 
1119
1169
  varying vec2 vUv;
1170
+ varying vec3 vTint;
1120
1171
  varying float light;
1121
1172
  varying float lift;
1122
1173
 
1123
1174
  void main(void)
1124
1175
  {
1125
1176
  vec4 color = texture2D(map, vUv);
1177
+ color.rgb *= vTint;
1126
1178
 
1127
1179
  if (color.a < 0.01) discard;
1128
1180
 
@@ -1136,16 +1188,19 @@ var _Materials = class _Materials {
1136
1188
  gl_FragColor = vec4(lift + color.rgb * light2, 1.0);
1137
1189
 
1138
1190
  }
1191
+
1192
+ #include <tonemapping_fragment>
1193
+ #include <colorspace_fragment>
1139
1194
  }
1140
1195
  `;
1141
1196
  try {
1142
- return new import_three6.ShaderMaterial({
1197
+ return new import_three5.ShaderMaterial({
1143
1198
  uniforms: {
1144
1199
  SHADE: { value: true },
1145
1200
  BRIGHTNESS: { value: 1 },
1146
1201
  EMISSIVE: { value: false },
1147
1202
  base: {
1148
- value: new import_three6.Color(12698049)
1203
+ value: new import_three5.Color(12698049)
1149
1204
  /*TODO*/
1150
1205
  },
1151
1206
  map: { value: Textures.createCanvasTexture(canvas) }
@@ -1154,7 +1209,7 @@ var _Materials = class _Materials {
1154
1209
  fragmentShader: fragShader,
1155
1210
  vertexColors: true,
1156
1211
  transparent,
1157
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1212
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1158
1213
  alphaTest: 0.5
1159
1214
  });
1160
1215
  } catch (e) {
@@ -1164,6 +1219,10 @@ var _Materials = class _Materials {
1164
1219
  }
1165
1220
  static getImage(key) {
1166
1221
  const keyStr = serializeMaterialKey(key);
1222
+ const map = Caching.materialCache.peek(keyStr)?.map;
1223
+ if (map && TextureLoader.hasFailed(map)) {
1224
+ Caching.materialCache.invalidate(keyStr);
1225
+ }
1167
1226
  return Caching.materialCache.get(keyStr, (k) => {
1168
1227
  return _Materials.createImage(key);
1169
1228
  });
@@ -1184,14 +1243,12 @@ var _Materials = class _Materials {
1184
1243
  }
1185
1244
  }
1186
1245
  };
1187
- _Materials.MISSING_TEXTURE_SRC = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX/AP8AAACfphTyAAAAFUlEQVQoz2MIhQKGVVAwKjIqQrwIAHRz/wFI17TEAAAAAElFTkSuQmCC";
1188
- var Materials = _Materials;
1189
1246
 
1190
1247
  // src/Meshes.ts
1191
- var import_three7 = require("three");
1248
+ var import_three6 = require("three");
1192
1249
  var Meshes = class _Meshes {
1193
1250
  static createBox(key) {
1194
- return new import_three7.Mesh(Geometries.getBox(key.geometry), Materials.getImage(key.material));
1251
+ return new import_three6.Mesh(Geometries.getBox(key.geometry), Materials.getImage(key.material));
1195
1252
  }
1196
1253
  static getBox(key) {
1197
1254
  const keyStr = serializeMeshKey(key);
@@ -1202,7 +1259,7 @@ var Meshes = class _Meshes {
1202
1259
  };
1203
1260
 
1204
1261
  // src/UVMapper.ts
1205
- var import_three8 = require("three");
1262
+ var import_three9 = require("three");
1206
1263
 
1207
1264
  // src/model/ModelMerger.ts
1208
1265
  var import_ts_deepmerge = __toESM(require_dist());
@@ -1238,9 +1295,10 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1238
1295
  this.rootType = rootType;
1239
1296
  this.extension = extension;
1240
1297
  this.root = root;
1298
+ this.isAssetKey = true;
1241
1299
  }
1242
1300
  static parse(assetType, str, origin) {
1243
- let namespace = (origin == null ? void 0 : origin.namespace) || DEFAULT_NAMESPACE;
1301
+ let namespace = origin?.namespace || DEFAULT_NAMESPACE;
1244
1302
  if (str.includes(":")) {
1245
1303
  let split2 = str.split(":");
1246
1304
  namespace = split2[0];
@@ -1253,12 +1311,15 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1253
1311
  split.shift();
1254
1312
  }
1255
1313
  let path = split.join("/");
1256
- let extension = assetType === "textures" ? ".png" : (origin == null ? void 0 : origin.assetType) || ".json";
1257
- return new _AssetKey(namespace, path, assetType, type, "assets", extension, origin == null ? void 0 : origin.root);
1314
+ const extension = assetType === "textures" ? ".png" : origin?.extension ?? ".json";
1315
+ if (extension && path.endsWith(extension)) {
1316
+ path = path.slice(0, -extension.length);
1317
+ }
1318
+ return new _AssetKey(namespace, path, assetType, type, "assets", extension, origin?.root);
1258
1319
  }
1259
1320
  toString() {
1260
1321
  let a = [
1261
- typeof this.root !== "undefined" || AssetLoader.ROOT !== DEFAULT_ROOT ? this.root ?? AssetLoader.ROOT : "__root__",
1322
+ this.root ?? AssetLoader.ROOT,
1262
1323
  this.rootType ?? "__rootType__",
1263
1324
  this.assetType ?? "__assetType__",
1264
1325
  this.type ?? "__type__",
@@ -1268,12 +1329,12 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1268
1329
  return a.join("/");
1269
1330
  }
1270
1331
  getFullPath() {
1271
- let p13 = [];
1332
+ let p12 = [];
1272
1333
  if (this.type) {
1273
- p13.push(this.type);
1334
+ p12.push(this.type);
1274
1335
  }
1275
- p13.push(this.path);
1276
- return p13.join("/");
1336
+ p12.push(this.path);
1337
+ return p12.join("/");
1277
1338
  }
1278
1339
  toNamespacedString() {
1279
1340
  return this.namespace + ":" + this.getFullPath();
@@ -1283,22 +1344,84 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1283
1344
  }
1284
1345
  };
1285
1346
  function isBasicAssetKey(obj) {
1286
- return "namespace" in obj && "path" in obj;
1347
+ return obj !== null && typeof obj === "object" && typeof obj.namespace === "string" && typeof obj.path === "string";
1287
1348
  }
1288
1349
  function isAssetKey(obj) {
1289
- return isBasicAssetKey(obj) && "parse" in obj;
1350
+ return isBasicAssetKey(obj) && obj.isAssetKey === true;
1290
1351
  }
1291
1352
 
1353
+ // src/model/DisplayTransforms.ts
1354
+ var import_three7 = require("three");
1355
+
1356
+ // src/model/DisplayPosition.ts
1357
+ var DisplayPosition = /* @__PURE__ */ ((DisplayPosition2) => {
1358
+ DisplayPosition2["THIRDPERSON_RIGHTHAND"] = "thirdperson_righthand";
1359
+ DisplayPosition2["THIRDPERSON_LEFTHAND"] = "thirdperson_lefthand";
1360
+ DisplayPosition2["FIRSTPERSON_RIGHTHAND"] = "firstperson_righthand";
1361
+ DisplayPosition2["FIRSTPERSON_LEFTHAND"] = "firstperson_lefthand";
1362
+ DisplayPosition2["GUI"] = "gui";
1363
+ DisplayPosition2["HEAD"] = "head";
1364
+ DisplayPosition2["GROUND"] = "ground";
1365
+ DisplayPosition2["FIXED"] = "fixed";
1366
+ DisplayPosition2["ON_SHELF"] = "on_shelf";
1367
+ return DisplayPosition2;
1368
+ })(DisplayPosition || {});
1369
+ var DISPLAY_POSITIONS = Object.values(DisplayPosition);
1370
+
1371
+ // src/model/DisplayTransforms.ts
1372
+ var DisplayTransforms = class {
1373
+ /** Resolve hand fallbacks within one model, before inheriting parent display entries. */
1374
+ static withHandFallbacks(display) {
1375
+ if (!display) return void 0;
1376
+ const resolved = { ...display };
1377
+ for (const [left, right] of [
1378
+ ["thirdperson_lefthand" /* THIRDPERSON_LEFTHAND */, "thirdperson_righthand" /* THIRDPERSON_RIGHTHAND */],
1379
+ ["firstperson_lefthand" /* FIRSTPERSON_LEFTHAND */, "firstperson_righthand" /* FIRSTPERSON_RIGHTHAND */]
1380
+ ]) {
1381
+ if (resolved[left] === void 0 && resolved[right] !== void 0) resolved[left] = resolved[right];
1382
+ }
1383
+ return resolved;
1384
+ }
1385
+ /** Build a display pose for geometry already centered at the model's [8, 8, 8] pivot. */
1386
+ static getMatrix(display, position) {
1387
+ const transform = this.withHandFallbacks(display)?.[position] ?? {};
1388
+ const left = position === "firstperson_lefthand" /* FIRSTPERSON_LEFTHAND */ || position === "thirdperson_lefthand" /* THIRDPERSON_LEFTHAND */;
1389
+ const sign = left ? -1 : 1;
1390
+ const [x, y, z] = transform.rotation ?? [0, 0, 0];
1391
+ const rotation = new import_three7.Quaternion().setFromEuler(new import_three7.Euler(toRadians(x), sign * toRadians(y), sign * toRadians(z), "XYZ"));
1392
+ const translation = new import_three7.Vector3(...transform.translation ?? [0, 0, 0]).clampScalar(-80, 80);
1393
+ translation.x *= sign;
1394
+ const scale = new import_three7.Vector3(...transform.scale ?? [1, 1, 1]).clampScalar(-4, 4);
1395
+ return new import_three7.Matrix4().compose(translation, rotation, scale);
1396
+ }
1397
+ static apply(geometry, matrix) {
1398
+ geometry.applyMatrix4(matrix);
1399
+ if (matrix.determinant() < 0) {
1400
+ if (!geometry.index) geometry.setIndex(Array.from({ length: geometry.getAttribute("position").count }, (_, i) => i));
1401
+ const index = geometry.index;
1402
+ for (let i = 0; i < index.count; i += 3) {
1403
+ const second = index.getX(i + 1);
1404
+ index.setX(i + 1, index.getX(i + 2));
1405
+ index.setX(i + 2, second);
1406
+ }
1407
+ index.needsUpdate = true;
1408
+ }
1409
+ }
1410
+ };
1411
+
1292
1412
  // src/model/ModelMerger.ts
1293
1413
  var ModelMerger = class {
1294
1414
  static async mergeWithParents(model) {
1295
1415
  const models = await this.collectAllParents(model);
1296
1416
  let merged = {};
1297
- for (let parentModel of models) {
1298
- merged = (0, import_ts_deepmerge.default)(merged, parentModel);
1417
+ for (const source of [...models, model]) {
1418
+ const inheritedDisplay = merged.display;
1419
+ merged = import_ts_deepmerge.default.withOptions({ mergeArrays: false }, merged, source);
1420
+ if (source.display) {
1421
+ merged.display = { ...inheritedDisplay, ...DisplayTransforms.withHandFallbacks(source.display) };
1422
+ }
1299
1423
  }
1300
- merged = (0, import_ts_deepmerge.default)(merged, model);
1301
- merged.hierarchy = models.map((m) => m.parent).filter((p13) => `${p13}`);
1424
+ merged.hierarchy = models.map((m) => m.parent).filter((p12) => `${p12}`);
1302
1425
  merged.hierarchy.push(`${merged.parent}`);
1303
1426
  return merged;
1304
1427
  }
@@ -1308,6 +1431,7 @@ var ModelMerger = class {
1308
1431
  }
1309
1432
  const models = [];
1310
1433
  const parentKey = AssetKey.parse("models", model.parent);
1434
+ parentKey.root = model.key?.root;
1311
1435
  const parentModel = await Models.getRaw(parentKey);
1312
1436
  if (parentModel) {
1313
1437
  models.unshift(parentModel);
@@ -1317,9 +1441,6 @@ var ModelMerger = class {
1317
1441
  }
1318
1442
  };
1319
1443
 
1320
- // src/assets/Models.ts
1321
- var import_typescript_memoize = require("typescript-memoize");
1322
-
1323
1444
  // src/assets/source/parser/AssetParsers.ts
1324
1445
  var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1325
1446
  AssetParser2["MODEL"] = "model";
@@ -1333,30 +1454,65 @@ var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1333
1454
  })(AssetParser || {});
1334
1455
 
1335
1456
  // src/assets/Models.ts
1336
- var _Models = class _Models {
1457
+ var Models = class _Models {
1337
1458
  // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading
1338
1459
  // the library, and would require an EnvProvider before any entry has had a chance to register
1339
1460
  static get PERSISTENT_CACHE() {
1340
1461
  return this._persistentCache ??= PersistentCache.open("minerender-models");
1341
1462
  }
1342
1463
  static async getItemList() {
1343
- return AssetLoader.get(new AssetKey(
1344
- DEFAULT_NAMESPACE,
1345
- "_list",
1346
- "models",
1347
- "item",
1348
- "assets",
1349
- ".json",
1350
- DEFAULT_ROOT
1351
- ), "list" /* LIST */).then((r) => (r == null ? void 0 : r.files) ?? []);
1464
+ const key = new AssetKey(DEFAULT_NAMESPACE, "_list", "items");
1465
+ const legacyKey = new AssetKey(DEFAULT_NAMESPACE, "_list", "models", "item");
1466
+ return Caching.listAssetCache.get(key.serialize(), async () => {
1467
+ return (await AssetLoader.getFirst([key, legacyKey], "list" /* LIST */))?.asset;
1468
+ }).then((r) => r?.files ?? []);
1352
1469
  }
1353
1470
  static async loadAndMerge(key) {
1354
- const model = await this.getRaw(key);
1471
+ const model = key.type === "item" ? await this.getItemModel(key) : await this.getRaw(key);
1355
1472
  if (!model) {
1356
1473
  return void 0;
1357
1474
  }
1358
1475
  return ModelMerger.mergeWithParents(model);
1359
1476
  }
1477
+ static async getItemModel(key) {
1478
+ const itemKey = new AssetKey(key.namespace, key.path, "items", void 0, key.rootType, ".json", key.root);
1479
+ const model = await this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(itemKey.serialize()), async () => {
1480
+ const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
1481
+ if (!result) return void 0;
1482
+ if (result.key.assetType !== "items") return { ...result.asset, key };
1483
+ const reference = this.defaultItemModel(result.asset.model, key);
1484
+ const modelKey = AssetKey.parse("models", reference);
1485
+ modelKey.root = key.root;
1486
+ const model2 = await this.getRaw(modelKey);
1487
+ if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${reference}`);
1488
+ return model2;
1489
+ });
1490
+ return model ? { ...model, key: Object.assign(new AssetKey("", ""), model.key) } : void 0;
1491
+ }
1492
+ // Item previews use the GUI context, false conditions, and zero numeric properties.
1493
+ static defaultItemModel(node, key) {
1494
+ if (!node || typeof node.type !== "string") {
1495
+ throw new Error(`Unsupported item model definition for ${key.toNamespacedString()}`);
1496
+ }
1497
+ switch (node.type.replace(/^minecraft:/, "")) {
1498
+ case "model":
1499
+ if (typeof node.model === "string" && node.model) return node.model;
1500
+ break;
1501
+ case "condition":
1502
+ return this.defaultItemModel(node.on_false, key);
1503
+ case "select": {
1504
+ const selected = node.property?.replace(/^minecraft:/, "") === "display_context" ? node.cases?.find((entry) => Array.isArray(entry.when) ? entry.when.includes("gui") : entry.when === "gui")?.model : void 0;
1505
+ return this.defaultItemModel(selected ?? node.fallback, key);
1506
+ }
1507
+ case "range_dispatch": {
1508
+ const selected = node.entries?.reduce((match, entry) => {
1509
+ return entry.threshold <= 0 && (!match || entry.threshold >= match.threshold) ? entry : match;
1510
+ }, void 0);
1511
+ return this.defaultItemModel(selected?.model ?? node.fallback, key);
1512
+ }
1513
+ }
1514
+ throw new Error(`Unsupported item model ${node?.type ?? "definition"} for ${key.toNamespacedString()}`);
1515
+ }
1360
1516
  static async getRaw(key) {
1361
1517
  if (!key.assetType) {
1362
1518
  key.assetType = "models";
@@ -1366,7 +1522,7 @@ var _Models = class _Models {
1366
1522
  }
1367
1523
  const keyStr = key.serialize();
1368
1524
  return Caching.rawModelCache.get(keyStr, (k) => {
1369
- return this.PERSISTENT_CACHE.getOrLoad(keyStr, (k1) => {
1525
+ return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
1370
1526
  return AssetLoader.get(key, "model" /* MODEL */);
1371
1527
  });
1372
1528
  }).then((asset) => {
@@ -1395,31 +1551,32 @@ var _Models = class _Models {
1395
1551
  return this.PERSISTENT_CACHE.clear();
1396
1552
  }
1397
1553
  };
1398
- __decorateClass([
1399
- (0, import_typescript_memoize.Memoize)()
1400
- ], _Models, "getItemList", 1);
1401
- var Models = _Models;
1402
1554
 
1403
1555
  // src/assets/BlockStates.ts
1404
- var import_typescript_memoize2 = require("typescript-memoize");
1405
1556
  var BlockStates = class {
1406
1557
  static get PERSISTENT_CACHE() {
1407
1558
  return this._persistentCache ??= PersistentCache.open("minerender-blockstates");
1408
1559
  }
1560
+ // BlockState names are hardcoded
1409
1561
  static async getList() {
1410
- return AssetLoader.get(new AssetKey(
1562
+ const key = new AssetKey(
1411
1563
  DEFAULT_NAMESPACE,
1412
1564
  "_list",
1413
1565
  "blockstates",
1414
1566
  void 0,
1415
1567
  "assets",
1416
1568
  ".json",
1417
- DEFAULT_ROOT
1418
- ), "list" /* LIST */).then((r) => (r == null ? void 0 : r.files) ?? []);
1569
+ AssetLoader.ROOT
1570
+ );
1571
+ return Caching.listAssetCache.get(key.serialize(), () => {
1572
+ return AssetLoader.get(key, "list" /* LIST */);
1573
+ }).then((r) => r?.files ?? []);
1419
1574
  }
1420
1575
  static async getDefaultStates() {
1421
1576
  const key = AssetKey.parse("blockstates", "minerender:defaultBlockStates");
1422
- return AssetLoader.get(key, "json" /* JSON */);
1577
+ return Caching.defaultBlockStatesCache.get(key.serialize(), () => {
1578
+ return AssetLoader.get(key, "json" /* JSON */);
1579
+ });
1423
1580
  }
1424
1581
  static async getDefaultState(key) {
1425
1582
  const defaultStates = await this.getDefaultStates();
@@ -1437,7 +1594,7 @@ var BlockStates = class {
1437
1594
  }
1438
1595
  const keyStr = key.serialize();
1439
1596
  return Caching.blockStateCache.get(keyStr, (k) => {
1440
- return this.PERSISTENT_CACHE.getOrLoad(keyStr, (k1) => {
1597
+ return this.PERSISTENT_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
1441
1598
  return AssetLoader.get(key, "blockstate" /* BLOCKSTATE */);
1442
1599
  });
1443
1600
  }).then((asset) => {
@@ -1458,17 +1615,11 @@ var BlockStates = class {
1458
1615
  await this.PERSISTENT_CACHE.clear();
1459
1616
  }
1460
1617
  };
1461
- __decorateClass([
1462
- (0, import_typescript_memoize2.Memoize)()
1463
- ], BlockStates, "getList", 1);
1464
- __decorateClass([
1465
- (0, import_typescript_memoize2.Memoize)()
1466
- ], BlockStates, "getDefaultStates", 1);
1467
1618
  var DefaultBlockStates = class {
1468
1619
  };
1469
1620
 
1470
1621
  // src/assets/Assets.ts
1471
- var DEFAULT_ROOT = "https://assets.mcasset.cloud/1.17.1";
1622
+ var DEFAULT_ROOT = "https://assets.mcasset.cloud/1.21.11";
1472
1623
  var DEFAULT_NAMESPACE = "minecraft";
1473
1624
  var Assets = class {
1474
1625
  /**
@@ -1489,24 +1640,237 @@ var Assets = class {
1489
1640
  var AssetSource = class {
1490
1641
  constructor() {
1491
1642
  }
1492
- };
1493
-
1494
- // src/nbt/NBTHelper.ts
1495
- var NBTHelper = class {
1496
- static async fromBuffer(buffer) {
1497
- const prismarineNbt = await import("prismarine-nbt");
1498
- const { parsed, type, metadata } = await prismarineNbt.parse(buffer);
1499
- return parsed;
1643
+ /**
1644
+ * Identifies this source's content across sessions for persistent caching. Sources that
1645
+ * cannot tell whether their content changed (an unnamed archive, for example) return
1646
+ * undefined, which keeps their results out of long-lived caches.
1647
+ */
1648
+ get cacheId() {
1649
+ return void 0;
1650
+ }
1651
+ };
1652
+ var AssetLoadError = class extends Error {
1653
+ constructor(source, key, path, cause) {
1654
+ super(`Failed to load ${key.toNamespacedString()} from ${path}${cause instanceof Error ? `: ${cause.message}` : ""}`);
1655
+ this.source = source;
1656
+ this.key = key;
1657
+ this.path = path;
1658
+ this.cause = cause;
1659
+ this.name = "AssetLoadError";
1660
+ }
1661
+ };
1662
+
1663
+ // src/util/BatchedExecutor.ts
1664
+ var BatchedExecutor = class {
1665
+ constructor(interval = 1, batch = 30) {
1666
+ this.interval = interval;
1667
+ this.batch = batch;
1668
+ this.queue = [];
1669
+ this.task = setInterval(() => this.run());
1670
+ }
1671
+ submit(task) {
1672
+ this.queue.push(task);
1673
+ }
1674
+ run() {
1675
+ for (let i = 0; i < this.batch; i++) {
1676
+ this.runNext();
1677
+ }
1678
+ }
1679
+ runNext() {
1680
+ let next = this.queue.shift();
1681
+ if (next) next();
1682
+ }
1683
+ };
1684
+
1685
+ // src/util/model.ts
1686
+ var import_three8 = require("three");
1687
+ function applyElementRotation(rotation, geometry) {
1688
+ const origin = new import_three8.Vector3(rotation.origin[0], rotation.origin[1], rotation.origin[2]);
1689
+ geometry.translate(-origin.x, -origin.y, -origin.z);
1690
+ switch (rotation.axis) {
1691
+ case "x" /* X */:
1692
+ geometry.rotateX(toRadians(rotation.angle));
1693
+ break;
1694
+ case "y" /* Y */:
1695
+ geometry.rotateY(toRadians(rotation.angle));
1696
+ break;
1697
+ case "z" /* Z */:
1698
+ geometry.rotateZ(toRadians(rotation.angle));
1699
+ break;
1700
+ }
1701
+ if (rotation.rescale) {
1702
+ if (Math.abs(rotation.angle) === 22.5) {
1703
+ const s = 1 / Math.cos(0.39269909262657166);
1704
+ geometry.scale(s, 1, s);
1705
+ } else {
1706
+ const s = 1 / Math.cos(0.7853981852531433);
1707
+ geometry.scale(s, 1, s);
1708
+ }
1709
+ }
1710
+ geometry.translate(origin.x, origin.y, origin.z);
1711
+ }
1712
+ function applyGenericRotation(axis, rotation, obj) {
1713
+ switch (axis) {
1714
+ case "x" /* X */:
1715
+ obj.rotateOnAxis(new import_three8.Vector3(1, 0, 0), toRadians(rotation));
1716
+ break;
1717
+ case "y" /* Y */:
1718
+ obj.rotateOnAxis(new import_three8.Vector3(0, 1, 0), toRadians(rotation));
1719
+ break;
1720
+ case "z" /* Z */:
1721
+ obj.rotateOnAxis(new import_three8.Vector3(0, 0, 1), toRadians(rotation));
1722
+ break;
1723
+ }
1724
+ }
1725
+ function addBox3WireframeToObject(box, obj, color = 16777215, w = 2) {
1726
+ let size = new import_three8.Vector3();
1727
+ box.getSize(size);
1728
+ let boxGeo = new import_three8.BoxGeometry(size.x, size.y, size.z, 1, 1, 1);
1729
+ let wireGeo = new import_three8.EdgesGeometry(boxGeo);
1730
+ let wireMat = new import_three8.LineBasicMaterial({ color, linewidth: w });
1731
+ let wireframe = new import_three8.LineSegments(wireGeo, wireMat);
1732
+ obj.add(wireframe);
1733
+ let axes = new import_three8.AxesHelper(1);
1734
+ obj.add(axes);
1735
+ }
1736
+ function addWireframeToObject(obj, color = 16777215, w = 2) {
1737
+ let boxGeo = new import_three8.BoxGeometry(16, 16, 16, 1, 1, 1);
1738
+ let wireGeo = new import_three8.EdgesGeometry(boxGeo);
1739
+ let wireMat = new import_three8.LineBasicMaterial({ color, linewidth: w });
1740
+ let wireframe = new import_three8.LineSegments(wireGeo, wireMat);
1741
+ obj.add(wireframe);
1742
+ let axes = new import_three8.AxesHelper(1);
1743
+ obj.add(axes);
1744
+ }
1745
+ function addWireframeToMesh(geo, mesh, color = 16777215, w = 2) {
1746
+ let wireGeo = new import_three8.EdgesGeometry(geo);
1747
+ let wireMat = new import_three8.LineBasicMaterial({ color, linewidth: w });
1748
+ let wireframe = new import_three8.LineSegments(wireGeo, wireMat);
1749
+ mesh.add(wireframe);
1750
+ let axes = new import_three8.AxesHelper(1);
1751
+ mesh.add(axes);
1752
+ }
1753
+
1754
+ // src/util/performance.ts
1755
+ function captureException(e, ...extra) {
1756
+ console.error(e, extra);
1757
+ }
1758
+ function timingStart(marker) {
1759
+ console.time(marker);
1760
+ }
1761
+ function timingEnd(marker) {
1762
+ console.timeEnd(marker);
1763
+ }
1764
+
1765
+ // src/util/three.ts
1766
+ function isObject3D(obj) {
1767
+ return obj.isObject3D;
1768
+ }
1769
+ function isMesh(obj) {
1770
+ return obj.isMesh;
1771
+ }
1772
+ function isInstancedMesh(obj) {
1773
+ return obj.isInstancedMesh;
1774
+ }
1775
+ function isPerspectiveCamera(obj) {
1776
+ return obj.isPerspectiveCamera;
1777
+ }
1778
+ function isOrthographicCamera(obj) {
1779
+ return obj.isOrthographicCamera;
1780
+ }
1781
+
1782
+ // src/nbt/NBTHelper.ts
1783
+ var NBTHelper = class {
1784
+ static async fromBuffer(buffer) {
1785
+ const prismarineNbt = await import("prismarine-nbt");
1786
+ const { parsed, type, metadata } = await prismarineNbt.parse(buffer);
1787
+ return parsed;
1788
+ }
1789
+ };
1790
+
1791
+ // src/assets/source/HostedAssetSource.ts
1792
+ var import_ts_deepmerge2 = __toESM(require_dist());
1793
+ var p3 = prefix("HostedAssetSource");
1794
+ var DEFAULT_OPTIONS = {
1795
+ retryDefaults: true
1796
+ };
1797
+ var HostedAssetSource = class _HostedAssetSource extends AssetSource {
1798
+ static {
1799
+ this.MODEL = {
1800
+ config(request) {
1801
+ },
1802
+ parse(response) {
1803
+ return response.data;
1804
+ }
1805
+ };
1806
+ }
1807
+ static {
1808
+ this.BLOCKSTATE = {
1809
+ config(request) {
1810
+ },
1811
+ parse(response) {
1812
+ return response.data;
1813
+ }
1814
+ };
1815
+ }
1816
+ static {
1817
+ this.META = {
1818
+ config(request) {
1819
+ },
1820
+ parse(response) {
1821
+ return response.data;
1822
+ }
1823
+ };
1824
+ }
1825
+ static {
1826
+ this.NBT = {
1827
+ config(request) {
1828
+ request.responseType = "arraybuffer";
1829
+ },
1830
+ parse(response) {
1831
+ return NBTHelper.fromBuffer(Buffer.from(response.data));
1832
+ }
1833
+ };
1834
+ }
1835
+ static {
1836
+ this.IMAGE = {
1837
+ config(request) {
1838
+ request.responseType = "arraybuffer";
1839
+ },
1840
+ async parse(response) {
1841
+ return await ImageLoader.processResponse(response);
1842
+ }
1843
+ };
1844
+ }
1845
+ static {
1846
+ this.LIST = {
1847
+ config(request) {
1848
+ },
1849
+ parse(response) {
1850
+ return response.data;
1851
+ }
1852
+ };
1853
+ }
1854
+ static {
1855
+ this.JSON = {
1856
+ config(request) {
1857
+ },
1858
+ parse(response) {
1859
+ return response.data;
1860
+ }
1861
+ };
1862
+ }
1863
+ static {
1864
+ this.PARSER_MAP = /* @__PURE__ */ new Map([
1865
+ ["model" /* MODEL */, _HostedAssetSource.MODEL],
1866
+ ["blockstate" /* BLOCKSTATE */, _HostedAssetSource.BLOCKSTATE],
1867
+ ["meta" /* META */, _HostedAssetSource.META],
1868
+ ["nbt" /* NBT */, _HostedAssetSource.NBT],
1869
+ ["image" /* IMAGE */, _HostedAssetSource.IMAGE],
1870
+ ["list" /* LIST */, _HostedAssetSource.LIST],
1871
+ ["json" /* JSON */, _HostedAssetSource.JSON]
1872
+ ]);
1500
1873
  }
1501
- };
1502
-
1503
- // src/assets/source/HostedAssetSource.ts
1504
- var import_ts_deepmerge2 = __toESM(require_dist());
1505
- var p3 = prefix("HostedAssetSource");
1506
- var DEFAULT_OPTIONS = {
1507
- retryDefaults: true
1508
- };
1509
- var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1510
1874
  async loadOrRetryWithDefaults(key, parser) {
1511
1875
  const direct = await this.load(key, parser);
1512
1876
  if (typeof direct !== "undefined") {
@@ -1519,17 +1883,17 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1519
1883
  if (typeof namespaced !== "undefined") {
1520
1884
  return namespaced;
1521
1885
  }
1522
- if (typeof key.root !== "undefined" && key.root !== DEFAULT_ROOT || typeof this.root !== "undefined" && this.root !== DEFAULT_ROOT) {
1886
+ if (typeof key.root !== "undefined" && key.root !== AssetLoader.ROOT || typeof this.root !== "undefined" && this.root !== AssetLoader.ROOT) {
1523
1887
  console.info(p3, "Retrying", key, "with default root+namespace");
1524
- const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, DEFAULT_ROOT);
1888
+ const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);
1525
1889
  const namespacedRooted = await this.load(namespacedRootedKey, parser);
1526
1890
  if (typeof namespacedRooted !== "undefined") {
1527
1891
  return namespacedRooted;
1528
1892
  }
1529
1893
  }
1530
- } else if (typeof key.root !== "undefined" && key.root !== DEFAULT_ROOT || typeof this.root !== "undefined" && this.root !== DEFAULT_ROOT) {
1894
+ } else if (typeof key.root !== "undefined" && key.root !== AssetLoader.ROOT || typeof this.root !== "undefined" && this.root !== AssetLoader.ROOT) {
1531
1895
  console.info(p3, "Retrying", key, "with default root");
1532
- const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, DEFAULT_ROOT);
1896
+ const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, AssetLoader.ROOT);
1533
1897
  const rooted = await this.load(rootKey, parser);
1534
1898
  if (typeof rooted !== "undefined") {
1535
1899
  return rooted;
@@ -1541,31 +1905,25 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1541
1905
  console.info(p3, "Loading", key);
1542
1906
  const url = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1543
1907
  console.debug(p3, url);
1544
- let req = {
1545
- url
1546
- };
1547
- parser.config(req);
1548
- return await Requests.mcAssetRequest(req).then((response) => {
1549
- if (response && response.data) {
1550
- try {
1551
- return parser.parse(response);
1552
- } catch (e) {
1553
- console.warn("Parser failed to process response", response, e);
1554
- throw e;
1555
- }
1556
- }
1557
- return void 0;
1558
- }).catch((err) => {
1559
- if (err.response) {
1560
- let response = err.response;
1561
- if (response.status === 404) {
1562
- console.debug(p3, key, "not found");
1908
+ const request = { url };
1909
+ try {
1910
+ parser.config(request);
1911
+ let response;
1912
+ try {
1913
+ response = await Requests.mcAssetRequest(request);
1914
+ } catch (cause) {
1915
+ if (cause instanceof RequestError && cause.response?.status === 404) {
1563
1916
  return void 0;
1564
1917
  }
1918
+ throw cause;
1565
1919
  }
1566
- console.debug(p3, "Failed to load", key, err == null ? void 0 : err.message);
1567
- return void 0;
1568
- });
1920
+ if (response.data === void 0) {
1921
+ throw new Error("Asset response has no data");
1922
+ }
1923
+ return await parser.parse(response);
1924
+ } catch (cause) {
1925
+ throw new AssetLoadError(this, key, request.url, cause);
1926
+ }
1569
1927
  }
1570
1928
  assetBasePath(key) {
1571
1929
  return `${key.root ?? this.root ?? AssetLoader.ROOT}/${key.rootType !== void 0 ? key.rootType + "/" : ""}${key.namespace !== void 0 ? key.namespace + "/" : ""}${key.assetType !== void 0 ? key.assetType + "/" : ""}`;
@@ -1578,6 +1936,9 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1578
1936
  get root() {
1579
1937
  return this._root;
1580
1938
  }
1939
+ get cacheId() {
1940
+ return `hosted:${this._root}`;
1941
+ }
1581
1942
  get options() {
1582
1943
  return this._options;
1583
1944
  }
@@ -1589,74 +1950,14 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1589
1950
  return this.load(key, responseParser);
1590
1951
  }
1591
1952
  };
1592
- _HostedAssetSource.MODEL = {
1593
- config(request) {
1594
- },
1595
- parse(response) {
1596
- return response.data;
1597
- }
1598
- };
1599
- _HostedAssetSource.BLOCKSTATE = {
1600
- config(request) {
1601
- },
1602
- parse(response) {
1603
- return response.data;
1604
- }
1605
- };
1606
- _HostedAssetSource.META = {
1607
- config(request) {
1608
- },
1609
- parse(response) {
1610
- return response.data;
1611
- }
1612
- };
1613
- _HostedAssetSource.NBT = {
1614
- config(request) {
1615
- request.responseType = "arraybuffer";
1616
- },
1617
- parse(response) {
1618
- return NBTHelper.fromBuffer(Buffer.from(response.data));
1619
- }
1620
- };
1621
- _HostedAssetSource.IMAGE = {
1622
- config(request) {
1623
- request.responseType = "arraybuffer";
1624
- },
1625
- async parse(response) {
1626
- return await ImageLoader.processResponse(response);
1627
- }
1628
- };
1629
- _HostedAssetSource.LIST = {
1630
- config(request) {
1631
- },
1632
- parse(response) {
1633
- return response.data;
1634
- }
1635
- };
1636
- _HostedAssetSource.JSON = {
1637
- config(request) {
1638
- },
1639
- parse(response) {
1640
- return response.data;
1641
- }
1642
- };
1643
- _HostedAssetSource.PARSER_MAP = /* @__PURE__ */ new Map([
1644
- ["model" /* MODEL */, _HostedAssetSource.MODEL],
1645
- ["blockstate" /* BLOCKSTATE */, _HostedAssetSource.BLOCKSTATE],
1646
- ["meta" /* META */, _HostedAssetSource.META],
1647
- ["nbt" /* NBT */, _HostedAssetSource.NBT],
1648
- ["image" /* IMAGE */, _HostedAssetSource.IMAGE],
1649
- ["list" /* LIST */, _HostedAssetSource.LIST],
1650
- ["json" /* JSON */, _HostedAssetSource.JSON]
1651
- ]);
1652
- var HostedAssetSource = _HostedAssetSource;
1653
1953
 
1654
1954
  // src/assets/source/archive/BrowserArchiveProxy.ts
1655
1955
  var import_zip = require("@zip.js/zip.js");
1656
1956
  var BrowserArchiveProxy = class {
1657
- constructor(blob) {
1957
+ constructor(blob, id) {
1658
1958
  this._blob = blob;
1659
1959
  this._reader = new import_zip.ZipReader(new import_zip.BlobReader(this._blob));
1960
+ this.id = id ?? (typeof File !== "undefined" && blob instanceof File ? `${blob.name}:${blob.size}:${blob.lastModified}` : void 0);
1660
1961
  }
1661
1962
  async getEntries() {
1662
1963
  return (await this._reader.getEntries()).map((e) => {
@@ -1672,7 +1973,6 @@ var BrowserArchiveProxy = class {
1672
1973
  };
1673
1974
 
1674
1975
  // src/assets/source/archive/ArchiveAssetSource.ts
1675
- var p4 = prefix("ArchiveAssetSource");
1676
1976
  var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1677
1977
  constructor(archiveProxy) {
1678
1978
  super();
@@ -1682,6 +1982,10 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1682
1982
  static blob(blob) {
1683
1983
  return new _ArchiveAssetSource(new BrowserArchiveProxy(blob));
1684
1984
  }
1985
+ get cacheId() {
1986
+ const id = this._archiveProxy.id;
1987
+ return id === void 0 ? void 0 : `archive:${id}`;
1988
+ }
1685
1989
  async getEntries() {
1686
1990
  return this._archiveProxy.getEntries();
1687
1991
  }
@@ -1691,74 +1995,31 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1691
1995
  }
1692
1996
  async get(key, parser) {
1693
1997
  const responseParser = HostedAssetSource.PARSER_MAP.get(parser);
1694
- console.log("ArchiveAssetSource.get", key, parser);
1695
- let entries = await this.getEntries();
1696
- const path = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1697
- console.log(path);
1698
- const entry = await this.getEntry(path);
1699
- console.log(entry);
1700
- if (!entry) {
1701
- return void 0;
1702
- }
1703
- let blob = await entry.getData();
1704
- const url = URL.createObjectURL(blob);
1705
- console.log(url);
1706
- let req = {
1707
- url
1708
- };
1709
- responseParser.config(req);
1710
- return Requests.genericRequest(req).then((response) => {
1711
- if (response && response.data) {
1712
- try {
1713
- return responseParser.parse(response);
1714
- } catch (e) {
1715
- console.warn("Parser failed to process response", response, e);
1716
- throw e;
1717
- }
1718
- }
1719
- return void 0;
1720
- }).catch((err) => {
1721
- if (err.response) {
1722
- let response = err.response;
1723
- if (response.status === 404) {
1724
- console.debug(p4, key, "not found");
1725
- return void 0;
1726
- }
1727
- }
1728
- console.debug(p4, "Failed to load", key, err == null ? void 0 : err.message);
1729
- return void 0;
1730
- });
1998
+ return this.load(key, responseParser);
1731
1999
  }
1732
- //TODO: abstract this
1733
2000
  async load(key, parser) {
1734
- console.info(p4, "Loading", key);
1735
- const url = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1736
- console.debug(p4, url);
1737
- let req = {
1738
- url
1739
- };
1740
- parser.config(req);
1741
- return await Requests.genericRequest(req).then((response) => {
1742
- if (response && response.data) {
1743
- try {
1744
- return parser.parse(response);
1745
- } catch (e) {
1746
- console.warn("Parser failed to process response", response, e);
1747
- throw e;
1748
- }
2001
+ const path = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
2002
+ let url;
2003
+ try {
2004
+ const entry = await this.getEntry(path);
2005
+ if (!entry) {
2006
+ return void 0;
1749
2007
  }
1750
- return void 0;
1751
- }).catch((err) => {
1752
- if (err.response) {
1753
- let response = err.response;
1754
- if (response.status === 404) {
1755
- console.debug(p4, key, "not found");
1756
- return void 0;
1757
- }
2008
+ url = URL.createObjectURL(await entry.getData());
2009
+ const request = { url };
2010
+ parser.config(request);
2011
+ const response = await Requests.genericRequest(request);
2012
+ if (response.data === void 0) {
2013
+ throw new Error("Asset response has no data");
1758
2014
  }
1759
- console.debug(p4, "Failed to load", key, err == null ? void 0 : err.message);
1760
- return void 0;
1761
- });
2015
+ return await parser.parse(response);
2016
+ } catch (cause) {
2017
+ throw new AssetLoadError(this, key, path, cause);
2018
+ } finally {
2019
+ if (url !== void 0) {
2020
+ URL.revokeObjectURL(url);
2021
+ }
2022
+ }
1762
2023
  }
1763
2024
  assetBasePath(key) {
1764
2025
  return `${key.rootType !== void 0 ? key.rootType + "/" : ""}${key.namespace !== void 0 ? key.namespace + "/" : ""}${key.assetType !== void 0 ? key.assetType + "/" : ""}`;
@@ -1766,18 +2027,64 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1766
2027
  };
1767
2028
 
1768
2029
  // src/assets/AssetLoader.ts
1769
- var import_ts_deepmerge3 = __toESM(require_dist());
1770
- var p5 = prefix("AssetLoader");
1771
- var _AssetLoader = class _AssetLoader {
2030
+ var p4 = prefix("AssetLoader");
2031
+ var FALLBACK_ROOT = "https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master";
2032
+ var AssetLoader = class {
2033
+ static {
2034
+ this.ROOT = DEFAULT_ROOT;
2035
+ }
2036
+ static {
2037
+ this._SOURCES = [];
2038
+ }
2039
+ static {
2040
+ /** Used when a registered source cannot identify its content, so nothing persists past this session. */
2041
+ this.SESSION_SCOPE = `session:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;
2042
+ }
2043
+ static get version() {
2044
+ return this.ROOT.substring(this.ROOT.lastIndexOf("/") + 1);
2045
+ }
2046
+ static setVersion(version) {
2047
+ this.ROOT = `https://assets.mcasset.cloud/${version}`;
2048
+ const source = new HostedAssetSource(this.ROOT, { retryDefaults: false });
2049
+ const index = this._SOURCES.findIndex((s) => s.key === "mcassets");
2050
+ if (index !== -1) {
2051
+ this._SOURCES[index] = { key: "mcassets", source };
2052
+ } else {
2053
+ this.addSource("mcassets", source);
2054
+ }
2055
+ Caching.clear();
2056
+ }
2057
+ /**
2058
+ * Scope for persistent cache keys. Empty with only the default vanilla sources, so their
2059
+ * entries stay valid across sessions; otherwise it names every added source (resource packs,
2060
+ * mirrors) so their results never masquerade as vanilla assets after a reload.
2061
+ */
2062
+ static get persistentScope() {
2063
+ const parts = [];
2064
+ for (const { key, source } of this._SOURCES) {
2065
+ const id = source.cacheId;
2066
+ if (key === "mcassets" && id === `hosted:${this.ROOT}`) continue;
2067
+ if (key === "mcassets-fallback" && id === `hosted:${FALLBACK_ROOT}`) continue;
2068
+ if (id === void 0) return this.SESSION_SCOPE;
2069
+ parts.push(`${key}=${id}`);
2070
+ }
2071
+ return parts.join("|");
2072
+ }
2073
+ /** Prefixes a persistent cache key with the current source scope. */
2074
+ static persistentKey(key) {
2075
+ const scope = this.persistentScope;
2076
+ return scope ? `${scope}
2077
+ ${key}` : key;
2078
+ }
1772
2079
  static addSource(key, source, override = true) {
1773
2080
  if (override) {
1774
2081
  const existing = this.removeSource(key);
1775
2082
  if (existing) {
1776
- console.log(p5, "Removed existing AssetSource", key);
2083
+ console.log(p4, "Removed existing AssetSource", key);
1777
2084
  }
1778
2085
  }
1779
2086
  this._SOURCES.unshift({ key, source });
1780
- console.log(p5, "Added AssetSource", key);
2087
+ console.log(p4, "Added AssetSource", key);
1781
2088
  }
1782
2089
  static removeSource(key) {
1783
2090
  const index = this._SOURCES.findIndex((s) => s.key === key);
@@ -1789,8 +2096,11 @@ var _AssetLoader = class _AssetLoader {
1789
2096
  }
1790
2097
  return void 0;
1791
2098
  }
2099
+ static {
2100
+ this.addSource("mcassets-fallback", new HostedAssetSource(FALLBACK_ROOT, { retryDefaults: false }));
2101
+ this.addSource("mcassets", new HostedAssetSource(this.ROOT, { retryDefaults: false }));
2102
+ }
1792
2103
  static async getAll(key, parser) {
1793
- console.log(this._SOURCES);
1794
2104
  let promises = [];
1795
2105
  for (const source of this._SOURCES) {
1796
2106
  promises.push(source.source.get(key, parser));
@@ -1799,31 +2109,36 @@ var _AssetLoader = class _AssetLoader {
1799
2109
  return results.filter((r) => r != void 0);
1800
2110
  });
1801
2111
  }
2112
+ /** Returns the first defined result in source-priority order, without merging assets. */
1802
2113
  static async get(key, parser) {
1803
- console.log(this._SOURCES);
1804
- let promises = [];
1805
- for (const source of this._SOURCES) {
1806
- promises.push(source.source.get(key, parser));
1807
- }
1808
- return Promise.all(promises).then((results) => {
1809
- const fallback = results[results.length - 1];
1810
- for (const result of results) {
1811
- if (result) {
1812
- if (fallback) {
1813
- return (0, import_ts_deepmerge3.default)({}, fallback, result);
1814
- }
1815
- return result;
2114
+ const keys = [key];
2115
+ if (key.rootType === "data" && (key.assetType === "structure" || key.assetType === "structures")) {
2116
+ keys.push(new AssetKey(
2117
+ key.namespace,
2118
+ key.path,
2119
+ key.assetType === "structure" ? "structures" : "structure",
2120
+ key.type,
2121
+ key.rootType,
2122
+ key.extension,
2123
+ key.root
2124
+ ));
2125
+ }
2126
+ return (await this.getFirst(keys, parser))?.asset;
2127
+ }
2128
+ /** Tries each path within a source before considering lower-priority sources. */
2129
+ static async getFirst(keys, parser) {
2130
+ const sources = [...this._SOURCES];
2131
+ for (const source of sources) {
2132
+ for (const key of keys) {
2133
+ const result = await source.source.get(key, parser);
2134
+ if (result !== void 0) {
2135
+ return { key, asset: result };
1816
2136
  }
1817
2137
  }
1818
- return void 0;
1819
- });
2138
+ }
2139
+ return void 0;
1820
2140
  }
1821
2141
  };
1822
- _AssetLoader.ROOT = DEFAULT_ROOT;
1823
- _AssetLoader._SOURCES = [];
1824
- _AssetLoader.addSource("mcassets-fallback", new HostedAssetSource("https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master", { retryDefaults: false }));
1825
- _AssetLoader.addSource("mcassets", new HostedAssetSource(DEFAULT_ROOT, { retryDefaults: false }));
1826
- var AssetLoader = _AssetLoader;
1827
2142
 
1828
2143
  // src/assets/ModelTextures.ts
1829
2144
  var ModelTextures = class {
@@ -1831,11 +2146,21 @@ var ModelTextures = class {
1831
2146
  return this._persistentMetaCache ??= PersistentCache.open("minerender-texturemeta");
1832
2147
  }
1833
2148
  static async get(key) {
1834
- const asset = await this.preload(key);
1835
- if (asset) {
1836
- return ImageLoader.infoToCanvasData(asset);
2149
+ const keyStr = key.serialize();
2150
+ const pending = this.preload(key);
2151
+ const cached = Caching.textureAssetCache.getIfPresent(keyStr);
2152
+ try {
2153
+ const asset = await pending;
2154
+ if (asset) {
2155
+ return await ImageLoader.infoToCanvasData(asset);
2156
+ }
2157
+ return void 0;
2158
+ } catch (err) {
2159
+ if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {
2160
+ Caching.textureAssetCache.invalidate(keyStr);
2161
+ }
2162
+ throw err;
1837
2163
  }
1838
- return void 0;
1839
2164
  }
1840
2165
  static async preload(key) {
1841
2166
  const keyStr = key.serialize();
@@ -1854,7 +2179,7 @@ var ModelTextures = class {
1854
2179
  }
1855
2180
  const keyStr = key.serialize();
1856
2181
  return Caching.textureMetaCache.get(keyStr, (k) => {
1857
- return this.PERSISTENT_META_CACHE.getOrLoad(keyStr, (k1) => {
2182
+ return this.PERSISTENT_META_CACHE.getOrLoad(AssetLoader.persistentKey(keyStr), (k1) => {
1858
2183
  return AssetLoader.get(key, "meta" /* META */).then((asset) => {
1859
2184
  if (asset)
1860
2185
  asset.key = key;
@@ -1909,7 +2234,28 @@ var CanvasImage = class {
1909
2234
  };
1910
2235
 
1911
2236
  // src/Ticker.ts
1912
- var _Ticker = class _Ticker {
2237
+ var Ticker = class _Ticker {
2238
+ static {
2239
+ this.TPS = 20;
2240
+ }
2241
+ static {
2242
+ this.counter = 0;
2243
+ }
2244
+ static {
2245
+ this._tickers = /* @__PURE__ */ new Map();
2246
+ }
2247
+ static {
2248
+ this.oneSecondTps = 0;
2249
+ }
2250
+ static {
2251
+ this.oneSecondTicks = 0;
2252
+ }
2253
+ static {
2254
+ this.fiveSecondTps = 0;
2255
+ }
2256
+ static {
2257
+ this.fiveSecondTicks = 0;
2258
+ }
1913
2259
  static schedule(fn, ms) {
1914
2260
  const handle = setInterval(fn, ms);
1915
2261
  const unref = handle.unref;
@@ -1971,14 +2317,6 @@ var _Ticker = class _Ticker {
1971
2317
  this._tickers.clear();
1972
2318
  }
1973
2319
  };
1974
- _Ticker.TPS = 20;
1975
- _Ticker.counter = 0;
1976
- _Ticker._tickers = /* @__PURE__ */ new Map();
1977
- _Ticker.oneSecondTps = 0;
1978
- _Ticker.oneSecondTicks = 0;
1979
- _Ticker.fiveSecondTps = 0;
1980
- _Ticker.fiveSecondTicks = 0;
1981
- var Ticker = _Ticker;
1982
2320
 
1983
2321
  // src/texture/TextureAtlas.ts
1984
2322
  var TextureAtlas = class {
@@ -2004,18 +2342,24 @@ var TextureAtlas = class {
2004
2342
 
2005
2343
  // src/model/ModelGenerator.ts
2006
2344
  var ModelGenerator = class {
2345
+ static {
2346
+ this.ITEM_LAYERS = ["layer0", "layer1", "layer2", "layer3", "layer4"];
2347
+ }
2007
2348
  static generateItemModel(imageData, layer) {
2349
+ const tintindex = this.ITEM_LAYERS.indexOf(layer);
2008
2350
  const mainElement = {
2009
2351
  from: [0, 0, 7.5],
2010
2352
  to: [16, 16, 8.5],
2011
2353
  faces: {
2012
2354
  "south": {
2013
2355
  uv: [0, 0, 16, 16],
2014
- texture: `#${layer}`
2356
+ texture: `#${layer}`,
2357
+ tintindex
2015
2358
  },
2016
2359
  "north": {
2017
2360
  uv: [16, 0, 0, 16],
2018
- texture: `#${layer}`
2361
+ texture: `#${layer}`,
2362
+ tintindex
2019
2363
  }
2020
2364
  },
2021
2365
  shade: true
@@ -2023,14 +2367,21 @@ var ModelGenerator = class {
2023
2367
  return [mainElement];
2024
2368
  }
2025
2369
  };
2026
- ModelGenerator.ITEM_LAYERS = ["layer0", "layer1", "layer2", "layer3", "layer4"];
2027
2370
 
2028
2371
  // src/UVMapper.ts
2029
- var p6 = prefix("UVMapper");
2372
+ var p5 = prefix("UVMapper");
2030
2373
  var DEFAULT_UV = [0, 0, 16, 16];
2031
2374
  var X = 0;
2032
2375
  var Y = 1;
2033
2376
  var Z = 2;
2377
+ var FACE_UV_AXES = {
2378
+ east: [new import_three9.Vector3(0, 0, -1), new import_three9.Vector3(0, -1, 0)],
2379
+ west: [new import_three9.Vector3(0, 0, 1), new import_three9.Vector3(0, -1, 0)],
2380
+ up: [new import_three9.Vector3(1, 0, 0), new import_three9.Vector3(0, 0, 1)],
2381
+ down: [new import_three9.Vector3(1, 0, 0), new import_three9.Vector3(0, 0, -1)],
2382
+ south: [new import_three9.Vector3(1, 0, 0), new import_three9.Vector3(0, -1, 0)],
2383
+ north: [new import_three9.Vector3(-1, 0, 0), new import_three9.Vector3(0, -1, 0)]
2384
+ };
2034
2385
  var UVMapper = class {
2035
2386
  static makeUv(uvCoord, originalTextureSize, actualTextureSize) {
2036
2387
  if (uvCoord === 0) return 0;
@@ -2126,7 +2477,43 @@ var UVMapper = class {
2126
2477
  return array;
2127
2478
  }
2128
2479
  static facesToUv(faces, originalTextureSize, actualTextureSize) {
2129
- return new import_three8.Float32BufferAttribute(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);
2480
+ return new import_three9.Float32BufferAttribute(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);
2481
+ }
2482
+ static lockUvs(geometry, faces, atlas, rotation) {
2483
+ const uv = geometry.getAttribute("uv");
2484
+ for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {
2485
+ const faceName = CUBE_FACES[faceIndex];
2486
+ const texture = faces[faceName]?.texture?.substring(1);
2487
+ const position = texture && atlas.positions[texture];
2488
+ const size = texture && atlas.sizes[texture];
2489
+ if (!position || !size) continue;
2490
+ const [sourceU, sourceV] = FACE_UV_AXES[faceName];
2491
+ const uAxis = sourceU.clone().applyEuler(rotation);
2492
+ const vAxis = sourceV.clone().applyEuler(rotation);
2493
+ const normal = vAxis.clone().cross(uAxis);
2494
+ const targetFace = CUBE_FACES.find((name) => {
2495
+ const [u, v] = FACE_UV_AXES[name];
2496
+ return v.clone().cross(u).dot(normal) > 0.5;
2497
+ });
2498
+ const [targetU, targetV] = FACE_UV_AXES[targetFace];
2499
+ const uu = Math.round(targetU.dot(uAxis));
2500
+ const uvCross = Math.round(targetU.dot(vAxis));
2501
+ const vu = Math.round(targetV.dot(uAxis));
2502
+ const vv = Math.round(targetV.dot(vAxis));
2503
+ for (let corner = 0; corner < 4; corner++) {
2504
+ const index = faceIndex * 4 + corner;
2505
+ const u = (uv.getX(index) * atlas.image.width - position[0]) / size[0] - 0.5;
2506
+ const v = ((1 - uv.getY(index)) * atlas.image.height - position[1]) / size[1] - 0.5;
2507
+ const lockedU = uu * u + uvCross * v + 0.5;
2508
+ const lockedV = vu * u + vv * v + 0.5;
2509
+ uv.setXY(
2510
+ index,
2511
+ (position[0] + lockedU * size[0]) / atlas.image.width,
2512
+ 1 - (position[1] + lockedV * size[1]) / atlas.image.height
2513
+ );
2514
+ }
2515
+ }
2516
+ uv.needsUpdate = true;
2130
2517
  }
2131
2518
  static async getAtlas(model) {
2132
2519
  const keyStr = model.key.serialize();
@@ -2168,43 +2555,42 @@ var UVMapper = class {
2168
2555
  v1 *= scaleV;
2169
2556
  u2 *= scaleU;
2170
2557
  v2 *= scaleV;
2171
- let tl = new import_three8.Vector2(u1, v1);
2172
- let tr = new import_three8.Vector2(u2, v1);
2173
- let bl = new import_three8.Vector2(u1, v2);
2174
- let br = new import_three8.Vector2(u2, v2);
2558
+ let tl = new import_three9.Vector2(u1, v1);
2559
+ let tr = new import_three9.Vector2(u2, v1);
2560
+ let bl = new import_three9.Vector2(u1, v2);
2561
+ let br = new import_three9.Vector2(u2, v2);
2175
2562
  switch (rotation) {
2176
2563
  case 0:
2177
2564
  case 360:
2178
2565
  default:
2179
2566
  break;
2180
2567
  case 90:
2181
- tl = new import_three8.Vector2(u1, v2);
2182
- tr = new import_three8.Vector2(u1, v1);
2183
- bl = new import_three8.Vector2(u2, v2);
2184
- br = new import_three8.Vector2(u2, v1);
2568
+ tl = new import_three9.Vector2(u1, v2);
2569
+ tr = new import_three9.Vector2(u1, v1);
2570
+ bl = new import_three9.Vector2(u2, v2);
2571
+ br = new import_three9.Vector2(u2, v1);
2185
2572
  break;
2186
2573
  case 180:
2187
- tl = new import_three8.Vector2(u2, v2);
2188
- tr = new import_three8.Vector2(u1, v2);
2189
- bl = new import_three8.Vector2(u2, v1);
2190
- br = new import_three8.Vector2(u1, v1);
2574
+ tl = new import_three9.Vector2(u2, v2);
2575
+ tr = new import_three9.Vector2(u1, v2);
2576
+ bl = new import_three9.Vector2(u2, v1);
2577
+ br = new import_three9.Vector2(u1, v1);
2191
2578
  break;
2192
2579
  case 270:
2193
- tl = new import_three8.Vector2(u2, v1);
2194
- tr = new import_three8.Vector2(u2, v2);
2195
- bl = new import_three8.Vector2(u1, v1);
2196
- br = new import_three8.Vector2(u1, v2);
2580
+ tl = new import_three9.Vector2(u2, v1);
2581
+ tr = new import_three9.Vector2(u2, v2);
2582
+ bl = new import_three9.Vector2(u1, v1);
2583
+ br = new import_three9.Vector2(u1, v2);
2197
2584
  break;
2198
2585
  }
2199
2586
  return [tl, tr, bl, br];
2200
2587
  }
2201
2588
  static async createAtlas(originalModel) {
2202
- var _a;
2203
2589
  const textureMap = {};
2204
2590
  const metaMap = {};
2205
2591
  const model = { ...originalModel };
2206
2592
  const isItemModel = !("elements" in model);
2207
- console.debug(p6, "Creating Atlas for", model.key);
2593
+ console.debug(p5, "Creating Atlas for", model.key);
2208
2594
  if (model.textures) {
2209
2595
  const promises = [];
2210
2596
  const uniqueTextureNames = [];
@@ -2218,7 +2604,7 @@ var UVMapper = class {
2218
2604
  const assetKey = AssetKey.parse("textures", textureValue, model.key);
2219
2605
  promises.push(ModelTextures.get(assetKey).then((asset) => {
2220
2606
  if (!asset) {
2221
- console.warn(p6, "Missing texture", assetKey);
2607
+ console.warn(p5, "Missing texture", assetKey);
2222
2608
  return;
2223
2609
  }
2224
2610
  textureMap[textureKey] = new WrappedImage(asset);
@@ -2230,7 +2616,7 @@ var UVMapper = class {
2230
2616
  }
2231
2617
  await Promise.all(promises);
2232
2618
  const textureCount = uniqueTextureNames.length;
2233
- console.debug(p6, "Creating Atlas for", textureCount, "textures");
2619
+ console.debug(p5, "Creating Atlas for", textureCount, "textures");
2234
2620
  this.fillMissingTextureKeys(model.textures, textureMap);
2235
2621
  this.fillMissingTextureKeys(model.textures, metaMap);
2236
2622
  const sizes = {};
@@ -2250,7 +2636,7 @@ var UVMapper = class {
2250
2636
  this.fillMissingTextureKeys(model.textures, sizes);
2251
2637
  const s = Math.ceil(Math.sqrt(textureCount + 1));
2252
2638
  const size = Math.ceil(s * maxWidth);
2253
- console.debug(p6, "Atlas size:", size);
2639
+ console.debug(p5, "Atlas size:", size);
2254
2640
  const squaredSize = size * size;
2255
2641
  const missing = await ImageLoader.getData("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX/AP8AAACfphTyAAAAFUlEQVQoz2MIhQKGVVAwKjIqQrwIAHRz/wFI17TEAAAAAElFTkSuQmCC");
2256
2642
  const empty = await ImageLoader.getData("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAA5JREFUKM9jGAWjgAIAAAJAAAFSSwuTAAAAAElFTkSuQmCC");
@@ -2279,16 +2665,15 @@ var UVMapper = class {
2279
2665
  if (texture.animated) {
2280
2666
  hasAnimation = true;
2281
2667
  const meta = metaMap[textureKey];
2282
- const frameTime = ((_a = meta == null ? void 0 : meta.animation) == null ? void 0 : _a.frametime) ?? 1;
2668
+ const frameTime = meta?.animation?.frametime ?? 1;
2283
2669
  console.log(meta);
2284
2670
  console.log(frameTime);
2285
2671
  let t = 0;
2286
2672
  let f = 0;
2287
2673
  animatorFunctions[textureKey] = () => {
2288
- var _a2;
2289
2674
  if (t++ >= frameTime) {
2290
2675
  t = 0;
2291
- const frames = (_a2 = meta == null ? void 0 : meta.animation) == null ? void 0 : _a2.frames;
2676
+ const frames = meta?.animation?.frames;
2292
2677
  const frame = frames ? frames[f] : f;
2293
2678
  image.putData(texture.getFrameSectionData(frame), x, y, 0, 0, maxWidth, maxWidth);
2294
2679
  f++;
@@ -2306,10 +2691,10 @@ var UVMapper = class {
2306
2691
  }
2307
2692
  }
2308
2693
  const atlasImageData = image.toDataURL();
2309
- console.log(p6, "Atlas Image for", model.key, atlasImageData);
2694
+ console.log(p5, "Atlas Image for", model.key, atlasImageData);
2310
2695
  this.fillMissingTextureKeys(model.textures, positions);
2311
2696
  if (isItemModel) {
2312
- console.debug(p6, "Generating item model for", model);
2697
+ console.debug(p5, "Generating item model for", model);
2313
2698
  model.elements = [];
2314
2699
  for (let layerName of ModelGenerator.ITEM_LAYERS) {
2315
2700
  const textureImage = textureMap[layerName];
@@ -2317,7 +2702,7 @@ var UVMapper = class {
2317
2702
  model.elements.push(...ModelGenerator.generateItemModel(textureImage.data, layerName));
2318
2703
  }
2319
2704
  }
2320
- console.debug(p6, "Item model elements", model.elements);
2705
+ console.debug(p5, "Item model elements", model.elements);
2321
2706
  }
2322
2707
  if (!model.elements) {
2323
2708
  }
@@ -2335,18 +2720,14 @@ var UVMapper = class {
2335
2720
  this.setCubeFaceUvInArray(uv, faceIndex * 4, [0, 1, 8 / size, (size - 8) / size]);
2336
2721
  continue;
2337
2722
  }
2723
+ if (!face.texture) continue;
2338
2724
  if (!face.uv) {
2339
2725
  face.uv = this.getFallbackUv(element, faceName);
2340
2726
  }
2341
- let faceTexture = face.texture;
2342
- let texPosition;
2343
- let texSize;
2344
- if (faceTexture) {
2345
- faceTexture = faceTexture.substr(1);
2346
- texPosition = positions[faceTexture] || [0, 0];
2347
- texSize = sizes[faceTexture] || [16, 16];
2348
- }
2349
- let texPosV = new import_three8.Vector2(texPosition[0], texPosition[1]);
2727
+ const faceTexture = face.texture.substr(1);
2728
+ const texPosition = positions[faceTexture] || [0, 0];
2729
+ const texSize = sizes[faceTexture] || [16, 16];
2730
+ let texPosV = new import_three9.Vector2(texPosition[0], texPosition[1]);
2350
2731
  const [tl, tr, bl, br] = this.expandAndRotateMcUvs(face.uv, face.rotation, texSize[0], texSize[1]);
2351
2732
  tl.add(texPosV);
2352
2733
  tr.add(texPosV);
@@ -2377,7 +2758,7 @@ var UVMapper = class {
2377
2758
  hasTransparency
2378
2759
  );
2379
2760
  } else {
2380
- console.warn(p6, "Model does not have any textures", model);
2761
+ console.warn(p5, "Model does not have any textures", model);
2381
2762
  }
2382
2763
  return void 0;
2383
2764
  }
@@ -2419,18 +2800,18 @@ var MinecraftCubeTexture = class {
2419
2800
  }
2420
2801
  getUvEast(w, h, l) {
2421
2802
  return [
2422
- [this.mapW(this.u), this.mapH(this.v + l + h)],
2423
- [this.mapW(this.u + l), this.mapH(this.v + l + h)],
2424
- [this.mapW(this.u), this.mapH(this.v + l)],
2425
- [this.mapW(this.u + l), this.mapH(this.v + l)]
2803
+ [this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
2804
+ [this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
2805
+ [this.mapW(this.u + l + w + l), this.mapH(this.v + l)],
2806
+ [this.mapW(this.u + l + w), this.mapH(this.v + l)]
2426
2807
  ];
2427
2808
  }
2428
2809
  getUvWest(w, h, l) {
2429
2810
  return [
2430
- [this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
2431
- [this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
2432
- [this.mapW(this.u + l + w), this.mapH(this.v + l)],
2433
- [this.mapW(this.u + l + w + l), this.mapH(this.v + l)]
2811
+ [this.mapW(this.u + l), this.mapH(this.v + l + h)],
2812
+ [this.mapW(this.u), this.mapH(this.v + l + h)],
2813
+ [this.mapW(this.u + l), this.mapH(this.v + l)],
2814
+ [this.mapW(this.u), this.mapH(this.v + l)]
2434
2815
  ];
2435
2816
  }
2436
2817
  getUvUp(w, h, l) {
@@ -2443,26 +2824,26 @@ var MinecraftCubeTexture = class {
2443
2824
  }
2444
2825
  getUvDown(w, h, l) {
2445
2826
  return [
2446
- [this.mapW(this.u + l), this.mapH(this.v + l)],
2447
- [this.mapW(this.u + l + w), this.mapH(this.v + l)],
2448
2827
  [this.mapW(this.u + l), this.mapH(this.v)],
2449
- [this.mapW(this.u + l + w), this.mapH(this.v)]
2828
+ [this.mapW(this.u + l + w), this.mapH(this.v)],
2829
+ [this.mapW(this.u + l), this.mapH(this.v + l)],
2830
+ [this.mapW(this.u + l + w), this.mapH(this.v + l)]
2450
2831
  ];
2451
2832
  }
2452
2833
  getUvSouth(w, h, l) {
2453
2834
  return [
2454
- [this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
2455
2835
  [this.mapW(this.u + l + w + l + w), this.mapH(this.v + l + h)],
2456
- [this.mapW(this.u + l + w + l), this.mapH(this.v + l)],
2457
- [this.mapW(this.u + l + w + l + w), this.mapH(this.v + l)]
2836
+ [this.mapW(this.u + l + w + l), this.mapH(this.v + l + h)],
2837
+ [this.mapW(this.u + l + w + l + w), this.mapH(this.v + l)],
2838
+ [this.mapW(this.u + l + w + l), this.mapH(this.v + l)]
2458
2839
  ];
2459
2840
  }
2460
2841
  getUvNorth(w, h, l) {
2461
2842
  return [
2462
- [this.mapW(this.u + l), this.mapH(this.v + l + h)],
2463
2843
  [this.mapW(this.u + l + w), this.mapH(this.v + l + h)],
2464
- [this.mapW(this.u + l), this.mapH(this.v + l)],
2465
- [this.mapW(this.u + l + w), this.mapH(this.v + l)]
2844
+ [this.mapW(this.u + l), this.mapH(this.v + l + h)],
2845
+ [this.mapW(this.u + l + w), this.mapH(this.v + l)],
2846
+ [this.mapW(this.u + l), this.mapH(this.v + l)]
2466
2847
  ];
2467
2848
  }
2468
2849
  getFaceUv(face, w, h, l) {
@@ -2481,10 +2862,12 @@ var MinecraftCubeTexture = class {
2481
2862
  return this.getUvNorth(w, h, l);
2482
2863
  }
2483
2864
  }
2484
- toUvArray(w, h, l) {
2865
+ toUvArray(w, h, l, mirror = false) {
2485
2866
  const uv = [];
2486
2867
  for (let i = 0; i < CUBE_FACES.length; i++) {
2487
- UVMapper.setFaceUvInArray(uv, i * 4, this.getFaceUv(CUBE_FACES[i], w, h, l));
2868
+ const face = mirror && i < 2 ? CUBE_FACES[1 - i] : CUBE_FACES[i];
2869
+ const corners = this.getFaceUv(face, w, h, l);
2870
+ UVMapper.setFaceUvInArray(uv, i * 4, mirror ? [corners[1], corners[0], corners[3], corners[2]] : corners);
2488
2871
  }
2489
2872
  return uv;
2490
2873
  }
@@ -2514,76 +2897,85 @@ function shutdown() {
2514
2897
  Caching.end();
2515
2898
  }
2516
2899
 
2900
+ // src/error/MineRenderError.ts
2901
+ var MineRenderError = class _MineRenderError extends Error {
2902
+ constructor(msg) {
2903
+ super(msg);
2904
+ Object.setPrototypeOf(this, _MineRenderError.prototype);
2905
+ }
2906
+ get name() {
2907
+ return "MineRenderError";
2908
+ }
2909
+ };
2910
+
2517
2911
  // src/assets/Entities.ts
2518
- var import_typescript_memoize3 = require("typescript-memoize");
2519
2912
  var Entities = class {
2520
- static async getBlockEntityModels() {
2521
- const key = AssetKey.parse("models", "minerender:blockEntityModels");
2522
- console.log(key);
2523
- return AssetLoader.get(key, "json" /* JSON */);
2524
- }
2525
- static async getEntityModels() {
2526
- const key = AssetKey.parse("models", "minerender:entityModels");
2527
- console.log(key);
2528
- return AssetLoader.get(key, "json" /* JSON */);
2529
- }
2530
- // BlockEntity names are hardcoded
2531
- static async getBlockList() {
2532
- const models = await this.getBlockEntityModels();
2533
- if (!models) {
2534
- return [];
2535
- }
2536
- return Object.keys(models);
2537
- }
2538
2913
  static async getEntityList() {
2539
- const models = await this.getEntityModels();
2540
- if (!models) {
2541
- return [];
2542
- }
2543
- return Object.keys(models);
2544
- }
2545
- static async getBlock(modelKey, textureKey) {
2546
- const models = await this.getBlockEntityModels();
2547
- if (!models) {
2548
- return void 0;
2549
- }
2550
- if (!textureKey) {
2551
- textureKey = modelKey;
2552
- }
2553
- const baseKey = modelKey.path.includes("/") ? new BasicAssetKey(modelKey.namespace, modelKey.path.split("/")[0]) : modelKey;
2554
- return {
2555
- key: textureKey,
2556
- parts: models[baseKey.toNamespacedString()]
2914
+ const collect = async (path) => {
2915
+ const prefix2 = path ? `${path}/` : "";
2916
+ const key = new AssetKey(DEFAULT_NAMESPACE, `${prefix2}_list`, void 0, void 0, "entity-models", ".json");
2917
+ const list = await Caching.listAssetCache.get(key.serialize(), () => AssetLoader.get(key, "list" /* LIST */));
2918
+ if (!list) return [];
2919
+ const files = list.files.filter((file) => file.endsWith(".json") && file !== "_list.json").map((file) => `${prefix2}${file.slice(0, -5)}`);
2920
+ const children = await Promise.all(list.directories.map((directory) => collect(`${prefix2}${directory}`)));
2921
+ return [...files, ...children.flat()];
2557
2922
  };
2923
+ return collect("");
2924
+ }
2925
+ static async getEntity(modelKey, textureKey, options) {
2926
+ const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
2927
+ const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json");
2928
+ const model = await Caching.entityModelCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
2929
+ if (!model) return void 0;
2930
+ const layerName = options?.layer ?? "main";
2931
+ const layer = model.layers[layerName];
2932
+ if (!layer) {
2933
+ throw new MineRenderError(`Entity ${model.id} has no layer "${layerName}". Available layers: ${Object.keys(model.layers).join(", ")}`);
2934
+ }
2935
+ let texture;
2936
+ if (textureKey) {
2937
+ const path2 = isAssetKey(textureKey) ? textureKey.getFullPath() : textureKey.path;
2938
+ texture = isAssetKey(textureKey) && textureKey.assetType === "textures" && path2.startsWith("entity/") ? textureKey : new AssetKey(textureKey.namespace, path2, "textures", "entity", "assets", ".png", isAssetKey(textureKey) ? textureKey.root : void 0);
2939
+ } else if (layer.textureLocation !== void 0) {
2940
+ texture = AssetKey.parse("textures", layer.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
2941
+ } else {
2942
+ texture = await this.resolveTexture(modelKey);
2943
+ }
2944
+ return { key: textureKey ?? modelKey, texture, layer, id: model.id };
2945
+ }
2946
+ static async resolveTexture(modelKey) {
2947
+ const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
2948
+ const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models", ".json");
2949
+ return Caching.entityTextureCache.get(key.serialize(), async () => {
2950
+ const name = path.split("/").pop();
2951
+ for (const candidate of [path, `${path}/${name}`]) {
2952
+ const texture = new AssetKey(modelKey.namespace, candidate, "textures", "entity", "assets", ".png");
2953
+ if (await ModelTextures.get(texture)) return texture;
2954
+ }
2955
+ const listKey = new AssetKey(modelKey.namespace, "_list", `${name}_variant`, void 0, "data", ".json");
2956
+ const list = await AssetLoader.get(listKey, "list" /* LIST */);
2957
+ const files = list?.files.filter((file2) => file2.endsWith(".json") && file2 !== "_list.json");
2958
+ const file = files?.find((file2) => file2 === "temperate.json") ?? files?.[0];
2959
+ if (!file) return void 0;
2960
+ const variantKey = new AssetKey(modelKey.namespace, file.slice(0, -5), `${name}_variant`, void 0, "data", ".json");
2961
+ const variant = await AssetLoader.get(variantKey, "json" /* JSON */);
2962
+ const assets = variant?.assets;
2963
+ const textureId = variant?.asset_id ?? (typeof assets?.wild === "string" ? assets.wild : Object.values(assets ?? {}).find((value) => typeof value === "string"));
2964
+ return typeof textureId === "string" ? AssetKey.parse("textures", textureId) : void 0;
2965
+ });
2558
2966
  }
2559
- static async getEntity(modelKey, textureKey) {
2560
- const models = await this.getEntityModels();
2561
- if (!models) {
2562
- return void 0;
2563
- }
2564
- if (!textureKey) {
2565
- textureKey = modelKey;
2566
- }
2567
- const baseKey = modelKey.path.includes("/") ? new BasicAssetKey(modelKey.namespace, modelKey.path.split("/")[0]) : modelKey;
2568
- return {
2569
- key: textureKey,
2570
- parts: models[baseKey.toNamespacedString()]
2571
- };
2967
+ /** @deprecated Use getEntityList(); block entities share the entity dataset. */
2968
+ static getBlockList() {
2969
+ return this.getEntityList();
2970
+ }
2971
+ /** @deprecated Use getEntity(); block entities share the entity dataset. */
2972
+ static getBlock(modelKey, textureKey, options) {
2973
+ return this.getEntity(modelKey, textureKey, options);
2572
2974
  }
2573
- };
2574
- __decorateClass([
2575
- (0, import_typescript_memoize3.Memoize)()
2576
- ], Entities, "getBlockEntityModels", 1);
2577
- __decorateClass([
2578
- (0, import_typescript_memoize3.Memoize)()
2579
- ], Entities, "getEntityModels", 1);
2580
- var EntityModels = class {
2581
- };
2582
- var BlockEntityModels = class {
2583
2975
  };
2584
2976
 
2585
2977
  // src/renderer/SceneObject.ts
2586
- var import_three9 = require("three");
2978
+ var import_three10 = require("three");
2587
2979
 
2588
2980
  // src/instance/InstanceReference.ts
2589
2981
  var InstanceReference = class {
@@ -2628,30 +3020,27 @@ function isInstanceReference(obj) {
2628
3020
  return obj.isInstanceReference;
2629
3021
  }
2630
3022
 
2631
- // src/error/MineRenderError.ts
2632
- var MineRenderError = class _MineRenderError extends Error {
2633
- constructor(msg) {
2634
- super(msg);
2635
- Object.setPrototypeOf(this, _MineRenderError.prototype);
2636
- }
2637
- get name() {
2638
- return "MineRenderError";
2639
- }
2640
- };
2641
-
2642
3023
  // src/renderer/SceneObject.ts
2643
- var import_ts_deepmerge4 = __toESM(require_dist());
2644
- var p7 = prefix("SceneObject");
2645
- var _SceneObject = class _SceneObject extends import_three9.Object3D {
3024
+ var import_ts_deepmerge3 = __toESM(require_dist());
3025
+ var p6 = prefix("SceneObject");
3026
+ var SceneObject = class _SceneObject extends import_three10.Object3D {
2646
3027
  constructor(options) {
2647
3028
  super();
2648
3029
  this.isSceneObject = true;
2649
3030
  this.materialCallbacks = {};
2650
3031
  this._isInstanced = false;
2651
3032
  this._instanceCounter = 0;
2652
- this.options = (0, import_ts_deepmerge4.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
3033
+ this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
2653
3034
  console.log("SceneObject options", this.options);
2654
3035
  }
3036
+ static {
3037
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge3.default)({}, {
3038
+ instanceMeshes: true,
3039
+ maxInstanceCount: 50,
3040
+ mergeMeshes: true,
3041
+ wireframe: false
3042
+ });
3043
+ }
2655
3044
  set scene(scene) {
2656
3045
  if (!!this._scene) throw new MineRenderError("Scene already set");
2657
3046
  this._scene = scene;
@@ -2680,7 +3069,7 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2680
3069
  return group;
2681
3070
  }
2682
3071
  createGroup(name, x = 0, y = 0, z = 0, offsetAxis, offset = 0) {
2683
- const obj = new import_three9.Object3D();
3072
+ const obj = new import_three10.Object3D();
2684
3073
  if (name) {
2685
3074
  obj.name = `group:${name}`;
2686
3075
  }
@@ -2730,7 +3119,7 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2730
3119
  return mesh;
2731
3120
  }
2732
3121
  createMesh(name, geometry, material, offsetAxis, offset = 0) {
2733
- const mesh = new import_three9.Mesh(geometry, material);
3122
+ const mesh = new import_three10.Mesh(geometry, material);
2734
3123
  if (name) {
2735
3124
  mesh.name = `mesh:${name}`;
2736
3125
  }
@@ -2742,7 +3131,8 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2742
3131
  return mesh;
2743
3132
  }
2744
3133
  createInstancedMesh(name, geometry, material, count) {
2745
- const mesh = new import_three9.InstancedMesh(geometry, material, count);
3134
+ const mesh = new import_three10.InstancedMesh(geometry, material, count);
3135
+ mesh.count = 0;
2746
3136
  if (name) {
2747
3137
  mesh.name = `mesh:${name}`;
2748
3138
  }
@@ -2763,15 +3153,8 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2763
3153
  return this.toggleObjectVisibility(this.getMeshByName(name), visible);
2764
3154
  }
2765
3155
  iterateAllMeshes(cb) {
2766
- this.children.forEach((obj) => {
2767
- if (obj.isMesh) {
2768
- cb(obj);
2769
- }
2770
- obj.children.forEach((obj1) => {
2771
- if (obj1.isMesh) {
2772
- cb(obj1);
2773
- }
2774
- });
3156
+ this.traverse((obj) => {
3157
+ if (isMesh(obj)) cb(obj);
2775
3158
  });
2776
3159
  }
2777
3160
  //</editor-fold>
@@ -2819,10 +3202,14 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2819
3202
  nextInstance() {
2820
3203
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2821
3204
  const i = this._instanceCounter++;
2822
- this.setMatrixAt(i, new import_three9.Matrix4());
2823
- console.debug(p7, "nextInstance " + i);
3205
+ this.setMatrixAt(i, new import_three10.Matrix4());
3206
+ const mesh = this.children[0];
3207
+ if (mesh && isInstancedMesh(mesh)) {
3208
+ mesh.count = Math.min(this._instanceCounter, mesh.instanceMatrix.count);
3209
+ }
3210
+ console.debug(p6, "nextInstance " + i);
2824
3211
  if (i === this.options.maxInstanceCount) {
2825
- console.warn(p7, "Max instance count reached for " + this);
3212
+ console.warn(p6, "Max instance count reached for " + this);
2826
3213
  }
2827
3214
  if (this.scene) {
2828
3215
  this.scene.stats.instanceCount++;
@@ -2832,7 +3219,7 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2832
3219
  }
2833
3220
  //</editor-fold>
2834
3221
  //<editor-fold desc="TRANSFORMATION">
2835
- getMatrixAt(index, matrix = new import_three9.Matrix4()) {
3222
+ getMatrixAt(index, matrix = new import_three10.Matrix4()) {
2836
3223
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2837
3224
  const child = this.children[0];
2838
3225
  if (child && isInstancedMesh(child)) {
@@ -2851,16 +3238,16 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2851
3238
  }
2852
3239
  setPositionRotationScaleAt(index, position, rotation, scale) {
2853
3240
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2854
- const oldPosition = new import_three9.Vector3();
2855
- const oldRotation = new import_three9.Quaternion();
2856
- const oldScale = new import_three9.Vector3();
2857
- const matrix = new import_three9.Matrix4();
3241
+ const oldPosition = new import_three10.Vector3();
3242
+ const oldRotation = new import_three10.Quaternion();
3243
+ const oldScale = new import_three10.Vector3();
3244
+ const matrix = new import_three10.Matrix4();
2858
3245
  if (!scale || !rotation || !position) {
2859
3246
  this.getMatrixAt(index, matrix).decompose(oldPosition, oldRotation, oldScale);
2860
3247
  }
2861
3248
  matrix.compose(
2862
3249
  position ? position : oldPosition,
2863
- rotation ? new import_three9.Quaternion().setFromEuler(rotation) : oldRotation,
3250
+ rotation ? new import_three10.Quaternion().setFromEuler(rotation) : oldRotation,
2864
3251
  scale ? scale : oldScale
2865
3252
  );
2866
3253
  this.setMatrixAt(index, matrix);
@@ -2869,7 +3256,7 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2869
3256
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2870
3257
  this.setPositionRotationScaleAt(index, position);
2871
3258
  }
2872
- getPositionAt(index, vector = new import_three9.Vector3()) {
3259
+ getPositionAt(index, vector = new import_three10.Vector3()) {
2873
3260
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2874
3261
  const matrix = this.getMatrixAt(index);
2875
3262
  vector.setFromMatrixPosition(matrix);
@@ -2879,7 +3266,7 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2879
3266
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2880
3267
  this.setPositionRotationScaleAt(index, void 0, rotation, void 0);
2881
3268
  }
2882
- getRotationAt(index, euler = new import_three9.Euler()) {
3269
+ getRotationAt(index, euler = new import_three10.Euler()) {
2883
3270
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2884
3271
  const matrix = this.getMatrixAt(index);
2885
3272
  euler.setFromRotationMatrix(matrix);
@@ -2889,7 +3276,7 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2889
3276
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2890
3277
  this.setPositionRotationScaleAt(index, void 0, void 0, scale);
2891
3278
  }
2892
- getScaleAt(index, vector = new import_three9.Vector3()) {
3279
+ getScaleAt(index, vector = new import_three10.Vector3()) {
2893
3280
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2894
3281
  const matrix = this.getMatrixAt(index);
2895
3282
  vector.setFromMatrixScale(matrix);
@@ -2993,34 +3380,28 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2993
3380
  this.notifyDirty();
2994
3381
  }
2995
3382
  removeFromScene() {
2996
- var _a;
2997
- (_a = this._scene) == null ? void 0 : _a.remove(this);
3383
+ this._scene?.remove(this);
2998
3384
  this.notifyDirty();
2999
3385
  }
3000
3386
  //</editor-fold>
3001
3387
  };
3002
- _SceneObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, {
3003
- instanceMeshes: true,
3004
- maxInstanceCount: 50,
3005
- mergeMeshes: true,
3006
- wireframe: false
3007
- });
3008
- var SceneObject = _SceneObject;
3009
3388
  function isSceneObject(obj) {
3010
3389
  return obj.isSceneObject;
3011
3390
  }
3012
3391
 
3013
3392
  // src/entity/scene/EntityObject.ts
3014
- var import_ts_deepmerge5 = __toESM(require_dist());
3015
- var import_three11 = require("three");
3016
- var THREE2 = __toESM(require("three"));
3017
- var EntityObject = class extends SceneObject {
3393
+ var import_ts_deepmerge4 = __toESM(require_dist());
3394
+ var import_three12 = require("three");
3395
+ var EntityObject = class _EntityObject extends SceneObject {
3018
3396
  constructor(entity, options) {
3019
3397
  super();
3020
3398
  this.entity = entity;
3021
3399
  this.isEntityObject = true;
3022
3400
  this.meshesCreated = false;
3023
- this.options = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
3401
+ this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
3402
+ }
3403
+ static {
3404
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, { flip: true });
3024
3405
  }
3025
3406
  async init() {
3026
3407
  this.createMeshes();
@@ -3029,67 +3410,76 @@ var EntityObject = class extends SceneObject {
3029
3410
  dispose() {
3030
3411
  super.dispose();
3031
3412
  }
3032
- async loadTextures() {
3033
- var _a;
3034
- this.imageData = await ModelTextures.get(new AssetKey(
3035
- ((_a = this.entity.key) == null ? void 0 : _a.namespace) ?? DEFAULT_NAMESPACE,
3036
- this.entity.key.path,
3037
- //TODO: texture may differ from entity name; most of them are in subdirectories for multiple variants etc.
3413
+ get textureKey() {
3414
+ if (this.entity.texture) return this.entity.texture;
3415
+ const key = this.entity.key;
3416
+ return new AssetKey(
3417
+ key.namespace,
3418
+ isAssetKey(key) ? key.getFullPath() : key.path,
3038
3419
  "textures",
3039
3420
  "entity",
3040
3421
  "assets",
3041
3422
  ".png"
3042
- ));
3423
+ );
3424
+ }
3425
+ async loadTextures() {
3426
+ this.imageData = await ModelTextures.get(this.textureKey);
3043
3427
  }
3044
- //TODO: abstract this, since extracted model data can be used for entities, blocks, players
3045
3428
  createMeshes(force = false) {
3046
3429
  if (this.meshesCreated && !force) return;
3047
- const mat = Materials.MISSING_TEXTURE;
3048
- for (let partName in this.entity.parts) {
3049
- const part = this.entity.parts[partName];
3050
- const texture = new MinecraftCubeTexture(part.textureOffsetU, part.textureOffsetV, part.textureWidth, part.textureHeight);
3051
- const partAnchor = new import_three11.Object3D();
3052
- partAnchor.position.x = part.pivotX;
3053
- partAnchor.position.y = part.pivotY;
3054
- partAnchor.position.z = part.pivotZ;
3055
- for (let cube of part.cubes) {
3056
- const w = cube.maxX - cube.minX;
3057
- const h = cube.maxY - cube.minY;
3058
- const l = cube.maxZ - cube.minZ;
3059
- const uv = texture.toUvArray(w, h, l);
3060
- const cubeGeo = this._getBoxGeometryForDimensionsAndUv(w, h, l, uv).clone();
3061
- cubeGeo.applyMatrix4(new THREE2.Matrix4().makeTranslation(w / 2, h / 2, l / 2));
3062
- cubeGeo.applyMatrix4(new THREE2.Matrix4().makeTranslation(cube.minX, cube.minY, cube.minZ));
3063
- applyModelPartRotation(part, cubeGeo);
3064
- const mesh = this.createMesh(partName, cubeGeo, mat);
3065
- partAnchor.add(mesh);
3066
- if (this.options.wireframe) {
3067
- addWireframeToMesh(cubeGeo, mesh);
3068
- }
3069
- }
3070
- this.add(partAnchor);
3071
- }
3430
+ const modelRoot = new import_three12.Object3D();
3431
+ if (this.options.flip) modelRoot.scale.set(-1, -1, 1);
3432
+ this.add(modelRoot);
3433
+ this.createPart("root", this.entity.layer.root, modelRoot, this.entity.layer.texture, Materials.MISSING_TEXTURE);
3072
3434
  this.meshesCreated = true;
3073
3435
  }
3074
- async applyTextures() {
3075
- var _a;
3076
- const textureAsset = await ModelTextures.preload(new AssetKey(
3077
- ((_a = this.entity.key) == null ? void 0 : _a.namespace) ?? DEFAULT_NAMESPACE,
3078
- this.entity.key.path,
3079
- "textures",
3080
- "entity",
3081
- "assets",
3082
- ".png"
3083
- ));
3084
- if (textureAsset) {
3085
- let mat = Materials.getImage({ texture: { src: textureAsset.src } });
3086
- this.iterateAllMeshes((mesh) => {
3087
- mesh.material = mat;
3088
- });
3436
+ createPart(name, part, parent, textureSize, material) {
3437
+ const anchor = this.createGroup(name);
3438
+ anchor.position.fromArray(part.pose.offset);
3439
+ anchor.rotation.set(...part.pose.rotation, "ZYX");
3440
+ anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);
3441
+ parent.add(anchor);
3442
+ const size = part.texture ?? textureSize;
3443
+ for (const cube of part.cubes) {
3444
+ const [width, height, depth] = cube.size;
3445
+ const [growX, growY, growZ] = cube.grow ?? [0, 0, 0];
3446
+ const texture = new MinecraftCubeTexture(...cube.uv, ...size);
3447
+ const uv = size[0] === 0 || size[1] === 0 ? new Array(48).fill(0) : texture.toUvArray(width, height, depth, cube.mirror);
3448
+ const geometry = this._getBoxGeometryForDimensionsAndUv(
3449
+ width + growX * 2,
3450
+ height + growY * 2,
3451
+ depth + growZ * 2,
3452
+ uv
3453
+ ).clone();
3454
+ geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
3455
+ const mesh = this.createMesh(name, geometry, material);
3456
+ anchor.add(mesh);
3457
+ if (this.options.wireframe) addWireframeToMesh(geometry, mesh);
3458
+ }
3459
+ for (const [childName, child] of Object.entries(part.children)) {
3460
+ this.createPart(childName, child, anchor, size, material);
3089
3461
  }
3090
3462
  }
3463
+ async applyTextures() {
3464
+ const assetKeyStr = this.textureKey.serialize();
3465
+ const keyStr = `entity:${assetKeyStr}`;
3466
+ let mat = Caching.materialCache.getIfPresent(keyStr);
3467
+ if (!mat) {
3468
+ const pending = this.loadTextures();
3469
+ const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
3470
+ await pending;
3471
+ if (!this.imageData) return;
3472
+ const canvas = this.imageData.data.canvas;
3473
+ const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
3474
+ mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
3475
+ this.imageData = void 0;
3476
+ }
3477
+ this.iterateAllMeshes((mesh) => {
3478
+ mesh.material = mat;
3479
+ });
3480
+ this.notifyDirty();
3481
+ }
3091
3482
  };
3092
- EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, {});
3093
3483
  function isEntityObject(obj) {
3094
3484
  return obj.isEntityObject;
3095
3485
  }
@@ -3100,16 +3490,16 @@ var GuiObject = class extends SceneObject {
3100
3490
  };
3101
3491
 
3102
3492
  // src/inspector/SceneInspector.ts
3103
- var import_three12 = require("three");
3104
- var p8 = prefix("SceneInspector");
3493
+ var import_three13 = require("three");
3494
+ var p7 = prefix("SceneInspector");
3105
3495
  var help = "<span>Ctrl+Click to Select<br/></span><br/>";
3106
3496
  var SceneInspector = class {
3107
3497
  constructor(renderer) {
3108
3498
  this.renderer = renderer;
3109
- this.mouse = new import_three12.Vector2();
3499
+ this.mouse = new import_three13.Vector2();
3110
3500
  this.objectInfoContainer = document.createElement("div");
3111
3501
  this.objectControlsContainer = document.createElement("div");
3112
- this.raycaster = new import_three12.Raycaster();
3502
+ this.raycaster = new import_three13.Raycaster();
3113
3503
  this.init();
3114
3504
  }
3115
3505
  init() {
@@ -3130,8 +3520,7 @@ var SceneInspector = class {
3130
3520
  return out;
3131
3521
  }
3132
3522
  onClick(event) {
3133
- var _a;
3134
- if (((_a = event.target) == null ? void 0 : _a.nodeName) !== "CANVAS") return;
3523
+ if (event.target?.nodeName !== "CANVAS") return;
3135
3524
  if (!event.ctrlKey) return;
3136
3525
  setTimeout(() => {
3137
3526
  this.mouse.x = event.clientX / window.innerWidth * 2 - 1;
@@ -3171,7 +3560,7 @@ var SceneInspector = class {
3171
3560
  }
3172
3561
  selectObject(targetObject, targetIntersection) {
3173
3562
  this.selectedObject = targetObject;
3174
- console.log(p8, "selected", targetObject);
3563
+ console.log(p7, "selected", targetObject);
3175
3564
  this.redraw(targetObject, targetIntersection);
3176
3565
  }
3177
3566
  redraw(targetObject, targetIntersection) {
@@ -3469,7 +3858,7 @@ var SceneStatsDisplay = class {
3469
3858
  };
3470
3859
 
3471
3860
  // src/instance/InstanceManager.ts
3472
- var p9 = prefix("InstanceManager");
3861
+ var p8 = prefix("InstanceManager");
3473
3862
  var InstanceManager = class {
3474
3863
  constructor() {
3475
3864
  this.isInstanceManager = true;
@@ -3477,7 +3866,7 @@ var InstanceManager = class {
3477
3866
  }
3478
3867
  async get(key) {
3479
3868
  if (key in this.instanceCache) {
3480
- console.debug(p9, "key in cache", key);
3869
+ console.debug(p8, "key in cache", key);
3481
3870
  return (await this.instanceCache[key]).nextInstance();
3482
3871
  }
3483
3872
  return void 0;
@@ -3486,13 +3875,17 @@ var InstanceManager = class {
3486
3875
  if (key in this.instanceCache) {
3487
3876
  return await this.get(key);
3488
3877
  }
3489
- console.debug(p9, "key not in cache", key);
3490
- this.instanceCache[key] = new Promise(async (resolve) => {
3491
- const obj = await supplier();
3492
- const instance = obj.nextInstance();
3493
- resolve(instance);
3494
- });
3495
- return await this.instanceCache[key];
3878
+ console.debug(p8, "key not in cache", key);
3879
+ const pending = Promise.resolve().then(supplier).then((obj) => obj.nextInstance());
3880
+ this.instanceCache[key] = pending;
3881
+ try {
3882
+ return await pending;
3883
+ } catch (error) {
3884
+ if (this.instanceCache[key] === pending) {
3885
+ delete this.instanceCache[key];
3886
+ }
3887
+ throw error;
3888
+ }
3496
3889
  }
3497
3890
  reset() {
3498
3891
  for (let instanceCacheKey in this.instanceCache) {
@@ -3509,20 +3902,6 @@ function isInstanceable(obj) {
3509
3902
  return "nextInstance" in obj;
3510
3903
  }
3511
3904
 
3512
- // src/model/DisplayPosition.ts
3513
- var DisplayPosition = /* @__PURE__ */ ((DisplayPosition2) => {
3514
- DisplayPosition2["THIRDPERSON_RIGHTHAND"] = "thirdperson_righthand";
3515
- DisplayPosition2["THIRDPERSON_LEFTHAND"] = "thirdperson_lefthand";
3516
- DisplayPosition2["FIRSTPERSON_RIGHTHAND"] = "firstperson_righthand";
3517
- DisplayPosition2["FIRSTPERSON_LEFTHAND"] = "firstperson_lefthand";
3518
- DisplayPosition2["GUI"] = "gui";
3519
- DisplayPosition2["HEAD"] = "head";
3520
- DisplayPosition2["GROUND"] = "ground";
3521
- DisplayPosition2["FIXED"] = "fixed";
3522
- return DisplayPosition2;
3523
- })(DisplayPosition || {});
3524
- var DISPLAY_POSITIONS = Object.values(DisplayPosition);
3525
-
3526
3905
  // src/model/GuiLight.ts
3527
3906
  var GuiLight = /* @__PURE__ */ ((GuiLight2) => {
3528
3907
  GuiLight2["FRONT"] = "front";
@@ -3545,11 +3924,96 @@ function isQuadArray(obj) {
3545
3924
  return Array.isArray(obj) && obj.length === 4;
3546
3925
  }
3547
3926
 
3927
+ // src/model/block/blockTints.json
3928
+ var blockTints_default = {
3929
+ "minecraft:large_fern": { source: "grass" },
3930
+ "minecraft:tall_grass": { source: "grass" },
3931
+ "minecraft:grass_block": { source: "grass" },
3932
+ "minecraft:fern": { source: "grass" },
3933
+ "minecraft:grass": { source: "grass" },
3934
+ "minecraft:short_grass": { source: "grass" },
3935
+ "minecraft:potted_fern": { source: "grass" },
3936
+ "minecraft:bush": { source: "grass" },
3937
+ "minecraft:pink_petals": { source: "grass", untinted: [0] },
3938
+ "minecraft:wildflowers": { source: "grass", untinted: [0] },
3939
+ "minecraft:spruce_leaves": { source: "constant", color: 6396257 },
3940
+ "minecraft:birch_leaves": { source: "constant", color: 8431445 },
3941
+ "minecraft:oak_leaves": { source: "constant", color: 4764952 },
3942
+ "minecraft:jungle_leaves": { source: "constant", color: 4764952 },
3943
+ "minecraft:acacia_leaves": { source: "constant", color: 4764952 },
3944
+ "minecraft:dark_oak_leaves": { source: "constant", color: 4764952 },
3945
+ "minecraft:vine": { source: "constant", color: 4764952 },
3946
+ "minecraft:mangrove_leaves": { source: "constant", color: 4764952 },
3947
+ "minecraft:leaf_litter": { source: "constant", color: 6044722 },
3948
+ "minecraft:water_cauldron": { source: "constant", color: 4159204 },
3949
+ "minecraft:redstone_wire": { source: "redstone" },
3950
+ "minecraft:attached_melon_stem": { source: "constant", color: 14731036 },
3951
+ "minecraft:attached_pumpkin_stem": { source: "constant", color: 14731036 },
3952
+ "minecraft:melon_stem": { source: "stem" },
3953
+ "minecraft:pumpkin_stem": { source: "stem" },
3954
+ "minecraft:lily_pad": { source: "constant", color: 7455580 }
3955
+ };
3956
+
3957
+ // src/model/block/BlockTints.ts
3958
+ var rules = blockTints_default;
3959
+ var BlockTints = class {
3960
+ /** Resolves block preview colors without biome context; explicit tints take precedence. */
3961
+ static async get(key, state, model, tints) {
3962
+ const rule = key && rules[key.toNamespacedString()];
3963
+ if (!key || !rule) return tints;
3964
+ const indices = /* @__PURE__ */ new Set();
3965
+ for (const element of model.elements ?? []) {
3966
+ for (const face of Object.values(element.faces)) {
3967
+ const index = face?.tintindex;
3968
+ if (index !== void 0 && index >= 0 && tints?.[index] === void 0 && !rule.untinted?.includes(index)) {
3969
+ indices.add(index);
3970
+ }
3971
+ }
3972
+ }
3973
+ if (!indices.size) return tints;
3974
+ let color;
3975
+ switch (rule.source) {
3976
+ case "constant":
3977
+ color = rule.color;
3978
+ break;
3979
+ case "grass":
3980
+ color = await this.grassColor(key);
3981
+ break;
3982
+ case "redstone": {
3983
+ const power = Number(state.power ?? 0) / 15;
3984
+ const red = power * 0.6 + (power > 0 ? 0.4 : 0.3);
3985
+ const green = Math.max(0, power * power * 0.7 - 0.5);
3986
+ const blue = Math.max(0, power * power * 0.6 - 0.7);
3987
+ color = Math.floor(red * 255) << 16 | Math.floor(green * 255) << 8 | Math.floor(blue * 255);
3988
+ break;
3989
+ }
3990
+ case "stem": {
3991
+ const age = Number(state.age ?? 0);
3992
+ color = age * 32 << 16 | 255 - age * 8 << 8 | age * 4;
3993
+ break;
3994
+ }
3995
+ }
3996
+ return { ...Object.fromEntries([...indices].map((index) => [index, color])), ...tints };
3997
+ }
3998
+ static async grassColor(origin) {
3999
+ const key = AssetKey.parse("textures", "minecraft:colormap/grass", origin);
4000
+ return await Caching.blockTintCache.get(key.serialize(), async () => {
4001
+ const image = await ModelTextures.get(key);
4002
+ if (!image) throw new MineRenderError(`Missing grass colormap: ${key.toNamespacedString()}`);
4003
+ if (image.width !== 256 || image.height !== 256) {
4004
+ throw new MineRenderError("Grass colormaps must be 256 \xD7 256 pixels");
4005
+ }
4006
+ const [red, green, blue] = image.data.getImageData(127, 127, 1, 1).data;
4007
+ return red << 16 | green << 8 | blue;
4008
+ });
4009
+ }
4010
+ };
4011
+
3548
4012
  // src/model/scene/ModelObject.ts
3549
- var import_three15 = require("three");
4013
+ var import_three16 = require("three");
3550
4014
 
3551
4015
  // src/three/BufferGeometryUtils.js
3552
- var import_three14 = require("three");
4016
+ var import_three15 = require("three");
3553
4017
  function computeTangents(geometry) {
3554
4018
  geometry.computeTangents();
3555
4019
  console.warn("THREE.BufferGeometryUtils: .computeTangents() has been removed. Use BufferGeometry.computeTangents() instead.");
@@ -3561,7 +4025,7 @@ function mergeBufferGeometries(geometries, useGroups = false) {
3561
4025
  const attributes = {};
3562
4026
  const morphAttributes = {};
3563
4027
  const morphTargetsRelative = geometries[0].morphTargetsRelative;
3564
- const mergedGeometry = new import_three14.BufferGeometry();
4028
+ const mergedGeometry = new import_three15.BufferGeometry();
3565
4029
  let offset = 0;
3566
4030
  for (let i = 0; i < geometries.length; ++i) {
3567
4031
  const geometry = geometries[i];
@@ -3685,7 +4149,7 @@ function mergeBufferAttributes(attributes) {
3685
4149
  array.set(attributes[i].array, offset);
3686
4150
  offset += attributes[i].array.length;
3687
4151
  }
3688
- return new import_three14.BufferAttribute(array, itemSize, normalized);
4152
+ return new import_three15.BufferAttribute(array, itemSize, normalized);
3689
4153
  }
3690
4154
  function interleaveAttributes(attributes) {
3691
4155
  let TypedArray;
@@ -3701,7 +4165,7 @@ function interleaveAttributes(attributes) {
3701
4165
  arrayLength += attribute.array.length;
3702
4166
  stride += attribute.itemSize;
3703
4167
  }
3704
- const interleavedBuffer = new import_three14.InterleavedBuffer(new TypedArray(arrayLength), stride);
4168
+ const interleavedBuffer = new import_three15.InterleavedBuffer(new TypedArray(arrayLength), stride);
3705
4169
  let offset = 0;
3706
4170
  const res = [];
3707
4171
  const getters = ["getX", "getY", "getZ", "getW"];
@@ -3710,7 +4174,7 @@ function interleaveAttributes(attributes) {
3710
4174
  const attribute = attributes[j];
3711
4175
  const itemSize = attribute.itemSize;
3712
4176
  const count = attribute.count;
3713
- const iba = new import_three14.InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, attribute.normalized);
4177
+ const iba = new import_three15.InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, attribute.normalized);
3714
4178
  res.push(iba);
3715
4179
  offset += itemSize;
3716
4180
  for (let c = 0; c < count; c++) {
@@ -3794,13 +4258,13 @@ function mergeVertices(geometry, tolerance = 1e-4) {
3794
4258
  const name = attributeNames[i];
3795
4259
  const oldAttribute = geometry.getAttribute(name);
3796
4260
  const buffer = new oldAttribute.array.constructor(attrArrays[name]);
3797
- const attribute = new import_three14.BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
4261
+ const attribute = new import_three15.BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
3798
4262
  result.setAttribute(name, attribute);
3799
4263
  if (name in morphAttrsArrays) {
3800
4264
  for (let j = 0; j < morphAttrsArrays[name].length; j++) {
3801
4265
  const oldMorphAttribute = geometry.morphAttributes[name][j];
3802
4266
  const buffer2 = new oldMorphAttribute.array.constructor(morphAttrsArrays[name][j]);
3803
- const morphAttribute = new import_three14.BufferAttribute(buffer2, oldMorphAttribute.itemSize, oldMorphAttribute.normalized);
4267
+ const morphAttribute = new import_three15.BufferAttribute(buffer2, oldMorphAttribute.itemSize, oldMorphAttribute.normalized);
3804
4268
  result.morphAttributes[name][j] = morphAttribute;
3805
4269
  }
3806
4270
  }
@@ -3809,11 +4273,11 @@ function mergeVertices(geometry, tolerance = 1e-4) {
3809
4273
  return result;
3810
4274
  }
3811
4275
  function toTrianglesDrawMode(geometry, drawMode) {
3812
- if (drawMode === import_three14.TrianglesDrawMode) {
4276
+ if (drawMode === import_three15.TrianglesDrawMode) {
3813
4277
  console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.");
3814
4278
  return geometry;
3815
4279
  }
3816
- if (drawMode === import_three14.TriangleFanDrawMode || drawMode === import_three14.TriangleStripDrawMode) {
4280
+ if (drawMode === import_three15.TriangleFanDrawMode || drawMode === import_three15.TriangleStripDrawMode) {
3817
4281
  let index = geometry.getIndex();
3818
4282
  if (index === null) {
3819
4283
  const indices = [];
@@ -3831,7 +4295,7 @@ function toTrianglesDrawMode(geometry, drawMode) {
3831
4295
  }
3832
4296
  const numberOfTriangles = index.count - 2;
3833
4297
  const newIndices = [];
3834
- if (drawMode === import_three14.TriangleFanDrawMode) {
4298
+ if (drawMode === import_three15.TriangleFanDrawMode) {
3835
4299
  for (let i = 1; i <= numberOfTriangles; i++) {
3836
4300
  newIndices.push(index.getX(0));
3837
4301
  newIndices.push(index.getX(i));
@@ -3867,15 +4331,15 @@ function computeMorphedAttributes(object) {
3867
4331
  console.error("THREE.BufferGeometryUtils: Geometry is not of type BufferGeometry.");
3868
4332
  return null;
3869
4333
  }
3870
- const _vA = new import_three14.Vector3();
3871
- const _vB = new import_three14.Vector3();
3872
- const _vC = new import_three14.Vector3();
3873
- const _tempA = new import_three14.Vector3();
3874
- const _tempB = new import_three14.Vector3();
3875
- const _tempC = new import_three14.Vector3();
3876
- const _morphA = new import_three14.Vector3();
3877
- const _morphB = new import_three14.Vector3();
3878
- const _morphC = new import_three14.Vector3();
4334
+ const _vA = new import_three15.Vector3();
4335
+ const _vB = new import_three15.Vector3();
4336
+ const _vC = new import_three15.Vector3();
4337
+ const _tempA = new import_three15.Vector3();
4338
+ const _tempB = new import_three15.Vector3();
4339
+ const _tempC = new import_three15.Vector3();
4340
+ const _morphA = new import_three15.Vector3();
4341
+ const _morphB = new import_three15.Vector3();
4342
+ const _morphC = new import_three15.Vector3();
3879
4343
  function _calculateMorphedAttributeData(object2, material2, attribute, morphAttribute, morphTargetsRelative2, a2, b2, c2, modifiedAttributeArray) {
3880
4344
  _vA.fromBufferAttribute(attribute, a2);
3881
4345
  _vB.fromBufferAttribute(attribute, b2);
@@ -4070,8 +4534,8 @@ function computeMorphedAttributes(object) {
4070
4534
  }
4071
4535
  }
4072
4536
  }
4073
- const morphedPositionAttribute = new import_three14.Float32BufferAttribute(modifiedPosition, 3);
4074
- const morphedNormalAttribute = new import_three14.Float32BufferAttribute(modifiedNormal, 3);
4537
+ const morphedPositionAttribute = new import_three15.Float32BufferAttribute(modifiedPosition, 3);
4538
+ const morphedNormalAttribute = new import_three15.Float32BufferAttribute(modifiedNormal, 3);
4075
4539
  return {
4076
4540
  positionAttribute,
4077
4541
  normalAttribute,
@@ -4081,26 +4545,29 @@ function computeMorphedAttributes(object) {
4081
4545
  }
4082
4546
 
4083
4547
  // src/model/scene/ModelObject.ts
4084
- var import_ts_deepmerge6 = __toESM(require_dist());
4085
- var p10 = prefix("ModelObject");
4086
- var _ModelObject = class _ModelObject extends SceneObject {
4548
+ var import_ts_deepmerge5 = __toESM(require_dist());
4549
+ var p9 = prefix("ModelObject");
4550
+ var ModelObject = class _ModelObject extends SceneObject {
4087
4551
  constructor(originalModel, options) {
4088
4552
  super(options);
4089
4553
  this.originalModel = originalModel;
4090
4554
  this.isModelObject = true;
4091
4555
  this.meshesCreated = false;
4092
- this.options = (0, import_ts_deepmerge6.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
4556
+ this.options = (0, import_ts_deepmerge5.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
4557
+ if (this.options.tints) this.options.tints = { ...this.options.tints };
4093
4558
  console.log("ModelObject options", this.options);
4094
4559
  }
4560
+ static {
4561
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, {});
4562
+ }
4095
4563
  async init() {
4096
4564
  await this.loadTextures();
4097
4565
  this.createMeshes();
4098
4566
  this.applyTextures();
4099
4567
  }
4100
4568
  dispose() {
4101
- var _a;
4102
4569
  super.dispose();
4103
- (_a = this.atlas) == null ? void 0 : _a.dispose();
4570
+ this.atlas?.dispose();
4104
4571
  }
4105
4572
  get textureAtlas() {
4106
4573
  return this.atlas;
@@ -4110,20 +4577,38 @@ var _ModelObject = class _ModelObject extends SceneObject {
4110
4577
  this.atlas = await UVMapper.getAtlas(this.originalModel);
4111
4578
  }
4112
4579
  createMeshes(force = false) {
4113
- var _a;
4114
4580
  if (this.meshesCreated && !force) return;
4115
4581
  const mat = Materials.MISSING_TEXTURE;
4582
+ const displayTransform = this.options.displayPosition ? DisplayTransforms.getMatrix(this.originalModel.display, this.options.displayPosition) : void 0;
4116
4583
  let allGeos = [];
4117
4584
  if (this.atlas) {
4118
4585
  if (this.atlas.model.elements) {
4119
- (_a = this.atlas.model.elements) == null ? void 0 : _a.forEach((el) => {
4586
+ this.atlas.model.elements?.forEach((el) => {
4120
4587
  const elGeo = this._getBoxGeometryFromElement(el).clone();
4121
- elGeo.applyMatrix4(new import_three15.Matrix4().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4122
- elGeo.applyMatrix4(new import_three15.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
4588
+ if (this.options.uvLockRotation) {
4589
+ UVMapper.lockUvs(elGeo, el.faces, this.atlas, new import_three16.Euler(...this.options.uvLockRotation));
4590
+ }
4591
+ if (this.options.tints) {
4592
+ const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
4593
+ for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
4594
+ const tintIndex = el.faces[faceName]?.tintindex;
4595
+ if (tintIndex === void 0 || tintIndex < 0) continue;
4596
+ const tint = this.options.tints[tintIndex];
4597
+ if (tint === void 0) continue;
4598
+ const color = new import_three16.Color(tint);
4599
+ for (let vertex = 0; vertex < 4; vertex++) {
4600
+ color.toArray(colors, (faceIndex * 4 + vertex) * 3);
4601
+ }
4602
+ }
4603
+ elGeo.setAttribute("color", new import_three16.BufferAttribute(colors, 3));
4604
+ }
4605
+ elGeo.applyMatrix4(new import_three16.Matrix4().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4606
+ elGeo.applyMatrix4(new import_three16.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
4123
4607
  if (el.rotation) {
4124
4608
  applyElementRotation(el.rotation, elGeo);
4125
4609
  }
4126
- elGeo.applyMatrix4(new import_three15.Matrix4().makeTranslation(-8, -8, -8));
4610
+ elGeo.applyMatrix4(new import_three16.Matrix4().makeTranslation(-8, -8, -8));
4611
+ if (displayTransform) DisplayTransforms.apply(elGeo, displayTransform);
4127
4612
  if (this.options.mergeMeshes) {
4128
4613
  allGeos.push(elGeo);
4129
4614
  } else {
@@ -4134,17 +4619,18 @@ var _ModelObject = class _ModelObject extends SceneObject {
4134
4619
  }
4135
4620
  });
4136
4621
  } else {
4137
- console.debug(p10, this.atlas.model, "has no elements");
4622
+ console.debug(p9, this.atlas.model, "has no elements");
4138
4623
  }
4139
4624
  } else {
4140
- console.debug(p10, "Missing atlas for", this);
4625
+ console.debug(p9, "Missing atlas for", this);
4141
4626
  }
4142
4627
  if (this.options.mergeMeshes) {
4143
4628
  let combinedGeo;
4144
4629
  if (allGeos.length > 0) {
4145
4630
  combinedGeo = mergeBufferGeometries(allGeos);
4146
4631
  } else {
4147
- combinedGeo = new import_three15.BoxGeometry(16, 16, 16);
4632
+ combinedGeo = new import_three16.BoxGeometry(16, 16, 16);
4633
+ if (displayTransform) DisplayTransforms.apply(combinedGeo, displayTransform);
4148
4634
  }
4149
4635
  combinedGeo.computeBoundingBox();
4150
4636
  let mesh;
@@ -4174,6 +4660,7 @@ var _ModelObject = class _ModelObject extends SceneObject {
4174
4660
  /*TODO: get this from render options*/
4175
4661
  );
4176
4662
  this.iterateAllMeshes((mesh) => {
4663
+ if (mesh.geometry.hasAttribute("color")) mat.vertexColors = true;
4177
4664
  mesh.material = mat;
4178
4665
  });
4179
4666
  if (this.atlas.hasAnimation) {
@@ -4189,17 +4676,25 @@ var _ModelObject = class _ModelObject extends SceneObject {
4189
4676
  }
4190
4677
  }
4191
4678
  };
4192
- _ModelObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge6.default)({}, SceneObject.DEFAULT_OPTIONS, {});
4193
- var ModelObject = _ModelObject;
4194
4679
  function isModelObject(obj) {
4195
4680
  return obj.isModelObject;
4196
4681
  }
4197
4682
 
4198
4683
  // src/model/block/scene/BlockObject.ts
4199
- var import_ts_deepmerge7 = __toESM(require_dist());
4200
- var import_three16 = require("three");
4201
- var p11 = prefix("BlockObject");
4202
- var _BlockObject = class _BlockObject extends SceneObject {
4684
+ var import_ts_deepmerge6 = __toESM(require_dist());
4685
+ var import_three17 = require("three");
4686
+ var p10 = prefix("BlockObject");
4687
+ function matchesCondition(condition, state) {
4688
+ return Object.entries(condition).every(([key, value]) => {
4689
+ if (Array.isArray(value)) {
4690
+ if (key === "OR") return value.some((child) => matchesCondition(child, state));
4691
+ if (key === "AND") return value.every((child) => matchesCondition(child, state));
4692
+ return false;
4693
+ }
4694
+ return typeof value === "string" && state[key] !== void 0 && value.split("|").includes(`${state[key]}`);
4695
+ });
4696
+ }
4697
+ var BlockObject = class _BlockObject extends SceneObject {
4203
4698
  constructor(blockState, options) {
4204
4699
  super(options);
4205
4700
  this.blockState = blockState;
@@ -4212,11 +4707,16 @@ var _BlockObject = class _BlockObject extends SceneObject {
4212
4707
  this._instanceModel = [];
4213
4708
  this._variants = [];
4214
4709
  this._models = [];
4215
- this.options = (0, import_ts_deepmerge7.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
4710
+ this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
4711
+ }
4712
+ static {
4713
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge6.default)({}, ModelObject.DEFAULT_OPTIONS, {
4714
+ applyDefaultState: true
4715
+ });
4216
4716
  }
4217
4717
  async init() {
4218
4718
  if (this.options.applyDefaultState) {
4219
- const defaultState = this.blockState.key ? BlockStates.getDefaultState(this.blockState.key) : void 0;
4719
+ const defaultState = this.blockState.key ? await BlockStates.getDefaultState(this.blockState.key) : void 0;
4220
4720
  if (defaultState && Object.keys(defaultState).length > 0) {
4221
4721
  const state = {};
4222
4722
  for (let k in defaultState) {
@@ -4227,15 +4727,9 @@ var _BlockObject = class _BlockObject extends SceneObject {
4227
4727
  if (this.blockState.variants) {
4228
4728
  await this.setState(Object.keys(this.blockState.variants)[0]);
4229
4729
  } else if (this.blockState.multipart) {
4230
- for (let part of this.blockState.multipart) {
4231
- if (part.when && !("OR" in part.when)) {
4232
- const k = Object.keys(part.when)[0];
4233
- if (k) {
4234
- await this.setState(k, part.when[k].split("|")[0]);
4235
- break;
4236
- }
4237
- }
4238
- }
4730
+ const condition = this.blockState.multipart.map((part) => part.when).find((when) => when !== void 0 && Object.values(when).every((value) => typeof value === "string"));
4731
+ const state = Object.fromEntries(Object.entries(condition ?? {}).map(([key, value]) => [key, value.split("|")[0]]));
4732
+ await this.setState(state);
4239
4733
  }
4240
4734
  }
4241
4735
  } else {
@@ -4250,7 +4744,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
4250
4744
  if (isModelObject(model)) {
4251
4745
  model.removeFromScene();
4252
4746
  } else if (isInstanceReference(model)) {
4253
- model.setScale(new import_three16.Vector3(0, 0, 0));
4747
+ model.setScale(new import_three17.Vector3(0, 0, 0));
4254
4748
  }
4255
4749
  }
4256
4750
  super.removeFromScene();
@@ -4292,55 +4786,11 @@ var _BlockObject = class _BlockObject extends SceneObject {
4292
4786
  } else if (this.blockState.multipart) {
4293
4787
  for (let part of this.blockState.multipart) {
4294
4788
  if (!part.apply) {
4295
- console.debug(p11, "Missing apply for blockState part", part);
4789
+ console.debug(p10, "Missing apply for blockState part", part);
4296
4790
  continue;
4297
4791
  }
4298
- if (!part.when) {
4792
+ if (!part.when || matchesCondition(part.when, state)) {
4299
4793
  out.push(this.getSingleVariant(part.apply));
4300
- } else {
4301
- let matches = true;
4302
- if ("OR" in part.when) {
4303
- const or = part.when.OR;
4304
- let anyMatch = false;
4305
- for (let o of or) {
4306
- for (let k in o) {
4307
- const split = o[k].split("|");
4308
- let m = false;
4309
- for (let s of split) {
4310
- if (`${state[k]}` === `${s}`) {
4311
- m = true;
4312
- break;
4313
- }
4314
- }
4315
- if (m) {
4316
- anyMatch = true;
4317
- break;
4318
- }
4319
- }
4320
- }
4321
- if (!anyMatch) {
4322
- matches = false;
4323
- }
4324
- } else {
4325
- for (let k in part.when) {
4326
- const split = part.when[k].split("|");
4327
- let m = false;
4328
- for (let s of split) {
4329
- if (`${state[k]}` === `${s}`) {
4330
- m = true;
4331
- break;
4332
- }
4333
- }
4334
- if (!m) {
4335
- matches = false;
4336
- break;
4337
- }
4338
- }
4339
- }
4340
- if (matches) {
4341
- const variants = part.apply;
4342
- out.push(this.getSingleVariant(variants));
4343
- }
4344
4794
  }
4345
4795
  }
4346
4796
  }
@@ -4355,7 +4805,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
4355
4805
  }
4356
4806
  for (let model of this._models) {
4357
4807
  if (isInstanceReference(model)) {
4358
- model.setScale(new import_three16.Vector3(0, 0, 0));
4808
+ model.setScale(new import_three17.Vector3(0, 0, 0));
4359
4809
  } else {
4360
4810
  model.dispose();
4361
4811
  }
@@ -4370,11 +4820,21 @@ var _BlockObject = class _BlockObject extends SceneObject {
4370
4820
  }
4371
4821
  }
4372
4822
  getSingleVariant(variants) {
4373
- if (Array.isArray(variants)) {
4374
- return variants[0];
4375
- } else {
4376
- return variants;
4377
- }
4823
+ if (!Array.isArray(variants)) return variants;
4824
+ if (!variants.length) throw new MineRenderError("Blockstate variant arrays must not be empty");
4825
+ const total = variants.reduce((sum, variant) => {
4826
+ const weight = variant.weight ?? 1;
4827
+ if (!Number.isInteger(weight) || weight < 1) {
4828
+ throw new MineRenderError(`Invalid blockstate variant weight: ${weight}`);
4829
+ }
4830
+ return sum + weight;
4831
+ }, 0);
4832
+ let choice = Math.random() * total;
4833
+ for (const variant of variants) {
4834
+ choice -= variant.weight ?? 1;
4835
+ if (choice < 0) return variant;
4836
+ }
4837
+ return variants[variants.length - 1];
4378
4838
  }
4379
4839
  // @deprecated
4380
4840
  async createAVariant(variants, instanceInfo) {
@@ -4382,28 +4842,27 @@ var _BlockObject = class _BlockObject extends SceneObject {
4382
4842
  await this.createVariant(variant);
4383
4843
  }
4384
4844
  async createVariant(variant) {
4385
- const model = await Models.getMerged(AssetKey.parse("models", variant.model));
4386
- const obj = await this.scene.addModel(model, this.options);
4387
- if (isInstanceReference(obj) || obj.isInstanced) {
4388
- this._isInstanced = true;
4389
- this._instanceCounter = 1;
4390
- }
4391
- let rotation = new import_three16.Euler(0, 0, 0);
4845
+ const rotation = new import_three17.Euler();
4392
4846
  if (typeof variant.x !== "undefined") {
4393
4847
  rotation.x = toRadians(clampRotationDegrees(variant.x));
4394
4848
  }
4395
4849
  if (typeof variant.y !== "undefined") {
4396
- if (typeof variant.x !== "undefined") {
4397
- rotation.y = toRadians(clampRotationDegrees(variant.y));
4398
- } else {
4399
- rotation.y = toRadians(clampRotationDegrees(360 - variant.y));
4400
- }
4850
+ rotation.y = toRadians(clampRotationDegrees(typeof variant.x !== "undefined" ? variant.y : 360 - variant.y));
4851
+ }
4852
+ const modelKey = AssetKey.parse("models", variant.model);
4853
+ modelKey.root = this.blockState.key?.root;
4854
+ const model = await Models.getMerged(modelKey);
4855
+ const options = {
4856
+ ...this.options,
4857
+ tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints) : this.options.tints,
4858
+ uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0) ? [rotation.x, rotation.y, rotation.z] : void 0
4859
+ };
4860
+ const obj = await this.scene.addModel(model, options);
4861
+ if (isInstanceReference(obj) || obj.isInstanced) {
4862
+ this._isInstanced = true;
4863
+ this._instanceCounter = 1;
4401
4864
  }
4402
4865
  obj.setRotation(rotation);
4403
- setTimeout(() => {
4404
- obj.setRotation(rotation);
4405
- }, 150);
4406
- console.log(obj);
4407
4866
  return obj;
4408
4867
  }
4409
4868
  async resetState() {
@@ -4472,7 +4931,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
4472
4931
  setPositionRotationScaleAt(index, position, rotation, scale) {
4473
4932
  super.setPositionRotationScaleAt(index, position, rotation, scale);
4474
4933
  }
4475
- getMatrixAt(index, matrix = new import_three16.Matrix4()) {
4934
+ getMatrixAt(index, matrix = new import_three17.Matrix4()) {
4476
4935
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
4477
4936
  const child = this._models[0];
4478
4937
  if (child && isModelObject(child)) {
@@ -4493,18 +4952,15 @@ var _BlockObject = class _BlockObject extends SceneObject {
4493
4952
  }
4494
4953
  }
4495
4954
  setPosition(position) {
4496
- super.setPosition(position);
4955
+ this.position.copy(position);
4497
4956
  for (let model of this._models) {
4498
4957
  model.setPosition(position);
4499
4958
  }
4959
+ this.notifyDirty();
4500
4960
  }
4501
4961
  //TODO: should override rotation + scale methods
4502
4962
  //TODO
4503
4963
  };
4504
- _BlockObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge7.default)({}, ModelObject.DEFAULT_OPTIONS, {
4505
- applyDefaultState: true
4506
- });
4507
- var BlockObject = _BlockObject;
4508
4964
  function isBlockObject(obj) {
4509
4965
  return obj.isBlockObject;
4510
4966
  }
@@ -4529,11 +4985,10 @@ var StructureParser = class {
4529
4985
  throw new MineRenderError("Structure does not have palette(s)");
4530
4986
  }
4531
4987
  const blocks = nbt.blocks.value.value.map((block) => {
4532
- var _a;
4533
4988
  const state = palette.value.value[block.state.value];
4534
4989
  if (state.Name.value === "minecraft:air") return void 0;
4535
4990
  const props = {};
4536
- for (let k in (_a = state.Properties) == null ? void 0 : _a.value) {
4991
+ for (let k in state.Properties?.value) {
4537
4992
  props[k] = state.Properties.value[k].value;
4538
4993
  }
4539
4994
  return {
@@ -4551,8 +5006,8 @@ var StructureParser = class {
4551
5006
  };
4552
5007
 
4553
5008
  // src/renderer/MineRenderScene.ts
4554
- var import_three17 = require("three");
4555
- var import_ts_deepmerge9 = __toESM(require_dist());
5009
+ var import_three19 = require("three");
5010
+ var import_ts_deepmerge8 = __toESM(require_dist());
4556
5011
 
4557
5012
  // src/skin/SkinPart.ts
4558
5013
  var SkinPart = /* @__PURE__ */ ((SkinPart2) => {
@@ -5170,90 +5625,80 @@ var baseSkinCoordinates = {
5170
5625
  ]
5171
5626
  },
5172
5627
  up: {
5173
- uv: [
5174
- 4,
5175
- 36,
5176
- 8,
5177
- 32
5178
- ]
5179
- },
5180
- down: {
5181
- uv: [
5182
- 8,
5183
- 32,
5184
- 12,
5185
- 36
5186
- ],
5187
- rotation: 180
5188
- }
5189
- },
5190
- cape: {
5191
- //TODO
5192
- east: {
5193
- uv: [
5194
- 0,
5195
- 36,
5196
- 4,
5197
- 48
5198
- ]
5199
- },
5200
- west: {
5201
5628
  uv: [
5202
5629
  8,
5203
5630
  36,
5204
- 12,
5205
- 48
5206
- ]
5207
- },
5208
- north: {
5209
- uv: [
5210
5631
  4,
5211
- 36,
5212
- 8,
5213
- 48
5632
+ 32
5214
5633
  ]
5215
5634
  },
5216
- south: {
5635
+ down: {
5217
5636
  uv: [
5218
5637
  12,
5219
- 36,
5220
- 16,
5221
- 48
5222
- ]
5223
- },
5224
- up: {
5225
- uv: [
5226
- 4,
5227
5638
  32,
5228
5639
  8,
5229
5640
  36
5230
- ]
5231
- },
5232
- down: {
5233
- uv: [
5234
- 8,
5235
- 32,
5236
- 12,
5237
- 36
5238
5641
  ],
5239
5642
  rotation: 180
5240
5643
  }
5644
+ },
5645
+ cape: {
5646
+ east: { uv: [0, 1, 1, 17] },
5647
+ west: { uv: [11, 1, 12, 17] },
5648
+ north: { uv: [1, 1, 11, 17] },
5649
+ south: { uv: [12, 1, 22, 17] },
5650
+ up: { uv: [11, 1, 1, 0] },
5651
+ down: { uv: [21, 0, 11, 1] }
5241
5652
  }
5242
5653
  };
5243
5654
  var classicSkinTextureCoordinates = {
5244
5655
  ...baseSkinCoordinates
5245
5656
  };
5246
- var slimSkinTextureCoordinates = { ...baseSkinCoordinates };
5657
+ var slimSkinTextureCoordinates = {
5658
+ ...baseSkinCoordinates,
5659
+ leftArm: {
5660
+ ...baseSkinCoordinates.leftArm,
5661
+ west: { uv: [39, 52, 43, 64] },
5662
+ north: { uv: [36, 52, 39, 64] },
5663
+ south: { uv: [43, 52, 46, 64] },
5664
+ up: { uv: [39, 52, 36, 48] },
5665
+ down: { uv: [42, 48, 39, 52] }
5666
+ },
5667
+ rightArm: {
5668
+ ...baseSkinCoordinates.rightArm,
5669
+ west: { uv: [47, 20, 51, 32] },
5670
+ north: { uv: [44, 20, 47, 32] },
5671
+ south: { uv: [51, 20, 54, 32] },
5672
+ up: { uv: [47, 20, 44, 16] },
5673
+ down: { uv: [50, 16, 47, 20] }
5674
+ },
5675
+ leftSleeve: {
5676
+ ...baseSkinCoordinates.leftSleeve,
5677
+ west: { uv: [55, 52, 59, 64] },
5678
+ north: { uv: [52, 52, 55, 64] },
5679
+ south: { uv: [59, 52, 62, 64] },
5680
+ up: { uv: [55, 52, 52, 48] },
5681
+ down: { uv: [58, 48, 55, 52], rotation: 180 }
5682
+ },
5683
+ rightSleeve: {
5684
+ ...baseSkinCoordinates.rightSleeve,
5685
+ west: { uv: [47, 36, 51, 48] },
5686
+ north: { uv: [44, 36, 47, 48] },
5687
+ south: { uv: [51, 36, 54, 48] },
5688
+ up: { uv: [47, 36, 44, 32] },
5689
+ down: { uv: [50, 32, 47, 36], rotation: 180 }
5690
+ }
5691
+ };
5247
5692
 
5248
5693
  // src/skin/SkinGeometries.ts
5249
5694
  var box8inner = [8, 8, 8];
5250
- var box8outer = [8.504, 8.504, 8.504];
5695
+ var box8outer = [9, 9, 9];
5251
5696
  var box8_12_4inner = [8, 12, 4];
5252
- var box8_12_4outer = [8.504, 12.504, 4.504];
5697
+ var box8_12_4outer = [8.5, 12.5, 4.5];
5253
5698
  var box4_12_4inner = [4, 12, 4];
5254
- var box4_12_4outer = [4.504, 12.504, 4.504];
5699
+ var box4_12_4outer = [4.5, 12.5, 4.5];
5255
5700
  var box3_12_4inner = [3, 12, 4];
5256
- var box3_12_4outer = [3.504, 12.504, 4.504];
5701
+ var box3_12_4outer = [3.5, 12.5, 4.5];
5257
5702
  var box10_16_1 = [10, 16, 1];
5258
5703
  var baseSkinGeometries = {
5259
5704
  head: box8inner,
@@ -5283,119 +5728,318 @@ var slimSkinGeometries = {
5283
5728
  };
5284
5729
 
5285
5730
  // src/skin/scene/SkinObject.ts
5286
- var import_ts_deepmerge8 = __toESM(require_dist());
5731
+ var import_ts_deepmerge7 = __toESM(require_dist());
5732
+
5733
+ // src/skin/SkinTextures.ts
5734
+ var import_three18 = require("three");
5735
+
5736
+ // src/skin/SkinImage.ts
5737
+ var SkinImage = class {
5738
+ static async getData(src) {
5739
+ const key = serializeImageKey({ src });
5740
+ return await Caching.imageDataCache.get(`skin:${key}`, async () => {
5741
+ const info = await ImageLoader.getInfo(src);
5742
+ if (info.type !== "png") return ImageLoader.getData(src);
5743
+ try {
5744
+ return await this.decodePng(info.data);
5745
+ } catch (error) {
5746
+ Caching.rawImageCache.invalidate(key);
5747
+ throw error;
5748
+ }
5749
+ });
5750
+ }
5751
+ static async decodePng(bytes) {
5752
+ const { decode, convertIndexedToRgb } = await import("fast-png");
5753
+ const png = decode(bytes);
5754
+ let { data, channels, depth } = png;
5755
+ if (channels === 1 && (png.palette || depth < 8)) {
5756
+ const max = (1 << depth) - 1;
5757
+ const palette = png.palette ?? Array.from({ length: max + 1 }, (_, value) => {
5758
+ const gray = value * 255 / max;
5759
+ return [gray, gray, gray, png.transparency?.[0] === value ? 0 : 255];
5760
+ });
5761
+ data = convertIndexedToRgb({ ...png, palette });
5762
+ channels = palette[0].length;
5763
+ depth = 8;
5764
+ }
5765
+ const pixels = new Uint8ClampedArray(png.width * png.height * 4);
5766
+ for (let pixel = 0; pixel < png.width * png.height; pixel++) {
5767
+ const source = pixel * channels;
5768
+ const target = pixel * 4;
5769
+ const sample = (channel) => depth === 16 ? data[source + channel] >>> 8 : data[source + channel];
5770
+ pixels[target] = sample(0);
5771
+ pixels[target + 1] = sample(channels < 3 ? 0 : 1);
5772
+ pixels[target + 2] = sample(channels < 3 ? 0 : 2);
5773
+ pixels[target + 3] = channels % 2 === 0 ? sample(channels - 1) : png.transparency?.every((value, channel) => data[source + channel] === value) ? 0 : 255;
5774
+ }
5775
+ return { width: png.width, height: png.height, data: pixels, colorSpace: "srgb" };
5776
+ }
5777
+ };
5778
+
5779
+ // src/skin/SkinTextures.ts
5780
+ var SkinTextures = class {
5781
+ static async get(src, legacy) {
5782
+ const image = await SkinImage.getData(src);
5783
+ const scale = image.width / 64;
5784
+ if (!Number.isInteger(scale) || scale < 1 || image.height !== image.width && image.height !== image.width / 2) {
5785
+ throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; expected 64x64 or 64x32, or an integer-scaled equivalent`);
5786
+ }
5787
+ const isLegacy = legacy ?? image.height === image.width / 2;
5788
+ if (!isLegacy && image.height !== image.width) {
5789
+ throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; non-legacy skins must be square`);
5790
+ }
5791
+ const slim = !isLegacy && this.isSlim(image, scale);
5792
+ const key = `skin:${serializeImageKey({ src })}:${isLegacy}`;
5793
+ const material = Caching.materialCache.get(key, () => {
5794
+ const pixels = isLegacy ? this.normalizeLegacy(image, scale) : new Uint8Array(image.data);
5795
+ this.makeBaseOpaque(pixels, image.width, scale);
5796
+ return this.createMaterial(pixels, image.width, image.width);
5797
+ });
5798
+ return { material, slim, legacy: isLegacy };
5799
+ }
5800
+ static async getCape(src, layout = "minecraft") {
5801
+ const image = await SkinImage.getData(src);
5802
+ const scale = image.width / 64;
5803
+ if (layout === "minecraft" && (!Number.isInteger(scale) || scale < 1 || image.height !== image.width / 2)) {
5804
+ throw new MineRenderError(`Invalid cape dimensions ${image.width}x${image.height}; expected 64x32 or an integer-scaled equivalent`);
5805
+ }
5806
+ return Caching.materialCache.get(`cape:${serializeImageKey({ src })}`, () => {
5807
+ return this.createMaterial(new Uint8Array(image.data), image.width, image.height, false);
5808
+ });
5809
+ }
5810
+ static createMaterial(pixels, width, height, transparent = true) {
5811
+ const texture = Textures.initTextureProps(new import_three18.DataTexture(pixels, width, height));
5812
+ texture.colorSpace = import_three18.SRGBColorSpace;
5813
+ texture.flipY = true;
5814
+ texture.needsUpdate = true;
5815
+ return new import_three18.MeshBasicMaterial({ map: texture, transparent, side: transparent ? import_three18.DoubleSide : import_three18.FrontSide, alphaTest: transparent ? 0.1 : 0 });
5816
+ }
5817
+ static isSlim(image, scale) {
5818
+ for (const [x, y] of [[46, 52], [54, 20]]) {
5819
+ for (let row = y * scale; row < (y + 12) * scale; row++) {
5820
+ for (let column = x * scale; column < (x + 1) * scale; column++) {
5821
+ if (image.data[(row * image.width + column) * 4 + 3] !== 0) return false;
5822
+ }
5823
+ }
5824
+ }
5825
+ return true;
5826
+ }
5827
+ static normalizeLegacy(image, scale) {
5828
+ const pixels = new Uint8Array(image.width * image.width * 4);
5829
+ pixels.set(image.data.subarray(0, image.width * image.width / 2 * 4));
5830
+ for (const [sx, sy, dx, dy, width, height] of [
5831
+ [4, 16, 20, 48, 4, 4],
5832
+ [8, 16, 24, 48, 4, 4],
5833
+ [0, 20, 24, 52, 4, 12],
5834
+ [4, 20, 20, 52, 4, 12],
5835
+ [8, 20, 16, 52, 4, 12],
5836
+ [12, 20, 28, 52, 4, 12],
5837
+ [44, 16, 36, 48, 4, 4],
5838
+ [48, 16, 40, 48, 4, 4],
5839
+ [40, 20, 40, 52, 4, 12],
5840
+ [44, 20, 36, 52, 4, 12],
5841
+ [48, 20, 32, 52, 4, 12],
5842
+ [52, 20, 44, 52, 4, 12]
5843
+ ]) {
5844
+ for (let y = 0; y < height * scale; y++) {
5845
+ for (let x = 0; x < width * scale; x++) {
5846
+ const source = ((sy * scale + y) * image.width + sx * scale + x) * 4;
5847
+ const target = ((dy * scale + y) * image.width + (dx + width) * scale - 1 - x) * 4;
5848
+ pixels.set(image.data.subarray(source, source + 4), target);
5849
+ }
5850
+ }
5851
+ }
5852
+ let clearHat = true;
5853
+ for (let y = 0; y < 32 * scale; y++) {
5854
+ for (let x = 32 * scale; x < image.width; x++) {
5855
+ if (pixels[(y * image.width + x) * 4 + 3] < 128) clearHat = false;
5856
+ }
5857
+ }
5858
+ if (clearHat) {
5859
+ for (let y = 0; y < 32 * scale; y++) {
5860
+ for (let x = 32 * scale; x < image.width; x++) {
5861
+ pixels[(y * image.width + x) * 4 + 3] = 0;
5862
+ }
5863
+ }
5864
+ }
5865
+ return pixels;
5866
+ }
5867
+ static makeBaseOpaque(pixels, width, scale) {
5868
+ for (const [x0, y0, x1, y1] of [[0, 0, 32, 16], [0, 16, 64, 32], [16, 48, 48, 64]]) {
5869
+ for (let y = y0 * scale; y < y1 * scale; y++) {
5870
+ for (let x = x0 * scale; x < x1 * scale; x++) pixels[(y * width + x) * 4 + 3] = 255;
5871
+ }
5872
+ }
5873
+ }
5874
+ };
5875
+
5876
+ // src/skin/CapeLayout.ts
5877
+ var capeTextureSizes = {
5878
+ minecraft: [64, 32],
5879
+ optifine: [46, 22],
5880
+ labymod: [22, 17]
5881
+ };
5882
+
5883
+ // src/skin/scene/SkinObject.ts
5287
5884
  var SkinObject = class extends SceneObject {
5288
5885
  constructor(options) {
5289
5886
  super();
5290
5887
  this.slim = false;
5291
- this.legacy = false;
5292
- this.skinTextureWidth = 64;
5293
- this.skinTextureHeight = 64;
5294
- this.options = (0, import_ts_deepmerge8.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
5888
+ this.detectedSlim = false;
5889
+ this.skinLoad = 0;
5890
+ this.capeLoad = 0;
5891
+ this.options = (0, import_ts_deepmerge7.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
5892
+ this.slim = this.options.slim ?? false;
5295
5893
  }
5296
5894
  async init() {
5895
+ const cape = this.getGroupByName("cape" /* CAPE */);
5297
5896
  this.createMeshes();
5897
+ if (cape) this.getGroupByName("body" /* BODY */).attach(cape);
5298
5898
  }
5299
5899
  removeMeshes() {
5300
5900
  }
5301
5901
  createMeshes() {
5302
- console.log("#createMeshes");
5303
- const mat = Materials.MISSING_TEXTURE;
5902
+ const mat = this.skinMaterial ?? Materials.MISSING_TEXTURE;
5304
5903
  {
5305
5904
  const headGroup = this.createAndAddGroup("head", 0, 28, 0, "y" /* Y */, -4);
5306
5905
  const headGeo = this.getBoxGeometry("head" /* HEAD */);
5307
5906
  const head = this.createAndAddMesh("head", headGroup, headGeo, mat, "y" /* Y */, 4);
5308
- if (!this.legacy) {
5309
- const hatGeo = this.getBoxGeometry("hat" /* HAT */);
5310
- const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, "y" /* Y */, 4);
5311
- }
5907
+ const hatGeo = this.getBoxGeometry("hat" /* HAT */);
5908
+ const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, "y" /* Y */, 4);
5312
5909
  }
5313
5910
  {
5314
- const bodyGroup = this.createAndAddGroup("body", 0, 18, 0);
5911
+ const bodyGroup = this.createAndAddGroup("body", 0, 24, 0);
5315
5912
  const bodyGeo = this.getBoxGeometry("body" /* BODY */);
5316
- const body = this.createAndAddMesh("body", bodyGroup, bodyGeo, mat);
5913
+ const body = this.createAndAddMesh("body", bodyGroup, bodyGeo, mat, "y" /* Y */, -6);
5317
5914
  const jacketGeo = this.getBoxGeometry("jacket" /* JACKET */);
5318
- const jacket = this.createAndAddMesh("jacket", bodyGroup, jacketGeo, mat);
5915
+ const jacket = this.createAndAddMesh("jacket", bodyGroup, jacketGeo, mat, "y" /* Y */, -6);
5319
5916
  }
5320
5917
  {
5321
5918
  {
5322
- const leftArmGroup = this.createAndAddGroup("leftArm", this.slim ? -5.5 : -6, 18, 0, "y" /* Y */, 4);
5919
+ const leftArmGroup = this.createAndAddGroup("leftArm", -5, 22, 0);
5323
5920
  const leftArmGeo = this.getBoxGeometry("leftArm" /* LEFT_ARM */);
5324
5921
  const leftArm = this.createAndAddMesh("leftArm", leftArmGroup, leftArmGeo, mat, "y" /* Y */, -4);
5922
+ leftArm.position.x = this.slim ? -0.5 : -1;
5325
5923
  const leftSleeveGeo = this.getBoxGeometry("leftSleeve" /* LEFT_SLEEVE */);
5326
5924
  const leftSleeve = this.createAndAddMesh("leftSleeve", leftArmGroup, leftSleeveGeo, mat, "y" /* Y */, -4);
5925
+ leftSleeve.position.x = this.slim ? -0.5 : -1;
5327
5926
  }
5328
5927
  {
5329
- const rightArmGroup = this.createAndAddGroup("rightArm", this.slim ? 5.5 : 6, 18, 0, "y" /* Y */, 4);
5928
+ const rightArmGroup = this.createAndAddGroup("rightArm", 5, 22, 0);
5330
5929
  const rightArmGeo = this.getBoxGeometry("rightArm" /* RIGHT_ARM */);
5331
5930
  const rightArm = this.createAndAddMesh("rightArm", rightArmGroup, rightArmGeo, mat, "y" /* Y */, -4);
5931
+ rightArm.position.x = this.slim ? 0.5 : 1;
5332
5932
  const rightSleeveGeo = this.getBoxGeometry("rightSleeve" /* RIGHT_SLEEVE */);
5333
5933
  const rightSleeve = this.createAndAddMesh("rightSleeve", rightArmGroup, rightSleeveGeo, mat, "y" /* Y */, -4);
5934
+ rightSleeve.position.x = this.slim ? 0.5 : 1;
5334
5935
  }
5335
5936
  }
5336
5937
  {
5337
5938
  {
5338
- const leftLegGroup = this.createAndAddGroup("leftLeg", -2, 6, 0, "y" /* Y */, 4);
5939
+ const leftLegGroup = this.createAndAddGroup("leftLeg", -1.9, 12, 0);
5339
5940
  const leftLegGeo = this.getBoxGeometry("leftLeg" /* LEFT_LEG */);
5340
- const leftLeg = this.createAndAddMesh("leftLeg", leftLegGroup, leftLegGeo, mat, "y" /* Y */, -4);
5941
+ const leftLeg = this.createAndAddMesh("leftLeg", leftLegGroup, leftLegGeo, mat, "y" /* Y */, -6);
5341
5942
  const leftTrousersGeo = this.getBoxGeometry("leftTrousers" /* LEFT_TROUSERS */);
5342
- const leftTrousers = this.createAndAddMesh("leftTrousers", leftLegGroup, leftTrousersGeo, mat, "y" /* Y */, -4);
5943
+ const leftTrousers = this.createAndAddMesh("leftTrousers", leftLegGroup, leftTrousersGeo, mat, "y" /* Y */, -6);
5343
5944
  }
5344
5945
  {
5345
- const rightLegGroup = this.createAndAddGroup("rightLeg", 2, 6, 0, "y" /* Y */, 4);
5946
+ const rightLegGroup = this.createAndAddGroup("rightLeg", 1.9, 12, 0);
5346
5947
  const rightLegGeo = this.getBoxGeometry("rightLeg" /* RIGHT_LEG */);
5347
- const rightLeg = this.createAndAddMesh("rightLeg", rightLegGroup, rightLegGeo, mat, "y" /* Y */, -4);
5948
+ const rightLeg = this.createAndAddMesh("rightLeg", rightLegGroup, rightLegGeo, mat, "y" /* Y */, -6);
5348
5949
  const rightTrousersGeo = this.getBoxGeometry("rightTrousers" /* RIGHT_TROUSERS */);
5349
- const rightTrousers = this.createAndAddMesh("rightTrousers", rightLegGroup, rightTrousersGeo, mat, "y" /* Y */, -4);
5950
+ const rightTrousers = this.createAndAddMesh("rightTrousers", rightLegGroup, rightTrousersGeo, mat, "y" /* Y */, -6);
5350
5951
  }
5351
5952
  }
5352
- console.log("#createMeshes done");
5353
5953
  }
5354
- setSkinTexture(src) {
5954
+ async setSkinTexture(src) {
5355
5955
  if (typeof src === "undefined") return;
5356
5956
  this.skinTextureSrc = src;
5357
- const mat = Materials.getImage({
5358
- texture: { src },
5359
- transparent: true
5360
- });
5361
- for (let part of SKIN_PARTS) {
5362
- let mesh = this.getMeshByName(part);
5957
+ const load = ++this.skinLoad;
5958
+ const texture = await SkinTextures.get(src, this.options.legacy);
5959
+ if (load !== this.skinLoad) return;
5960
+ this.skinMaterial = texture.material;
5961
+ this.detectedSlim = texture.slim;
5962
+ this.updateSlim(this.options.slim ?? this.detectedSlim);
5963
+ for (const part of SKIN_PARTS) {
5964
+ if (part === "cape" /* CAPE */) continue;
5965
+ const mesh = this.getMeshByName(part);
5363
5966
  if (mesh) {
5364
- mesh.material = mat;
5967
+ mesh.material = texture.material;
5365
5968
  }
5366
5969
  }
5970
+ this.notifyDirty();
5971
+ }
5972
+ /** Load a cape texture in the selected layout, or pass undefined to remove the cape. */
5973
+ async setCapeTexture(src, layout = "minecraft") {
5974
+ const load = ++this.capeLoad;
5975
+ if (src === void 0) {
5976
+ const group = this.getGroupByName("cape" /* CAPE */);
5977
+ group?.removeFromParent();
5978
+ this.notifyDirty();
5979
+ return;
5980
+ }
5981
+ const material = await SkinTextures.getCape(src, layout);
5982
+ if (load !== this.capeLoad) return;
5983
+ const size = capeTextureSizes[layout];
5984
+ const geometry = this._getBoxGeometryFromDimensions(
5985
+ classicSkinGeometries.cape,
5986
+ classicSkinTextureCoordinates.cape,
5987
+ size,
5988
+ size
5989
+ );
5990
+ const mesh = this.getMeshByName("cape" /* CAPE */);
5991
+ if (mesh) {
5992
+ mesh.material = material;
5993
+ mesh.geometry = geometry;
5994
+ } else {
5995
+ const body = this.getGroupByName("body" /* BODY */);
5996
+ const group = this.createGroup("cape" /* CAPE */, 0, body ? 0 : 24, 2);
5997
+ (body ?? this).add(group);
5998
+ group.rotation.set(toRadians(-6), Math.PI, 0);
5999
+ const cape = this.createAndAddMesh("cape" /* CAPE */, group, geometry, material);
6000
+ cape.position.set(0, -8, -0.5);
6001
+ }
6002
+ this.notifyDirty();
5367
6003
  }
5368
- //TODO: cape
6004
+ /** Select the arm model, or pass undefined to use texture detection. */
5369
6005
  setSlim(slim) {
5370
- console.log("#setSlim");
5371
- const changed = slim !== this.slim;
6006
+ this.options.slim = slim;
6007
+ this.updateSlim(slim ?? this.detectedSlim);
6008
+ }
6009
+ updateSlim(slim) {
6010
+ if (slim === this.slim) return;
5372
6011
  this.slim = slim;
5373
- if (changed) {
5374
- this.createMeshes();
5375
- }
5376
- if (changed) {
5377
- if (this.skinTextureSrc) {
5378
- this.setSkinTexture(this.skinTextureSrc);
6012
+ const offset = slim ? 0.5 : -0.5;
6013
+ for (const part of ["leftArm" /* LEFT_ARM */, "leftSleeve" /* LEFT_SLEEVE */, "rightArm" /* RIGHT_ARM */, "rightSleeve" /* RIGHT_SLEEVE */]) {
6014
+ const mesh = this.getMeshByName(part);
6015
+ if (mesh) {
6016
+ mesh.geometry = this.getBoxGeometry(part);
6017
+ mesh.position.x += part === "leftArm" /* LEFT_ARM */ || part === "leftSleeve" /* LEFT_SLEEVE */ ? offset : -offset;
5379
6018
  }
5380
6019
  }
5381
- console.log("#setSlim done");
6020
+ this.notifyDirty();
5382
6021
  }
5383
- setLegacy(legacy) {
5384
- if (legacy !== this.legacy) {
5385
- }
5386
- this.legacy = legacy;
6022
+ /** Select the texture layout, or pass undefined to detect it from image dimensions. */
6023
+ async setLegacy(legacy) {
6024
+ if (legacy === this.options.legacy) return;
6025
+ this.options.legacy = legacy;
6026
+ if (this.skinTextureSrc) await this.setSkinTexture(this.skinTextureSrc);
6027
+ }
6028
+ dispose() {
6029
+ this.skinLoad++;
6030
+ this.capeLoad++;
6031
+ super.dispose();
5387
6032
  }
5388
6033
  //TODO: layer toggles
5389
6034
  getBoxGeometry(part) {
5390
- console.log("slim", this.slim);
5391
6035
  const coordinates = this.slim ? slimSkinTextureCoordinates : classicSkinTextureCoordinates;
5392
6036
  const geometries = this.slim ? slimSkinGeometries : classicSkinGeometries;
5393
- return this._getBoxGeometryFromDimensions(geometries[part], coordinates[part], [64, 64], [this.skinTextureWidth, this.skinTextureHeight]);
6037
+ return this._getBoxGeometryFromDimensions(geometries[part], coordinates[part], [64, 64], [64, 64]);
5394
6038
  }
5395
6039
  };
5396
6040
 
5397
6041
  // src/renderer/MineRenderScene.ts
5398
- var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
6042
+ var MineRenderScene = class _MineRenderScene extends import_three19.Scene {
5399
6043
  constructor(options) {
5400
6044
  super();
5401
6045
  this.isMineRenderScene = true;
@@ -5404,12 +6048,14 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5404
6048
  this.dirty = true;
5405
6049
  this.observedObjects = /* @__PURE__ */ new Set();
5406
6050
  this.onObjectChange = (event) => {
5407
- var _a;
5408
- if (((_a = event.target) == null ? void 0 : _a.parent) === this) {
6051
+ if (event.target?.parent === this) {
5409
6052
  this.dirty = true;
5410
6053
  }
5411
6054
  };
5412
- this.options = (0, import_ts_deepmerge9.default)({}, _MineRenderScene.DEFAULT_OPTIONS, options ?? {});
6055
+ this.options = (0, import_ts_deepmerge8.default)({}, _MineRenderScene.DEFAULT_OPTIONS, options ?? {});
6056
+ }
6057
+ static {
6058
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge8.default)({}, {});
5413
6059
  }
5414
6060
  add(...objects) {
5415
6061
  for (const object of objects) {
@@ -5417,7 +6063,7 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5417
6063
  try {
5418
6064
  super.add(object);
5419
6065
  } finally {
5420
- if ((object == null ? void 0 : object.isObject3D) && object !== this) {
6066
+ if (object?.isObject3D && object !== this) {
5421
6067
  this.updateObjectRegistration(object, object.parent === this);
5422
6068
  }
5423
6069
  }
@@ -5460,15 +6106,21 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5460
6106
  return this.add(...object);
5461
6107
  }
5462
6108
  async addSceneObject(asset, objectSupplier, _options, parent = this) {
5463
- var _a, _b;
5464
6109
  console.log("addSceneObject", asset);
5465
6110
  console.log("parent", parent);
5466
6111
  console.log(_options);
5467
6112
  this.dirty = true;
5468
6113
  const obj = await objectSupplier();
5469
- if (((_a = obj == null ? void 0 : obj.options) == null ? void 0 : _a.instanceMeshes) && asset.key && ((_b = asset.key) == null ? void 0 : _b.assetType) === "models") {
6114
+ if (obj?.options?.instanceMeshes && asset.key && asset.key?.assetType === "models") {
5470
6115
  console.log("instanceMeshes + key");
5471
- const key = asset.key.serialize();
6116
+ let key = asset.key.serialize();
6117
+ if (isModelObject(obj)) {
6118
+ const { displayPosition, uvLockRotation, tints } = obj.options;
6119
+ if (displayPosition) key += `|display:${displayPosition}`;
6120
+ if (uvLockRotation) key += `|uvlock:${uvLockRotation.join(",")}`;
6121
+ const palette = Object.entries(tints ?? {}).sort(([a], [b]) => Number(a) - Number(b));
6122
+ if (palette.length) key += `|tints:${JSON.stringify(palette)}`;
6123
+ }
5472
6124
  return this.instanceManager.getOrCreate(key, async () => {
5473
6125
  obj.scene = this;
5474
6126
  await obj.init();
@@ -5495,10 +6147,10 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5495
6147
  this.dirty = true;
5496
6148
  const obj = new SkinObject(options);
5497
6149
  obj.scene = this;
5498
- await obj.init();
5499
6150
  if (skin) {
5500
- obj.setSkinTexture(skin);
6151
+ await obj.setSkinTexture(skin);
5501
6152
  }
6153
+ await obj.init();
5502
6154
  parent.add(obj);
5503
6155
  return obj;
5504
6156
  }
@@ -5506,24 +6158,22 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5506
6158
  return this.addSceneObject(entity, () => new EntityObject(entity, options), options, parent);
5507
6159
  }
5508
6160
  };
5509
- _MineRenderScene.DEFAULT_OPTIONS = (0, import_ts_deepmerge9.default)({}, {});
5510
- var MineRenderScene = _MineRenderScene;
5511
6161
  function isMineRenderScene(obj) {
5512
6162
  return obj.isMineRenderScene;
5513
6163
  }
5514
6164
 
5515
6165
  // src/renderer/Renderer.ts
5516
- var import_three19 = require("three");
5517
- var import_ts_deepmerge10 = __toESM(require_dist());
6166
+ var import_three21 = require("three");
6167
+ var import_ts_deepmerge9 = __toESM(require_dist());
5518
6168
  var import_stats = __toESM(require("stats.js"));
5519
6169
  var import_postprocessing = require("postprocessing");
5520
6170
 
5521
6171
  // src/three/OrbitControls.js
5522
- var import_three18 = require("three");
6172
+ var import_three20 = require("three");
5523
6173
  var _changeEvent = { type: "change" };
5524
6174
  var _startEvent = { type: "start" };
5525
6175
  var _endEvent = { type: "end" };
5526
- var OrbitControls = class extends import_three18.EventDispatcher {
6176
+ var OrbitControls = class extends import_three20.EventDispatcher {
5527
6177
  constructor(object, domElement) {
5528
6178
  super();
5529
6179
  if (domElement === void 0) console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.');
@@ -5532,7 +6182,7 @@ var OrbitControls = class extends import_three18.EventDispatcher {
5532
6182
  this.domElement = domElement;
5533
6183
  this.domElement.style.touchAction = "none";
5534
6184
  this.enabled = true;
5535
- this.target = new import_three18.Vector3();
6185
+ this.target = new import_three20.Vector3();
5536
6186
  this.minDistance = 0;
5537
6187
  this.maxDistance = Infinity;
5538
6188
  this.minZoom = 0;
@@ -5554,8 +6204,8 @@ var OrbitControls = class extends import_three18.EventDispatcher {
5554
6204
  this.autoRotate = false;
5555
6205
  this.autoRotateSpeed = 2;
5556
6206
  this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" };
5557
- this.mouseButtons = { LEFT: import_three18.MOUSE.ROTATE, MIDDLE: import_three18.MOUSE.DOLLY, RIGHT: import_three18.MOUSE.PAN };
5558
- this.touches = { ONE: import_three18.TOUCH.ROTATE, TWO: import_three18.TOUCH.DOLLY_PAN };
6207
+ this.mouseButtons = { LEFT: import_three20.MOUSE.ROTATE, MIDDLE: import_three20.MOUSE.DOLLY, RIGHT: import_three20.MOUSE.PAN };
6208
+ this.touches = { ONE: import_three20.TOUCH.ROTATE, TWO: import_three20.TOUCH.DOLLY_PAN };
5559
6209
  this.target0 = this.target.clone();
5560
6210
  this.position0 = this.object.position.clone();
5561
6211
  this.zoom0 = this.object.zoom;
@@ -5584,11 +6234,11 @@ var OrbitControls = class extends import_three18.EventDispatcher {
5584
6234
  state = STATE.NONE;
5585
6235
  };
5586
6236
  this.update = function() {
5587
- const offset = new import_three18.Vector3();
5588
- const quat = new import_three18.Quaternion().setFromUnitVectors(object.up, new import_three18.Vector3(0, 1, 0));
6237
+ const offset = new import_three20.Vector3();
6238
+ const quat = new import_three20.Quaternion().setFromUnitVectors(object.up, new import_three20.Vector3(0, 1, 0));
5589
6239
  const quatInverse = quat.clone().invert();
5590
- const lastPosition = new import_three18.Vector3();
5591
- const lastQuaternion = new import_three18.Quaternion();
6240
+ const lastPosition = new import_three20.Vector3();
6241
+ const lastQuaternion = new import_three20.Quaternion();
5592
6242
  const twoPI = 2 * Math.PI;
5593
6243
  return function update() {
5594
6244
  const position = scope.object.position;
@@ -5674,20 +6324,20 @@ var OrbitControls = class extends import_three18.EventDispatcher {
5674
6324
  };
5675
6325
  let state = STATE.NONE;
5676
6326
  const EPS = 1e-6;
5677
- const spherical = new import_three18.Spherical();
5678
- const sphericalDelta = new import_three18.Spherical();
6327
+ const spherical = new import_three20.Spherical();
6328
+ const sphericalDelta = new import_three20.Spherical();
5679
6329
  let scale = 1;
5680
- const panOffset = new import_three18.Vector3();
6330
+ const panOffset = new import_three20.Vector3();
5681
6331
  let zoomChanged = false;
5682
- const rotateStart = new import_three18.Vector2();
5683
- const rotateEnd = new import_three18.Vector2();
5684
- const rotateDelta = new import_three18.Vector2();
5685
- const panStart = new import_three18.Vector2();
5686
- const panEnd = new import_three18.Vector2();
5687
- const panDelta = new import_three18.Vector2();
5688
- const dollyStart = new import_three18.Vector2();
5689
- const dollyEnd = new import_three18.Vector2();
5690
- const dollyDelta = new import_three18.Vector2();
6332
+ const rotateStart = new import_three20.Vector2();
6333
+ const rotateEnd = new import_three20.Vector2();
6334
+ const rotateDelta = new import_three20.Vector2();
6335
+ const panStart = new import_three20.Vector2();
6336
+ const panEnd = new import_three20.Vector2();
6337
+ const panDelta = new import_three20.Vector2();
6338
+ const dollyStart = new import_three20.Vector2();
6339
+ const dollyEnd = new import_three20.Vector2();
6340
+ const dollyDelta = new import_three20.Vector2();
5691
6341
  const pointers = [];
5692
6342
  const pointerPositions = {};
5693
6343
  function getAutoRotationAngle() {
@@ -5703,7 +6353,7 @@ var OrbitControls = class extends import_three18.EventDispatcher {
5703
6353
  sphericalDelta.phi -= angle;
5704
6354
  }
5705
6355
  const panLeft = function() {
5706
- const v = new import_three18.Vector3();
6356
+ const v = new import_three20.Vector3();
5707
6357
  return function panLeft2(distance, objectMatrix) {
5708
6358
  v.setFromMatrixColumn(objectMatrix, 0);
5709
6359
  v.multiplyScalar(-distance);
@@ -5711,7 +6361,7 @@ var OrbitControls = class extends import_three18.EventDispatcher {
5711
6361
  };
5712
6362
  }();
5713
6363
  const panUp = function() {
5714
- const v = new import_three18.Vector3();
6364
+ const v = new import_three20.Vector3();
5715
6365
  return function panUp2(distance, objectMatrix) {
5716
6366
  if (scope.screenSpacePanning === true) {
5717
6367
  v.setFromMatrixColumn(objectMatrix, 1);
@@ -5724,7 +6374,7 @@ var OrbitControls = class extends import_three18.EventDispatcher {
5724
6374
  };
5725
6375
  }();
5726
6376
  const pan = function() {
5727
- const offset = new import_three18.Vector3();
6377
+ const offset = new import_three20.Vector3();
5728
6378
  return function pan2(deltaX, deltaY) {
5729
6379
  const element = scope.domElement;
5730
6380
  if (scope.object.isPerspectiveCamera) {
@@ -5973,12 +6623,12 @@ var OrbitControls = class extends import_three18.EventDispatcher {
5973
6623
  mouseAction = -1;
5974
6624
  }
5975
6625
  switch (mouseAction) {
5976
- case import_three18.MOUSE.DOLLY:
6626
+ case import_three20.MOUSE.DOLLY:
5977
6627
  if (scope.enableZoom === false) return;
5978
6628
  handleMouseDownDolly(event);
5979
6629
  state = STATE.DOLLY;
5980
6630
  break;
5981
- case import_three18.MOUSE.ROTATE:
6631
+ case import_three20.MOUSE.ROTATE:
5982
6632
  if (event.ctrlKey || event.metaKey || event.shiftKey) {
5983
6633
  if (scope.enablePan === false) return;
5984
6634
  handleMouseDownPan(event);
@@ -5989,7 +6639,7 @@ var OrbitControls = class extends import_three18.EventDispatcher {
5989
6639
  state = STATE.ROTATE;
5990
6640
  }
5991
6641
  break;
5992
- case import_three18.MOUSE.PAN:
6642
+ case import_three20.MOUSE.PAN:
5993
6643
  if (event.ctrlKey || event.metaKey || event.shiftKey) {
5994
6644
  if (scope.enableRotate === false) return;
5995
6645
  handleMouseDownRotate(event);
@@ -6045,12 +6695,12 @@ var OrbitControls = class extends import_three18.EventDispatcher {
6045
6695
  switch (pointers.length) {
6046
6696
  case 1:
6047
6697
  switch (scope.touches.ONE) {
6048
- case import_three18.TOUCH.ROTATE:
6698
+ case import_three20.TOUCH.ROTATE:
6049
6699
  if (scope.enableRotate === false) return;
6050
6700
  handleTouchStartRotate();
6051
6701
  state = STATE.TOUCH_ROTATE;
6052
6702
  break;
6053
- case import_three18.TOUCH.PAN:
6703
+ case import_three20.TOUCH.PAN:
6054
6704
  if (scope.enablePan === false) return;
6055
6705
  handleTouchStartPan();
6056
6706
  state = STATE.TOUCH_PAN;
@@ -6061,12 +6711,12 @@ var OrbitControls = class extends import_three18.EventDispatcher {
6061
6711
  break;
6062
6712
  case 2:
6063
6713
  switch (scope.touches.TWO) {
6064
- case import_three18.TOUCH.DOLLY_PAN:
6714
+ case import_three20.TOUCH.DOLLY_PAN:
6065
6715
  if (scope.enableZoom === false && scope.enablePan === false) return;
6066
6716
  handleTouchStartDollyPan();
6067
6717
  state = STATE.TOUCH_DOLLY_PAN;
6068
6718
  break;
6069
- case import_three18.TOUCH.DOLLY_ROTATE:
6719
+ case import_three20.TOUCH.DOLLY_ROTATE:
6070
6720
  if (scope.enableZoom === false && scope.enableRotate === false) return;
6071
6721
  handleTouchStartDollyRotate();
6072
6722
  state = STATE.TOUCH_DOLLY_ROTATE;
@@ -6133,7 +6783,7 @@ var OrbitControls = class extends import_three18.EventDispatcher {
6133
6783
  function trackPointer(event) {
6134
6784
  let position = pointerPositions[event.pointerId];
6135
6785
  if (position === void 0) {
6136
- position = new import_three18.Vector2();
6786
+ position = new import_three20.Vector2();
6137
6787
  pointerPositions[event.pointerId] = position;
6138
6788
  }
6139
6789
  position.set(event.pageX, event.pageY);
@@ -6153,19 +6803,17 @@ var MapControls = class extends OrbitControls {
6153
6803
  constructor(object, domElement) {
6154
6804
  super(object, domElement);
6155
6805
  this.screenSpacePanning = false;
6156
- this.mouseButtons.LEFT = import_three18.MOUSE.PAN;
6157
- this.mouseButtons.RIGHT = import_three18.MOUSE.ROTATE;
6158
- this.touches.ONE = import_three18.TOUCH.PAN;
6159
- this.touches.TWO = import_three18.TOUCH.DOLLY_ROTATE;
6806
+ this.mouseButtons.LEFT = import_three20.MOUSE.PAN;
6807
+ this.mouseButtons.RIGHT = import_three20.MOUSE.ROTATE;
6808
+ this.touches.ONE = import_three20.TOUCH.PAN;
6809
+ this.touches.TWO = import_three20.TOUCH.DOLLY_ROTATE;
6160
6810
  }
6161
6811
  };
6162
6812
 
6163
6813
  // src/renderer/Renderer.ts
6164
- var _Renderer = class _Renderer {
6814
+ var Renderer = class _Renderer {
6165
6815
  constructor(options) {
6166
6816
  this._dirty = true;
6167
- this._animationTimer = void 0;
6168
- this._animationFrame = void 0;
6169
6817
  this._resizeListener = void 0;
6170
6818
  this._disposed = false;
6171
6819
  this._debugHelpers = [];
@@ -6173,9 +6821,9 @@ var _Renderer = class _Renderer {
6173
6821
  this._changeListener = () => {
6174
6822
  this._dirty = true;
6175
6823
  };
6176
- this.options = (0, import_ts_deepmerge10.default)({}, _Renderer.DEFAULT_OPTIONS, options ?? {});
6824
+ this.options = (0, import_ts_deepmerge9.default)({}, _Renderer.DEFAULT_OPTIONS, options ?? {});
6177
6825
  this._animationLoop = this.animate.bind(this);
6178
- this._fpsTimer = this.options.render.fpsLimit > 0 ? 1e3 / this.options.render.fpsLimit : void 0;
6826
+ this._frameInterval = this.options.render.fpsLimit > 0 ? 1e3 / this.options.render.fpsLimit : void 0;
6179
6827
  this._scene = this.createScene();
6180
6828
  this._camera = this.createCamera();
6181
6829
  this._renderer = this.createRenderer();
@@ -6187,6 +6835,45 @@ var _Renderer = class _Renderer {
6187
6835
  this.init();
6188
6836
  this._controls = this.createControls();
6189
6837
  }
6838
+ static {
6839
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge9.default)({}, {
6840
+ camera: {
6841
+ type: "perspective",
6842
+ near: 1,
6843
+ far: 5e3,
6844
+ perspective: {
6845
+ aspect: void 0,
6846
+ fov: 50
6847
+ },
6848
+ orthographic: {
6849
+ left: void 0,
6850
+ right: void 0,
6851
+ top: void 0,
6852
+ bottom: void 0
6853
+ },
6854
+ position: new import_three21.Vector3(50, 50, 50),
6855
+ lookingAt: new import_three21.Vector3(0, 0, 0)
6856
+ },
6857
+ render: {
6858
+ fpsLimit: 60,
6859
+ stats: false,
6860
+ antialias: true,
6861
+ shade: true,
6862
+ autoResize: true,
6863
+ renderAlways: false
6864
+ },
6865
+ composer: {
6866
+ enabled: true
6867
+ },
6868
+ controls: {
6869
+ enabled: false
6870
+ },
6871
+ debug: {
6872
+ grid: false,
6873
+ axes: false
6874
+ }
6875
+ });
6876
+ }
6190
6877
  //<editor-fold desc="INIT">
6191
6878
  createScene() {
6192
6879
  return new MineRenderScene();
@@ -6195,14 +6882,14 @@ var _Renderer = class _Renderer {
6195
6882
  switch (this.options.camera.type) {
6196
6883
  case "perspective":
6197
6884
  default:
6198
- return new import_three19.PerspectiveCamera(
6885
+ return new import_three21.PerspectiveCamera(
6199
6886
  this.options.camera.perspective.fov,
6200
6887
  this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
6201
6888
  this.options.camera.near,
6202
6889
  this.options.camera.far
6203
6890
  );
6204
6891
  case "orthographic":
6205
- return new import_three19.OrthographicCamera(
6892
+ return new import_three21.OrthographicCamera(
6206
6893
  this.options.camera.orthographic.left ?? this.viewWidth / -2,
6207
6894
  this.options.camera.orthographic.right ?? this.viewWidth / 2,
6208
6895
  this.options.camera.orthographic.top ?? this.viewHeight / 2,
@@ -6213,7 +6900,7 @@ var _Renderer = class _Renderer {
6213
6900
  }
6214
6901
  }
6215
6902
  createRenderer() {
6216
- const renderer = new import_three19.WebGLRenderer({
6903
+ const renderer = new import_three21.WebGLRenderer({
6217
6904
  antialias: this.options.render.antialias,
6218
6905
  alpha: true,
6219
6906
  powerPreference: "high-performance",
@@ -6221,21 +6908,20 @@ var _Renderer = class _Renderer {
6221
6908
  });
6222
6909
  renderer.setClearColor(0, 0);
6223
6910
  renderer.shadowMap.enabled = true;
6224
- renderer.shadowMap.type = import_three19.PCFSoftShadowMap;
6225
- renderer.outputEncoding = import_three19.LinearEncoding;
6911
+ renderer.shadowMap.type = import_three21.PCFSoftShadowMap;
6912
+ renderer.outputColorSpace = import_three21.SRGBColorSpace;
6226
6913
  renderer.setSize(this.viewWidth, this.viewHeight);
6227
6914
  return renderer;
6228
6915
  }
6229
6916
  createComposer() {
6917
+ if (!this.options.composer.enabled) return void 0;
6230
6918
  const composer = new import_postprocessing.EffectComposer(this.renderer);
6231
- if (!this.options.composer.enabled) return composer;
6232
6919
  composer.setSize(this.viewWidth, this.viewHeight);
6233
6920
  composer.addPass(new import_postprocessing.RenderPass(this.scene, this.camera));
6234
6921
  return composer;
6235
6922
  }
6236
6923
  createControls() {
6237
- var _a;
6238
- if (!((_a = this.options.controls) == null ? void 0 : _a.enabled)) return void 0;
6924
+ if (!this.options.controls?.enabled) return void 0;
6239
6925
  const position = this.camera.position.clone();
6240
6926
  const controls = new OrbitControls(this.camera, this.renderer.domElement);
6241
6927
  this.camera.position.copy(position);
@@ -6257,20 +6943,20 @@ var _Renderer = class _Renderer {
6257
6943
  window["__THREE_DEVTOOLS__"].dispatchEvent(new CustomEvent("observe", { detail: this.scene }));
6258
6944
  }
6259
6945
  if (this.options.debug.grid) {
6260
- const gridHelper = new import_three19.GridHelper(128, 16);
6946
+ const gridHelper = new import_three21.GridHelper(128, 16);
6261
6947
  this._debugHelpers.push(gridHelper);
6262
6948
  this.scene.add(gridHelper);
6263
- const gridHelper2 = new import_three19.GridHelper(128, 16);
6949
+ const gridHelper2 = new import_three21.GridHelper(128, 16);
6264
6950
  this._debugHelpers.push(gridHelper2);
6265
6951
  gridHelper2.rotation.x = 90 * (Math.PI / 180);
6266
6952
  this.scene.add(gridHelper2);
6267
- const gridHelper3 = new import_three19.GridHelper(128, 16);
6953
+ const gridHelper3 = new import_three21.GridHelper(128, 16);
6268
6954
  this._debugHelpers.push(gridHelper3);
6269
6955
  gridHelper3.rotation.z = 90 * (Math.PI / 180);
6270
6956
  this.scene.add(gridHelper3);
6271
6957
  }
6272
6958
  if (this.options.debug.axes) {
6273
- const axesHelper = new import_three19.AxesHelper(64);
6959
+ const axesHelper = new import_three21.AxesHelper(64);
6274
6960
  this._debugHelpers.push(axesHelper);
6275
6961
  this.scene.add(axesHelper);
6276
6962
  }
@@ -6338,7 +7024,7 @@ var _Renderer = class _Renderer {
6338
7024
  this.camera.updateProjectionMatrix();
6339
7025
  }
6340
7026
  this.renderer.setSize(width, height);
6341
- this.composer.setSize(width, height);
7027
+ this.composer?.setSize(width, height);
6342
7028
  this._dirty = true;
6343
7029
  }
6344
7030
  //<editor-fold desc="RENDER">
@@ -6357,12 +7043,7 @@ var _Renderer = class _Renderer {
6357
7043
  stop() {
6358
7044
  if (this._disposed) return;
6359
7045
  this.renderer.setAnimationLoop(null);
6360
- if (this._animationTimer)
6361
- clearTimeout(this._animationTimer);
6362
- this._animationTimer = void 0;
6363
- if (this._animationFrame)
6364
- cancelAnimationFrame(this._animationFrame);
6365
- this._animationFrame = void 0;
7046
+ this._nextFrameTime = void 0;
6366
7047
  }
6367
7048
  /**
6368
7049
  * Stops rendering and releases owned resources. Repeated calls have no effect, and a disposed
@@ -6370,7 +7051,6 @@ var _Renderer = class _Renderer {
6370
7051
  * controls must be managed by their owners.
6371
7052
  */
6372
7053
  dispose() {
6373
- var _a;
6374
7054
  if (this._disposed) return;
6375
7055
  this.stop();
6376
7056
  this._disposed = true;
@@ -6384,7 +7064,7 @@ var _Renderer = class _Renderer {
6384
7064
  }
6385
7065
  }
6386
7066
  this._eventDispatchers.clear();
6387
- (_a = this._stats) == null ? void 0 : _a.dom.remove();
7067
+ this._stats?.dom.remove();
6388
7068
  this._stats = void 0;
6389
7069
  this.renderer.domElement.remove();
6390
7070
  this._element = void 0;
@@ -6403,26 +7083,30 @@ var _Renderer = class _Renderer {
6403
7083
  }
6404
7084
  }
6405
7085
  this._debugHelpers.length = 0;
6406
- this.composer.dispose();
7086
+ this.composer?.dispose();
6407
7087
  this.renderer.dispose();
6408
7088
  this.renderer.forceContextLoss();
6409
7089
  }
6410
- animate(t) {
6411
- var _a;
7090
+ animate(t = performance.now()) {
6412
7091
  if (this._disposed) return;
6413
- if (this._stats) {
6414
- this._stats.begin();
6415
- }
6416
- if ((_a = this._controls) == null ? void 0 : _a.enabled) {
7092
+ if (this._controls?.enabled) {
6417
7093
  this._controls.update();
6418
7094
  }
6419
7095
  if (this._disposed) return;
6420
- if (this.dirty || this.options.render.renderAlways) {
6421
- if (this.options.composer.enabled) {
6422
- this.composer.render();
6423
- } else {
6424
- this.renderer.render(this.scene, this.camera);
6425
- }
7096
+ if (!this.dirty && !this.options.render.renderAlways) return;
7097
+ const interval = this._frameInterval;
7098
+ if (interval) {
7099
+ const next = this._nextFrameTime;
7100
+ if (next !== void 0 && t + 0.1 < next) return;
7101
+ this._nextFrameTime = next !== void 0 && t - next < interval ? next + interval : t + interval;
7102
+ }
7103
+ if (this._stats) {
7104
+ this._stats.begin();
7105
+ }
7106
+ if (this.options.composer.enabled && this.composer) {
7107
+ this.composer.render();
7108
+ } else {
7109
+ this.renderer.render(this.scene, this.camera);
6426
7110
  }
6427
7111
  this.dirty = false;
6428
7112
  if (this._stats) {
@@ -6438,12 +7122,10 @@ var _Renderer = class _Renderer {
6438
7122
  return this.element === document.body;
6439
7123
  }
6440
7124
  get viewWidth() {
6441
- var _a;
6442
- return this.attachedToBody ? window.innerWidth : ((_a = this.element) == null ? void 0 : _a.offsetWidth) || 0;
7125
+ return this.attachedToBody ? window.innerWidth : this.element?.offsetWidth || 0;
6443
7126
  }
6444
7127
  get viewHeight() {
6445
- var _a;
6446
- return this.attachedToBody ? window.innerHeight : ((_a = this.element) == null ? void 0 : _a.offsetHeight) || 0;
7128
+ return this.attachedToBody ? window.innerHeight : this.element?.offsetHeight || 0;
6447
7129
  }
6448
7130
  get scene() {
6449
7131
  return this._scene;
@@ -6463,44 +7145,6 @@ var _Renderer = class _Renderer {
6463
7145
  }
6464
7146
  ///
6465
7147
  };
6466
- _Renderer.DEFAULT_OPTIONS = (0, import_ts_deepmerge10.default)({}, {
6467
- camera: {
6468
- type: "perspective",
6469
- near: 1,
6470
- far: 5e3,
6471
- perspective: {
6472
- aspect: void 0,
6473
- fov: 50
6474
- },
6475
- orthographic: {
6476
- left: void 0,
6477
- right: void 0,
6478
- top: void 0,
6479
- bottom: void 0
6480
- },
6481
- position: new import_three19.Vector3(50, 50, 50),
6482
- lookingAt: new import_three19.Vector3(0, 0, 0)
6483
- },
6484
- render: {
6485
- fpsLimit: 60,
6486
- stats: false,
6487
- antialias: true,
6488
- shade: true,
6489
- autoResize: true,
6490
- renderAlways: false
6491
- },
6492
- composer: {
6493
- enabled: true
6494
- },
6495
- controls: {
6496
- enabled: false
6497
- },
6498
- debug: {
6499
- grid: false,
6500
- axes: false
6501
- }
6502
- });
6503
- var Renderer = _Renderer;
6504
7148
 
6505
7149
  // src/skin/Skins.ts
6506
7150
  var Skins = class {
@@ -6512,7 +7156,7 @@ var Skins = class {
6512
7156
  return this.fromUsername(uuidOrUsername);
6513
7157
  }
6514
7158
  static async fromUuid(uuid) {
6515
- return this.getSkinProxySkinUrl(uuid);
7159
+ return this.getMcProxySkinUrl(uuid);
6516
7160
  }
6517
7161
  static async fromUsername(username) {
6518
7162
  return this.usernameToUuid(username).then((uuid) => {
@@ -6539,7 +7183,7 @@ var Skins = class {
6539
7183
  return this.capeFromUsername(uuidOrUsername);
6540
7184
  }
6541
7185
  static async capeFromUuid(uuid) {
6542
- return this.getSkinProxyCapeUrl(uuid);
7186
+ return this.getMcProxyCapeUrl(uuid);
6543
7187
  }
6544
7188
  static async capeFromUsername(username) {
6545
7189
  return this.usernameToUuid(username).then((uuid) => {
@@ -6549,19 +7193,31 @@ var Skins = class {
6549
7193
  return void 0;
6550
7194
  });
6551
7195
  }
6552
- static async capeFromCapesDev(uuid, capeType = "minecraft") {
6553
- return this.getCapesDev(uuid, capeType).then((cape) => {
6554
- if (cape) {
6555
- return cape == null ? void 0 : cape.stillImageUrl;
6556
- }
6557
- return void 0;
6558
- });
7196
+ /** Returns a full static cape texture for a username or UUID. */
7197
+ static async capeFromCapesDev(player, capeType = "minecraft") {
7198
+ const cape = await this.getCapesDev(player, capeType);
7199
+ return cape?.exists ? cape.imageUrls?.still?.full : void 0;
6559
7200
  }
6560
7201
  //</editor-fold>
6561
7202
  //<editor-fold desc="Helpers">
6562
7203
  static async usernameToUuid(username) {
6563
- return this.usernameToUuidSkinProxy(username);
7204
+ return this.usernameToUuidMcProxy(username);
7205
+ }
7206
+ static async usernameToUuidMcProxy(username) {
7207
+ return Requests.genericRequest({
7208
+ baseURL: "https://mcproxy.dev",
7209
+ url: "/uuid/" + username
7210
+ }).then((res) => {
7211
+ if (res.status === 200) {
7212
+ return res.data["data"]["id"];
7213
+ }
7214
+ return void 0;
7215
+ }).catch((err) => {
7216
+ console.warn(err);
7217
+ return void 0;
7218
+ });
6564
7219
  }
7220
+ /** @deprecated **/
6565
7221
  static async usernameToUuidSkinProxy(username) {
6566
7222
  return Requests.genericRequest({
6567
7223
  baseURL: "https://minecraft-skin-proxy.inventive.workers.dev",
@@ -6614,18 +7270,15 @@ var Skins = class {
6614
7270
  return void 0;
6615
7271
  });
6616
7272
  }
6617
- static async getCapesDev(uuid, type = "all") {
7273
+ static async getCapesDev(player, type = "all") {
6618
7274
  return Requests.genericRequest({
6619
7275
  baseURL: "https://api.capes.dev",
6620
- url: "/load/" + uuid + "/" + type
7276
+ url: "/load/" + encodeURIComponent(player) + "/" + encodeURIComponent(type)
6621
7277
  }).then((res) => {
6622
7278
  if (res.status === 200) {
6623
7279
  return res.data;
6624
7280
  }
6625
7281
  return void 0;
6626
- }).catch((err) => {
6627
- console.warn(err);
6628
- return void 0;
6629
7282
  });
6630
7283
  }
6631
7284
  static getCrafatarSkinUrl(uuid) {
@@ -6640,20 +7293,28 @@ var Skins = class {
6640
7293
  static getMineSkinPlayerSkinUrl(uuid) {
6641
7294
  return "https://mineskin.org/skin/player/" + uuid;
6642
7295
  }
7296
+ /** @deprecated **/
6643
7297
  static getSkinProxySkinUrl(uuid) {
6644
7298
  return "https://minecraft-skin-proxy.inventive.workers.dev/skin/" + uuid;
6645
7299
  }
7300
+ /** @deprecated **/
6646
7301
  static getSkinProxyCapeUrl(uuid) {
6647
7302
  return "https://minecraft-skin-proxy.inventive.workers.dev/cape/" + uuid;
6648
7303
  }
7304
+ static getMcProxySkinUrl(uuid) {
7305
+ return "https://mcproxy.dev/skin/" + uuid;
7306
+ }
7307
+ static getMcProxyCapeUrl(uuid) {
7308
+ return "https://mcproxy.dev/cape/" + uuid;
7309
+ }
6649
7310
  //</editor-fold>
6650
7311
  };
6651
7312
 
6652
7313
  // src/world/Chunk.ts
6653
- var import_three22 = require("three");
7314
+ var import_three24 = require("three");
6654
7315
 
6655
7316
  // src/world/MineRenderWorld.ts
6656
- var import_three21 = require("three");
7317
+ var import_three23 = require("three");
6657
7318
  var MineRenderWorld = class {
6658
7319
  constructor(scene) {
6659
7320
  this._size = 4;
@@ -6664,10 +7325,10 @@ var MineRenderWorld = class {
6664
7325
  }
6665
7326
  getBlockAt(posOrX, y, z) {
6666
7327
  if (typeof posOrX == "number") {
6667
- return this.getBlockAt(new import_three21.Vector3(posOrX, y, z));
7328
+ return this.getBlockAt(new import_three23.Vector3(posOrX, y, z));
6668
7329
  }
6669
7330
  if (isTripleArray(posOrX)) {
6670
- return this.getBlockAt(new import_three21.Vector3(posOrX[0], posOrX[1], posOrX[2]));
7331
+ return this.getBlockAt(new import_three23.Vector3(posOrX[0], posOrX[1], posOrX[2]));
6671
7332
  }
6672
7333
  const chunk = this.getChunkAt(posOrX);
6673
7334
  if (typeof chunk === "undefined") {
@@ -6678,10 +7339,10 @@ var MineRenderWorld = class {
6678
7339
  }
6679
7340
  async setBlockAt(posOrX, yOrBlock, z, block) {
6680
7341
  if (typeof posOrX == "number") {
6681
- return this.setBlockAt(new import_three21.Vector3(posOrX, yOrBlock, z), block);
7342
+ return this.setBlockAt(new import_three23.Vector3(posOrX, yOrBlock, z), block);
6682
7343
  }
6683
7344
  if (isTripleArray(posOrX)) {
6684
- return this.setBlockAt(new import_three21.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
7345
+ return this.setBlockAt(new import_three23.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
6685
7346
  }
6686
7347
  this.validatePosBounds(posOrX);
6687
7348
  const chunk = this.getOrCreateChunkAt(posOrX);
@@ -6709,7 +7370,7 @@ var MineRenderWorld = class {
6709
7370
  console.log("CHUNKS", this._chunks);
6710
7371
  for (let chunk of this._chunks.values()) {
6711
7372
  console.log("dispose chunk", chunk);
6712
- await (chunk == null ? void 0 : chunk.dispose());
7373
+ await chunk?.dispose();
6713
7374
  }
6714
7375
  this._chunks.clear();
6715
7376
  }
@@ -6727,14 +7388,14 @@ var MineRenderWorld = class {
6727
7388
  return this._chunks[index];
6728
7389
  }
6729
7390
  static worldToScenePosition(pos) {
6730
- return new import_three21.Vector3(
7391
+ return new import_three23.Vector3(
6731
7392
  pos.x * 16,
6732
7393
  pos.y * 16,
6733
7394
  pos.z * 16
6734
7395
  );
6735
7396
  }
6736
7397
  static sceneToWorldPosition(pos) {
6737
- return new import_three21.Vector3(
7398
+ return new import_three23.Vector3(
6738
7399
  pos.x / 16,
6739
7400
  pos.y / 16,
6740
7401
  pos.z / 16
@@ -6763,7 +7424,7 @@ var MineRenderWorld = class {
6763
7424
  };
6764
7425
 
6765
7426
  // src/world/Chunk.ts
6766
- var p12 = prefix("Chunk");
7427
+ var p11 = prefix("Chunk");
6767
7428
  var Chunk = class _Chunk {
6768
7429
  constructor(scene, x, y, z) {
6769
7430
  this._blocks = [];
@@ -6771,12 +7432,12 @@ var Chunk = class _Chunk {
6771
7432
  this.x = x;
6772
7433
  this.y = y;
6773
7434
  this.z = z;
6774
- let anchor = new import_three22.Object3D();
7435
+ let anchor = new import_three24.Object3D();
6775
7436
  this._anchor = anchor;
6776
7437
  scene.add(anchor);
6777
7438
  anchor.position.set(this.x * 256 + 128 - 8, this.y * 256 + 128 - 8, this.z * 256 + 128 - 8);
6778
7439
  addBox3WireframeToObject(
6779
- new import_three22.Box3(new import_three22.Vector3(0, 0, 0), new import_three22.Vector3(256, 256, 256)),
7440
+ new import_three24.Box3(new import_three24.Vector3(0, 0, 0), new import_three24.Vector3(256, 256, 256)),
6780
7441
  anchor,
6781
7442
  16776960,
6782
7443
  4
@@ -6784,10 +7445,10 @@ var Chunk = class _Chunk {
6784
7445
  }
6785
7446
  getBlockAt(posOrX, y, z) {
6786
7447
  if (typeof posOrX == "number") {
6787
- return this.getBlockAt(new import_three22.Vector3(posOrX, y, z));
7448
+ return this.getBlockAt(new import_three24.Vector3(posOrX, y, z));
6788
7449
  }
6789
7450
  if (isTripleArray(posOrX)) {
6790
- return this.getBlockAt(new import_three22.Vector3(posOrX[0], posOrX[1], posOrX[2]));
7451
+ return this.getBlockAt(new import_three24.Vector3(posOrX[0], posOrX[1], posOrX[2]));
6791
7452
  }
6792
7453
  const pos = this.worldPosToChunkPos(posOrX);
6793
7454
  const index = _Chunk.chunkPosToBlockIndex(pos);
@@ -6795,10 +7456,10 @@ var Chunk = class _Chunk {
6795
7456
  }
6796
7457
  async setBlockAt(posOrX, yOrBlock, z, block) {
6797
7458
  if (typeof posOrX == "number") {
6798
- return this.setBlockAt(new import_three22.Vector3(posOrX, yOrBlock, z), block);
7459
+ return this.setBlockAt(new import_three24.Vector3(posOrX, yOrBlock, z), block);
6799
7460
  }
6800
7461
  if (isTripleArray(posOrX)) {
6801
- return this.setBlockAt(new import_three22.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
7462
+ return this.setBlockAt(new import_three24.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
6802
7463
  }
6803
7464
  const worldPos = posOrX;
6804
7465
  const pos = this.worldPosToChunkPos(worldPos);
@@ -6815,7 +7476,7 @@ var Chunk = class _Chunk {
6815
7476
  const index = _Chunk.chunkPosToBlockIndex(pos);
6816
7477
  const current = this._blocks[index];
6817
7478
  if (typeof current !== "undefined") {
6818
- console.debug(p12, "deleting existing block at", pos, worldPos, index);
7479
+ console.debug(p11, "deleting existing block at", pos, worldPos, index);
6819
7480
  current.object.removeFromScene();
6820
7481
  delete this._blocks[index];
6821
7482
  }
@@ -6844,7 +7505,7 @@ var Chunk = class _Chunk {
6844
7505
  }
6845
7506
  async clear() {
6846
7507
  let promises = [];
6847
- let pos = new import_three22.Vector3();
7508
+ let pos = new import_three24.Vector3();
6848
7509
  for (let x = 0; x < 16; x++) {
6849
7510
  for (let z = 0; z < 16; z++) {
6850
7511
  for (let y = 0; y < 16; y++) {
@@ -6863,14 +7524,14 @@ var Chunk = class _Chunk {
6863
7524
  return pos.y * 16 * 16 + pos.z * 16 + pos.x;
6864
7525
  }
6865
7526
  worldPosToChunkPos(pos) {
6866
- return new import_three22.Vector3(
7527
+ return new import_three24.Vector3(
6867
7528
  pos.x - this.x * 16,
6868
7529
  pos.y - this.y * 16,
6869
7530
  pos.z - this.z * 16
6870
7531
  );
6871
7532
  }
6872
7533
  chunkPosToWorldPos(pos) {
6873
- return new import_three22.Vector3(
7534
+ return new import_three24.Vector3(
6874
7535
  this.x * 16 + pos.x,
6875
7536
  this.y * 16 + pos.y,
6876
7537
  this.z * 16 + pos.z
@@ -6882,6 +7543,7 @@ var Chunk = class _Chunk {
6882
7543
  AXES,
6883
7544
  ArchiveAssetSource,
6884
7545
  AssetKey,
7546
+ AssetLoadError,
6885
7547
  AssetLoader,
6886
7548
  AssetParser,
6887
7549
  AssetSource,
@@ -6891,9 +7553,9 @@ var Chunk = class _Chunk {
6891
7553
  BUILTIN_GENERATED,
6892
7554
  BasicAssetKey,
6893
7555
  BatchedExecutor,
6894
- BlockEntityModels,
6895
7556
  BlockObject,
6896
7557
  BlockStates,
7558
+ BlockTints,
6897
7559
  BrowserArchiveProxy,
6898
7560
  CUBE_FACES,
6899
7561
  Caching,
@@ -6908,8 +7570,8 @@ var Chunk = class _Chunk {
6908
7570
  DISPLAY_POSITIONS,
6909
7571
  DefaultBlockStates,
6910
7572
  DisplayPosition,
7573
+ DisplayTransforms,
6911
7574
  Entities,
6912
- EntityModels,
6913
7575
  EntityObject,
6914
7576
  Env,
6915
7577
  Geometries,
@@ -6939,6 +7601,7 @@ var Chunk = class _Chunk {
6939
7601
  OrbitControls,
6940
7602
  PersistentCache,
6941
7603
  Renderer,
7604
+ RequestError,
6942
7605
  Requests,
6943
7606
  SKIN_PARTS,
6944
7607
  SceneInspector,
@@ -6946,8 +7609,10 @@ var Chunk = class _Chunk {
6946
7609
  SceneStats,
6947
7610
  SceneStatsDisplay,
6948
7611
  SchematicParser,
7612
+ SkinImage,
6949
7613
  SkinObject,
6950
7614
  SkinPart,
7615
+ SkinTextures,
6951
7616
  Skins,
6952
7617
  StructureParser,
6953
7618
  TextureAtlas,
@@ -6962,10 +7627,10 @@ var Chunk = class _Chunk {
6962
7627
  addWireframeToObject,
6963
7628
  applyElementRotation,
6964
7629
  applyGenericRotation,
6965
- applyModelPartRotation,
6966
7630
  axisToVec3,
6967
7631
  base64decode,
6968
7632
  base64encode,
7633
+ capeTextureSizes,
6969
7634
  captureException,
6970
7635
  changeEvent,
6971
7636
  clampRotationDegrees,