minerender 2.1.0-alpha.2 → 2.1.0-alpha.21

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
- exports.default = merge11;
120
+ exports.default = merge10;
129
121
  }
130
122
  });
131
123
 
@@ -135,6 +127,7 @@ __export(index_browser_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,
@@ -147,6 +140,7 @@ __export(index_browser_exports, {
147
140
  BlockEntityModels: () => BlockEntityModels,
148
141
  BlockObject: () => BlockObject,
149
142
  BlockStates: () => BlockStates,
143
+ BlockTints: () => BlockTints,
150
144
  BrowserArchiveProxy: () => BrowserArchiveProxy,
151
145
  BrowserCache: () => BrowserCache,
152
146
  BrowserEnv: () => BrowserEnv,
@@ -192,6 +186,7 @@ __export(index_browser_exports, {
192
186
  OrbitControls: () => OrbitControls,
193
187
  PersistentCache: () => PersistentCache,
194
188
  Renderer: () => Renderer,
189
+ RequestError: () => RequestError,
195
190
  Requests: () => Requests,
196
191
  SKIN_PARTS: () => SKIN_PARTS,
197
192
  SceneInspector: () => SceneInspector,
@@ -308,17 +303,20 @@ var _PersistentCache = class _PersistentCache {
308
303
  static open(name) {
309
304
  return Env.provider.openCache(name, _PersistentCache.VERSION);
310
305
  }
306
+ /** Loads a missing entry and stores only non-nullish results. */
311
307
  async getOrLoad(key, loader) {
312
308
  let v = await this.get(key);
313
309
  if (typeof v === "undefined" || v === null) {
314
310
  v = await loader(key);
315
- await this.put(key, v);
311
+ if (typeof v !== "undefined" && v !== null) {
312
+ await this.put(key, v);
313
+ }
316
314
  }
317
315
  return v;
318
316
  }
319
317
  };
320
318
  /** Bump to invalidate every persisted entry. */
321
- _PersistentCache.VERSION = 1;
319
+ _PersistentCache.VERSION = 2;
322
320
  var PersistentCache = _PersistentCache;
323
321
 
324
322
  // src/env/browser/BrowserCache.ts
@@ -419,7 +417,8 @@ var BrowserEnv = class {
419
417
  }
420
418
  openCache(name, version) {
421
419
  return new BrowserCache(import_localforage.default.createInstance({
422
- name,
420
+ // IndexedDB schema upgrades retain records; each cache generation needs its own database.
421
+ name: name + version,
423
422
  version
424
423
  }));
425
424
  }
@@ -436,7 +435,7 @@ registerBrowserEnv();
436
435
  // src/Axis.ts
437
436
  var import_three = require("three");
438
437
  var Axis = /* @__PURE__ */ ((Axis3) => {
439
- Axis3["X"] = "X";
438
+ Axis3["X"] = "x";
440
439
  Axis3["Y"] = "y";
441
440
  Axis3["Z"] = "z";
442
441
  return Axis3;
@@ -444,7 +443,7 @@ var Axis = /* @__PURE__ */ ((Axis3) => {
444
443
  var AXES = Object.values(Axis);
445
444
  function axisToVec3(axis) {
446
445
  switch (axis) {
447
- case "X" /* X */:
446
+ case "x" /* X */:
448
447
  return new import_three.Vector3(1, 0, 0);
449
448
  case "y" /* Y */:
450
449
  return new import_three.Vector3(0, 1, 0);
@@ -547,7 +546,10 @@ function serializeMeshKey(key) {
547
546
  // src/cache/Caching.ts
548
547
  var import_loading_cache = require("@inventivetalent/loading-cache");
549
548
  var import_time = require("@inventivetalent/time");
550
- var Caching = class {
549
+ var _Caching = class _Caching {
550
+ static createAssetCache() {
551
+ 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();
552
+ }
551
553
  /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */
552
554
  static get all() {
553
555
  return [
@@ -564,7 +566,11 @@ var Caching = class {
564
566
  this.rawModelCache,
565
567
  this.mergedModelCache,
566
568
  this.modelTextureAtlasCache,
567
- this.blockStateCache
569
+ this.blockStateCache,
570
+ this.listAssetCache,
571
+ this.defaultBlockStatesCache,
572
+ this.blockTintCache,
573
+ this.entityModelsCache
568
574
  ];
569
575
  }
570
576
  static clear() {
@@ -575,8 +581,8 @@ var Caching = class {
575
581
  /**
576
582
  * Clears every cache and stops its expiry timer.
577
583
  *
578
- * loading-cache reschedules that timer indefinitely, so a Node process will not exit until
579
- * this is called - see {@link shutdown}.
584
+ * Expiry timers are unref'd in Node, so idle processes can exit without this cleanup.
585
+ * Use {@link shutdown} to also stop requests and the shared Ticker.
580
586
  */
581
587
  static end() {
582
588
  for (const cache of this.all) {
@@ -590,20 +596,25 @@ var Caching = class {
590
596
  };
591
597
  }
592
598
  };
593
- 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();
594
- 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();
595
- 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();
596
- 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();
597
- 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();
598
- 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();
599
- 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();
600
- 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();
601
- 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();
602
- 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();
603
- 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();
604
- 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();
605
- 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();
606
- 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();
599
+ _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();
600
+ _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();
601
+ _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();
602
+ _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();
603
+ _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();
604
+ _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();
605
+ _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();
606
+ _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();
607
+ _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();
608
+ _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();
609
+ _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();
610
+ _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();
611
+ _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();
612
+ _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();
613
+ _Caching.listAssetCache = _Caching.createAssetCache();
614
+ _Caching.defaultBlockStatesCache = _Caching.createAssetCache();
615
+ _Caching.blockTintCache = _Caching.createAssetCache();
616
+ _Caching.entityModelsCache = _Caching.createAssetCache();
617
+ var Caching = _Caching;
607
618
 
608
619
  // src/Geometries.ts
609
620
  var Geometries = class _Geometries {
@@ -624,13 +635,14 @@ var Geometries = class _Geometries {
624
635
  };
625
636
 
626
637
  // src/Materials.ts
627
- var import_three6 = require("three");
638
+ var import_three5 = require("three");
628
639
 
629
640
  // src/texture/Textures.ts
630
- var import_three5 = require("three");
641
+ var import_three4 = require("three");
631
642
 
632
643
  // src/texture/TextureLoader.ts
633
- var import_three4 = require("three");
644
+ var import_three3 = require("three");
645
+ var THREE = __toESM(require("three"));
634
646
 
635
647
  // src/canvas/CanvasCompat.ts
636
648
  function createImage(width, height) {
@@ -641,9 +653,7 @@ function createCanvas(width, height) {
641
653
  }
642
654
 
643
655
  // src/request/Requests.ts
644
- var import_axios = __toESM(require("axios"));
645
656
  var import_jobqu = require("jobqu");
646
- var import_time2 = require("@inventivetalent/time");
647
657
 
648
658
  // src/util/log.ts
649
659
  var Reset = "\x1B[0m";
@@ -653,198 +663,170 @@ function prefix(prefix2) {
653
663
  return `${FgGreen}MR${BgBlack}${prefix2 ?? ""}${Reset}`;
654
664
  }
655
665
 
656
- // src/util/BatchedExecutor.ts
657
- var BatchedExecutor = class {
658
- constructor(interval = 1, batch = 30) {
659
- this.interval = interval;
660
- this.batch = batch;
661
- this.queue = [];
662
- this.task = setInterval(() => this.run());
663
- }
664
- submit(task) {
665
- this.queue.push(task);
666
- }
667
- run() {
668
- for (let i = 0; i < this.batch; i++) {
669
- this.runNext();
670
- }
671
- }
672
- runNext() {
673
- let next = this.queue.shift();
674
- if (next) next();
666
+ // src/request/Requests.ts
667
+ var p = prefix("Requests");
668
+ var RequestError = class extends Error {
669
+ constructor(message, response, cause) {
670
+ super(message);
671
+ this.response = response;
672
+ this.cause = cause;
673
+ this.name = "RequestError";
675
674
  }
676
675
  };
677
-
678
- // src/util/model.ts
679
- var import_three3 = require("three");
680
- function applyElementRotation(rotation, geometry) {
681
- const origin = new import_three3.Vector3(rotation.origin[0], rotation.origin[1], rotation.origin[2]);
682
- geometry.translate(-origin.x, -origin.y, -origin.z);
683
- switch (rotation.axis) {
684
- case "X" /* X */:
685
- geometry.rotateX(toRadians(rotation.angle));
686
- break;
687
- case "y" /* Y */:
688
- geometry.rotateY(toRadians(rotation.angle));
689
- break;
690
- case "z" /* Z */:
691
- geometry.rotateZ(toRadians(rotation.angle));
692
- break;
693
- }
694
- if (rotation.rescale) {
695
- if (Math.abs(rotation.angle) === 22.5) {
696
- const s = 1 / Math.cos(0.39269909262657166);
697
- geometry.scale(s, 1, s);
698
- } else {
699
- const s = 1 / Math.cos(0.7853981852531433);
700
- geometry.scale(s, 1, s);
676
+ async function fetchRequest(config, defaultBaseURL) {
677
+ const { url, baseURL = defaultBaseURL, timeout = 5e3, responseType = "json", signal, ...options } = config;
678
+ const target = baseURL && !/^([a-z][a-z\d+.-]*:|\/\/)/i.test(url) ? `${baseURL.replace(/\/+$/, "")}/${url.replace(/^\/+/, "")}` : url;
679
+ const headers = new Headers(options.headers);
680
+ if (typeof window === "undefined" && !headers.has("User-Agent")) {
681
+ headers.set("User-Agent", "MineRender");
682
+ }
683
+ const attemptSignal = AbortSignal.any([
684
+ ...signal ? [signal] : [],
685
+ ...timeout === 0 ? [] : [AbortSignal.timeout(timeout)]
686
+ ]);
687
+ const request = new Request(target, { ...options, headers, signal: attemptSignal });
688
+ attemptSignal.throwIfAborted();
689
+ try {
690
+ const response = await fetch(request);
691
+ const result = {
692
+ data: void 0,
693
+ status: response.status,
694
+ statusText: response.statusText,
695
+ headers: response.headers,
696
+ url: response.url
697
+ };
698
+ if (!response.ok) {
699
+ await response.body?.cancel().catch(() => {
700
+ });
701
+ throw new RequestError(`Request failed with status ${response.status}`, result);
701
702
  }
703
+ const emptyBody = request.method === "HEAD" || response.status === 204 || response.status === 205;
704
+ const data = responseType === "arraybuffer" ? await response.arrayBuffer() : emptyBody || response.body === null ? void 0 : await response.json();
705
+ return { ...result, data };
706
+ } catch (error) {
707
+ attemptSignal.throwIfAborted();
708
+ if (/^https?:/.test(request.url) && request.redirect !== "error" && error instanceof TypeError) {
709
+ throw new RequestError("Network request failed", void 0, error);
710
+ }
711
+ throw error;
702
712
  }
703
- geometry.translate(origin.x, origin.y, origin.z);
704
- }
705
- function applyModelPartRotation(modelPart, geometry) {
706
- const origin = new import_three3.Vector3(modelPart.pivotX, modelPart.pivotY, modelPart.pivotZ);
707
- geometry.translate(-origin.x, -origin.y, -origin.z);
708
- geometry.rotateX(toRadians(modelPart.pitch));
709
- geometry.rotateY(toRadians(modelPart.yaw));
710
- geometry.rotateZ(toRadians(modelPart.roll));
711
- geometry.translate(origin.x, origin.y, origin.z);
712
713
  }
713
- function applyGenericRotation(axis, rotation, obj) {
714
- switch (axis) {
715
- case "X" /* X */:
716
- obj.rotateOnAxis(new import_three3.Vector3(1, 0, 0), toRadians(rotation));
717
- break;
718
- case "y" /* Y */:
719
- obj.rotateOnAxis(new import_three3.Vector3(0, 1, 0), toRadians(rotation));
720
- break;
721
- case "z" /* Z */:
722
- obj.rotateOnAxis(new import_three3.Vector3(0, 0, 1), toRadians(rotation));
723
- break;
714
+ async function abortable(promise, signal) {
715
+ if (!signal) return promise;
716
+ let abort;
717
+ const cancelled = new Promise((_, reject) => {
718
+ abort = () => reject(signal.reason);
719
+ signal.addEventListener("abort", abort, { once: true });
720
+ if (signal.aborted) abort();
721
+ });
722
+ try {
723
+ return await Promise.race([promise, cancelled]);
724
+ } finally {
725
+ signal.removeEventListener("abort", abort);
724
726
  }
725
727
  }
726
- function addBox3WireframeToObject(box, obj, color = 16777215, w = 2) {
727
- let size = new import_three3.Vector3();
728
- box.getSize(size);
729
- let boxGeo = new import_three3.BoxGeometry(size.x, size.y, size.z, 1, 1, 1);
730
- let wireGeo = new import_three3.EdgesGeometry(boxGeo);
731
- let wireMat = new import_three3.LineBasicMaterial({ color, linewidth: w });
732
- let wireframe = new import_three3.LineSegments(wireGeo, wireMat);
733
- obj.add(wireframe);
734
- let axes = new import_three3.AxesHelper(1);
735
- obj.add(axes);
736
- }
737
- function addWireframeToObject(obj, color = 16777215, w = 2) {
738
- let boxGeo = new import_three3.BoxGeometry(16, 16, 16, 1, 1, 1);
739
- let wireGeo = new import_three3.EdgesGeometry(boxGeo);
740
- let wireMat = new import_three3.LineBasicMaterial({ color, linewidth: w });
741
- let wireframe = new import_three3.LineSegments(wireGeo, wireMat);
742
- obj.add(wireframe);
743
- let axes = new import_three3.AxesHelper(1);
744
- obj.add(axes);
745
- }
746
- function addWireframeToMesh(geo, mesh, color = 16777215, w = 2) {
747
- let wireGeo = new import_three3.EdgesGeometry(geo);
748
- let wireMat = new import_three3.LineBasicMaterial({ color, linewidth: w });
749
- let wireframe = new import_three3.LineSegments(wireGeo, wireMat);
750
- mesh.add(wireframe);
751
- let axes = new import_three3.AxesHelper(1);
752
- mesh.add(axes);
753
- }
754
-
755
- // src/util/performance.ts
756
- function captureException(e, ...extra) {
757
- console.error(e, extra);
758
- }
759
- function timingStart(marker) {
760
- console.time(marker);
761
- }
762
- function timingEnd(marker) {
763
- console.timeEnd(marker);
764
- }
765
-
766
- // src/util/three.ts
767
- function isObject3D(obj) {
768
- return obj.isObject3D;
769
- }
770
- function isMesh(obj) {
771
- return obj.isMesh;
772
- }
773
- function isInstancedMesh(obj) {
774
- return obj.isInstancedMesh;
775
- }
776
- function isPerspectiveCamera(obj) {
777
- return obj.isPerspectiveCamera;
778
- }
779
- function isOrthographicCamera(obj) {
780
- return obj.isOrthographicCamera;
781
- }
782
-
783
- // src/request/Requests.ts
784
- var p = prefix("Requests");
785
- if (typeof window === "undefined") {
786
- import_axios.default.defaults.headers["User-Agent"] = "MineRender";
787
- }
788
- var _Requests = class _Requests {
789
- static genericRequest(request) {
790
- return this.genericQueue.add(request).catch(async (e) => {
791
- console.debug(p, "generic catch", e.code, e);
792
- if (this.shouldRetry(e, request)) {
793
- await sleep(100);
794
- return this.genericRequest(request);
795
- }
796
- throw e;
797
- });
798
- }
799
- static mcAssetRequest(request) {
800
- return this.mcAssetRequestQueue.add(request).catch((e) => {
801
- console.debug(p, "mcAssetRequest catch", e.code, e);
802
- throw e;
803
- });
728
+ var RequestQueue = class {
729
+ constructor() {
730
+ this.pendingRequests = 0;
731
+ this.stopped = new AbortController();
732
+ this.queue = new import_jobqu.JobQueue(
733
+ (request) => fetchRequest(request, this.baseURL),
734
+ { interval: 10, maxPerRun: 1, maxActive: 8 }
735
+ );
804
736
  }
805
- static shouldRetry(e, request) {
806
- if ("code" in e) {
807
- if ("ECONNABORTED" === e.code) {
808
- if ("minerenderRetry" in request) {
809
- if (request["minerenderRetry"] > 0) {
810
- request["minerenderRetry"]--;
811
- return true;
737
+ async request(request) {
738
+ this.pendingRequests++;
739
+ const signal = request.signal;
740
+ try {
741
+ for (let retries = 0; ; retries++) {
742
+ signal?.throwIfAborted();
743
+ try {
744
+ return await abortable(this.queue.add(request), signal);
745
+ } catch (error) {
746
+ console.debug(p, "Request failed", error);
747
+ const delay = this.retryDelay(error, request, retries);
748
+ if (delay === void 0) {
749
+ throw error;
812
750
  }
813
- } else {
814
- request["minerenderRetry"] = 3;
815
- return true;
751
+ await this.waitForRetry(delay, signal);
816
752
  }
817
753
  }
754
+ } finally {
755
+ if (signal?.aborted) {
756
+ this.queue.remove(request);
757
+ }
758
+ this.pendingRequests--;
818
759
  }
819
- return false;
760
+ }
761
+ retryDelay(error, request, retries) {
762
+ if (this.stopped.signal.aborted || retries >= 3 || (request.method ?? "get").toLowerCase() !== "get" || request.signal?.aborted) {
763
+ return void 0;
764
+ }
765
+ if (error instanceof RequestError) {
766
+ const status = error.response?.status;
767
+ if (status !== void 0 && status !== 408 && status !== 429 && !(status >= 500 && status < 600)) return void 0;
768
+ } else if (!(error instanceof DOMException && error.name === "TimeoutError")) {
769
+ return void 0;
770
+ }
771
+ let delay = 100 * 2 ** retries;
772
+ const retryAfter = error instanceof RequestError ? error.response?.headers.get("Retry-After") : void 0;
773
+ if (retryAfter !== void 0 && retryAfter !== null) {
774
+ const seconds = Number(retryAfter);
775
+ if (!retryAfter.trim() || !Number.isFinite(seconds) || seconds < 0) {
776
+ return void 0;
777
+ }
778
+ delay = Math.max(delay, seconds * 1e3);
779
+ }
780
+ return delay;
781
+ }
782
+ async waitForRetry(delay, signal) {
783
+ let timer;
784
+ const waiting = new Promise((resolve) => {
785
+ timer = setTimeout(resolve, delay);
786
+ });
787
+ try {
788
+ await abortable(waiting, AbortSignal.any([this.stopped.signal, ...signal ? [signal] : []]));
789
+ } finally {
790
+ clearTimeout(timer);
791
+ }
792
+ }
793
+ get pendingSize() {
794
+ return this.pendingRequests;
795
+ }
796
+ end() {
797
+ this.queue.end();
798
+ this.stopped.abort(new import_jobqu.JobCancelledError("ended"));
799
+ }
800
+ };
801
+ var Requests = class {
802
+ static genericRequest(request) {
803
+ return this.genericQueue.request(request);
804
+ }
805
+ static mcAssetRequest(request) {
806
+ return this.mcAssetRequestQueue.request(request);
820
807
  }
821
808
  static setMcAssetRoot(root) {
822
- this.mcAssetInstance.defaults.baseURL = root;
809
+ this.mcAssetRequestQueue.baseURL = root;
823
810
  }
811
+ /** Counts unsettled calls, including retry delays and requests still running after shutdown. */
824
812
  static get queueSizes() {
825
813
  return {
826
- generic: this.genericQueue.size,
827
- mcAsset: this.mcAssetRequestQueue.size
814
+ generic: this.genericQueue.pendingSize,
815
+ mcAsset: this.mcAssetRequestQueue.pendingSize
828
816
  };
829
817
  }
830
818
  /**
831
- * Stops both queue timers. jobqu reschedules itself indefinitely, so a Node process will not
832
- * exit until this is called - see {@link shutdown}.
819
+ * Permanently stops both queues and rejects waiting, retrying, and future requests.
820
+ * Requests already running can finish. Idle queues hold no timer, so Node can exit without
821
+ * this cleanup. See {@link shutdown}.
833
822
  */
834
823
  static end() {
835
824
  this.genericQueue.end();
836
825
  this.mcAssetRequestQueue.end();
837
826
  }
838
827
  };
839
- _Requests.axiosInstance = import_axios.default.create({
840
- timeout: 5e3
841
- });
842
- _Requests.mcAssetInstance = import_axios.default.create({
843
- timeout: 5e3
844
- });
845
- _Requests.genericQueue = new import_jobqu.JobQueue((request) => _Requests.axiosInstance.request(request), import_time2.Time.millis(10), 1);
846
- _Requests.mcAssetRequestQueue = new import_jobqu.JobQueue((request) => _Requests.mcAssetInstance.request(request), import_time2.Time.millis(10), 1);
847
- var Requests = _Requests;
828
+ Requests.genericQueue = new RequestQueue();
829
+ Requests.mcAssetRequestQueue = new RequestQueue();
848
830
 
849
831
  // src/WrappedImage.ts
850
832
  var WrappedImage = class {
@@ -882,10 +864,10 @@ var WrappedImage = class {
882
864
  return this.animated ? this.width : this.height;
883
865
  }
884
866
  get frameCount() {
885
- return this.height / this.width;
867
+ return this.height / this.frameHeight;
886
868
  }
887
869
  getFrameY(frame) {
888
- return this.height / this.frameCount * Math.max(0, Math.min(this.frameCount, frame));
870
+ return this.frameHeight * Math.max(0, Math.min(this.frameCount - 1, frame));
889
871
  }
890
872
  getSectionData(sx, sy, sw, sh) {
891
873
  return this.dta.data.getImageData(sx, sy, sw, sh);
@@ -895,7 +877,7 @@ var WrappedImage = class {
895
877
  }
896
878
  getFrameSectionData(frame) {
897
879
  const y = this.getFrameY(frame);
898
- return this.getSectionData(0, y, this.width, this.width + y);
880
+ return this.getSectionData(0, y, this.frameWidth, this.frameHeight);
899
881
  }
900
882
  };
901
883
 
@@ -909,29 +891,41 @@ var ImageLoader = class _ImageLoader {
909
891
  static async loadAsync(src) {
910
892
  return new Promise((resolve, reject) => {
911
893
  const image = this._createImage();
912
- image.src = src;
913
894
  image.onload = () => resolve(image);
914
- image.onerror = (err) => reject(err);
895
+ image.onerror = (err) => reject(err instanceof Error ? err : new Error("Failed to decode image"));
896
+ image.src = src;
915
897
  });
916
898
  }
917
899
  static loadElement(src, onload, onerr) {
918
900
  const image = this._createImage();
919
- image.src = src;
920
901
  if (onload)
921
902
  image.onload = onload;
922
903
  if (onerr)
923
904
  image.onerror = onerr;
905
+ image.src = src;
924
906
  return image;
925
907
  }
926
908
  static async loadData(src) {
927
909
  console.debug(p2, "loadData", src);
928
- return await this.infoToData(await this.getInfo(src));
910
+ const image = await this.loadCanvasData(src);
911
+ return image.data.getImageData(0, 0, image.width, image.height);
929
912
  }
930
913
  static async loadCanvasData(src) {
931
- return await this.infoToCanvasData(await this.getInfo(src));
914
+ const keyStr = serializeImageKey({ src });
915
+ const info = this.getInfo(src);
916
+ const cached = Caching.rawImageCache.getIfPresent(keyStr);
917
+ try {
918
+ return await this.infoToCanvasData(await info);
919
+ } catch (err) {
920
+ if (cached && Caching.rawImageCache.getIfPresent(keyStr) === cached) {
921
+ Caching.rawImageCache.invalidate(keyStr);
922
+ }
923
+ throw err;
924
+ }
932
925
  }
933
926
  static async infoToCanvasData(info) {
934
- const image = await _ImageLoader.loadAsync(info.src);
927
+ const type = info.type === "jpg" ? "jpeg" : info.type ?? "png";
928
+ const image = await _ImageLoader.loadAsync(`data:image/${type};base64,${info.data.toString("base64")}`);
935
929
  const canvas = createCanvas(info.width, info.height);
936
930
  const context = canvas.getContext("2d");
937
931
  context.drawImage(image, 0, 0);
@@ -942,11 +936,8 @@ var ImageLoader = class _ImageLoader {
942
936
  };
943
937
  }
944
938
  static async infoToData(info) {
945
- const image = await _ImageLoader.loadAsync(info.src);
946
- const canvas = createCanvas(info.width, info.height);
947
- const context = canvas.getContext("2d");
948
- context.drawImage(image, 0, 0);
949
- return context.getImageData(0, 0, canvas.width, canvas.height);
939
+ const image = await this.infoToCanvasData(info);
940
+ return image.data.getImageData(0, 0, image.width, image.height);
950
941
  }
951
942
  static async getData(src) {
952
943
  const keyStr = serializeImageKey({ src });
@@ -961,38 +952,25 @@ var ImageLoader = class _ImageLoader {
961
952
  });
962
953
  }
963
954
  static async processResponse(response) {
964
- const src = response.config.url;
955
+ const src = response.url;
965
956
  const data = import_buffer.Buffer.from(response.data);
966
957
  const { width, height, type } = Env.provider.imageSize(data);
958
+ if (!width || !height) {
959
+ throw new Error("Invalid or unsupported image dimensions");
960
+ }
967
961
  return {
968
962
  src,
969
- width: width || 0,
970
- height: height || 0,
963
+ width,
964
+ height,
971
965
  type,
972
966
  data
973
967
  };
974
968
  }
975
969
  static async loadInfo(src) {
976
- if (src.startsWith("data:image/png;base64")) {
977
- return this.processResponse({
978
- config: {
979
- url: src
980
- },
981
- data: import_buffer.Buffer.from(src.substr("data:image/png;base64,".length), "base64")
982
- });
983
- }
984
970
  return Requests.genericRequest({
985
971
  url: src,
986
972
  responseType: "arraybuffer"
987
- }).then(this.processResponse).catch((err) => {
988
- return {
989
- src,
990
- width: 0,
991
- height: 0,
992
- type: void 0,
993
- data: import_buffer.Buffer.from([0])
994
- };
995
- });
973
+ }).then(this.processResponse);
996
974
  }
997
975
  static async getInfo(src) {
998
976
  const keyStr = serializeImageKey({ src });
@@ -1014,38 +992,50 @@ var ImageLoader = class _ImageLoader {
1014
992
 
1015
993
  // src/texture/TextureLoader.ts
1016
994
  var TextureLoader = class {
995
+ /** Reports whether image loading failed, so cached textures can be retried. */
996
+ static hasFailed(texture) {
997
+ return this.failedTextures.has(texture);
998
+ }
1017
999
  static createTexture() {
1018
- return new import_three4.Texture();
1000
+ return new import_three3.Texture();
1019
1001
  }
1020
- static loadInBackground(src, format = import_three4.RGBAFormat, rotation = 0) {
1002
+ static loadInBackground(src, format = import_three3.RGBAFormat, rotation = 0) {
1021
1003
  const texture = this.createTexture();
1022
- const image = ImageLoader.loadElement(src);
1023
- image.onload = function() {
1004
+ texture.colorSpace = THREE.SRGBColorSpace;
1005
+ const image = ImageLoader.loadElement(src, () => {
1024
1006
  texture.needsUpdate = true;
1025
- };
1007
+ }, (error) => {
1008
+ this.failedTextures.add(texture);
1009
+ console.warn("Failed to load texture", src, error);
1010
+ });
1026
1011
  texture.image = image;
1027
1012
  texture.format = format;
1028
1013
  texture.rotation = rotation;
1029
1014
  return Textures.initTextureProps(texture);
1030
1015
  }
1031
- static load(src, format = import_three4.RGBAFormat, rotation = 0) {
1032
- const texture = new import_three4.Texture();
1016
+ static load(src, format = import_three3.RGBAFormat, rotation = 0) {
1017
+ const texture = new import_three3.Texture();
1018
+ texture.colorSpace = THREE.SRGBColorSpace;
1033
1019
  ImageLoader.getData(src).then((image) => {
1034
- texture.needsUpdate = true;
1035
1020
  texture.image = image;
1021
+ texture.needsUpdate = true;
1022
+ }).catch((error) => {
1023
+ this.failedTextures.add(texture);
1024
+ console.warn("Failed to load texture", src, error);
1036
1025
  });
1037
1026
  texture.format = format;
1038
1027
  texture.rotation = rotation;
1039
1028
  return Textures.initTextureProps(texture);
1040
1029
  }
1041
1030
  };
1031
+ TextureLoader.failedTextures = /* @__PURE__ */ new WeakSet();
1042
1032
 
1043
1033
  // src/texture/Textures.ts
1044
- var THREE = __toESM(require("three"));
1034
+ var THREE2 = __toESM(require("three"));
1045
1035
  var Textures = class _Textures {
1046
1036
  static initTextureProps(texture) {
1047
- texture.magFilter = THREE.NearestFilter;
1048
- texture.minFilter = THREE.NearestFilter;
1037
+ texture.magFilter = THREE2.NearestFilter;
1038
+ texture.minFilter = THREE2.NearestFilter;
1049
1039
  texture.anisotropy = 0;
1050
1040
  return texture;
1051
1041
  }
@@ -1053,13 +1043,19 @@ var Textures = class _Textures {
1053
1043
  return TextureLoader.load(key.src, key.format, key.rotation);
1054
1044
  }
1055
1045
  static createAsset(key) {
1056
- return new import_three5.Texture();
1046
+ return new import_three4.Texture();
1057
1047
  }
1058
1048
  static createCanvasTexture(canvas) {
1059
- return this.initTextureProps(new import_three5.CanvasTexture(canvas));
1049
+ const texture = new import_three4.CanvasTexture(canvas);
1050
+ texture.colorSpace = THREE2.SRGBColorSpace;
1051
+ return this.initTextureProps(texture);
1060
1052
  }
1061
1053
  static getImage(key) {
1062
1054
  const keyStr = serializeTextureKey(key);
1055
+ const cached = Caching.textureCache.peek(keyStr);
1056
+ if (cached && TextureLoader.hasFailed(cached)) {
1057
+ Caching.textureCache.invalidate(keyStr);
1058
+ }
1063
1059
  return Caching.textureCache.get(keyStr, (k) => {
1064
1060
  return _Textures.createImage(key);
1065
1061
  });
@@ -1075,26 +1071,26 @@ var _Materials = class _Materials {
1075
1071
  }
1076
1072
  static createImage(key) {
1077
1073
  const transparent = key.transparent || false;
1078
- return new import_three6.MeshBasicMaterial({
1074
+ return new import_three5.MeshBasicMaterial({
1079
1075
  map: Textures.getImage(key.texture),
1080
1076
  transparent,
1081
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1077
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1082
1078
  alphaTest: 0.5
1083
1079
  });
1084
1080
  }
1085
1081
  static createBasicCanvasMaterial(canvas, transparent = false, shade = false) {
1086
1082
  if (shade) {
1087
- return new import_three6.MeshStandardMaterial({
1083
+ return new import_three5.MeshStandardMaterial({
1088
1084
  map: Textures.createCanvasTexture(canvas),
1089
1085
  transparent,
1090
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1086
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1091
1087
  alphaTest: 0.5
1092
1088
  });
1093
1089
  }
1094
- return new import_three6.MeshBasicMaterial({
1090
+ return new import_three5.MeshBasicMaterial({
1095
1091
  map: Textures.createCanvasTexture(canvas),
1096
1092
  transparent,
1097
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1093
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1098
1094
  alphaTest: 0.5
1099
1095
  });
1100
1096
  }
@@ -1103,6 +1099,7 @@ var _Materials = class _Materials {
1103
1099
  uniform bool SHADE;
1104
1100
 
1105
1101
  varying vec2 vUv;
1102
+ varying vec3 vTint;
1106
1103
  varying float light;
1107
1104
  varying float lift;
1108
1105
 
@@ -1115,7 +1112,11 @@ var _Materials = class _Materials {
1115
1112
 
1116
1113
  if (SHADE) {
1117
1114
 
1118
- vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );
1115
+ #ifdef USE_INSTANCING
1116
+ vec3 N = vec3( modelMatrix * instanceMatrix * vec4(normal, 0.0) );
1117
+ #else
1118
+ vec3 N = vec3( modelMatrix * vec4(normal, 0.0) );
1119
+ #endif
1119
1120
 
1120
1121
  float yLight = (1.0+N.y) * 0.5;
1121
1122
  light = yLight * (1.0-AMBIENT) + N.x*N.x * XFAC + N.z*N.z * ZFAC + AMBIENT;
@@ -1133,6 +1134,7 @@ var _Materials = class _Materials {
1133
1134
  }
1134
1135
 
1135
1136
  vUv = uv;
1137
+ vTint = color;
1136
1138
 
1137
1139
  #ifdef USE_INSTANCING
1138
1140
  gl_Position = projectionMatrix * viewMatrix * modelMatrix * instanceMatrix * vec4(position, 1.0);
@@ -1154,12 +1156,14 @@ var _Materials = class _Materials {
1154
1156
  uniform float BRIGHTNESS;
1155
1157
 
1156
1158
  varying vec2 vUv;
1159
+ varying vec3 vTint;
1157
1160
  varying float light;
1158
1161
  varying float lift;
1159
1162
 
1160
1163
  void main(void)
1161
1164
  {
1162
1165
  vec4 color = texture2D(map, vUv);
1166
+ color.rgb *= vTint;
1163
1167
 
1164
1168
  if (color.a < 0.01) discard;
1165
1169
 
@@ -1173,16 +1177,19 @@ var _Materials = class _Materials {
1173
1177
  gl_FragColor = vec4(lift + color.rgb * light2, 1.0);
1174
1178
 
1175
1179
  }
1180
+
1181
+ #include <tonemapping_fragment>
1182
+ #include <colorspace_fragment>
1176
1183
  }
1177
1184
  `;
1178
1185
  try {
1179
- return new import_three6.ShaderMaterial({
1186
+ return new import_three5.ShaderMaterial({
1180
1187
  uniforms: {
1181
1188
  SHADE: { value: true },
1182
1189
  BRIGHTNESS: { value: 1 },
1183
1190
  EMISSIVE: { value: false },
1184
1191
  base: {
1185
- value: new import_three6.Color(12698049)
1192
+ value: new import_three5.Color(12698049)
1186
1193
  /*TODO*/
1187
1194
  },
1188
1195
  map: { value: Textures.createCanvasTexture(canvas) }
@@ -1191,7 +1198,7 @@ var _Materials = class _Materials {
1191
1198
  fragmentShader: fragShader,
1192
1199
  vertexColors: true,
1193
1200
  transparent,
1194
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1201
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1195
1202
  alphaTest: 0.5
1196
1203
  });
1197
1204
  } catch (e) {
@@ -1201,6 +1208,10 @@ var _Materials = class _Materials {
1201
1208
  }
1202
1209
  static getImage(key) {
1203
1210
  const keyStr = serializeMaterialKey(key);
1211
+ const map = Caching.materialCache.peek(keyStr)?.map;
1212
+ if (map && TextureLoader.hasFailed(map)) {
1213
+ Caching.materialCache.invalidate(keyStr);
1214
+ }
1204
1215
  return Caching.materialCache.get(keyStr, (k) => {
1205
1216
  return _Materials.createImage(key);
1206
1217
  });
@@ -1225,10 +1236,10 @@ _Materials.MISSING_TEXTURE_SRC = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA
1225
1236
  var Materials = _Materials;
1226
1237
 
1227
1238
  // src/Meshes.ts
1228
- var import_three7 = require("three");
1239
+ var import_three6 = require("three");
1229
1240
  var Meshes = class _Meshes {
1230
1241
  static createBox(key) {
1231
- return new import_three7.Mesh(Geometries.getBox(key.geometry), Materials.getImage(key.material));
1242
+ return new import_three6.Mesh(Geometries.getBox(key.geometry), Materials.getImage(key.material));
1232
1243
  }
1233
1244
  static getBox(key) {
1234
1245
  const keyStr = serializeMeshKey(key);
@@ -1275,6 +1286,7 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1275
1286
  this.rootType = rootType;
1276
1287
  this.extension = extension;
1277
1288
  this.root = root;
1289
+ this.isAssetKey = true;
1278
1290
  }
1279
1291
  static parse(assetType, str, origin) {
1280
1292
  let namespace = origin?.namespace || DEFAULT_NAMESPACE;
@@ -1290,12 +1302,15 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1290
1302
  split.shift();
1291
1303
  }
1292
1304
  let path = split.join("/");
1293
- let extension = assetType === "textures" ? ".png" : origin?.assetType || ".json";
1305
+ const extension = assetType === "textures" ? ".png" : origin?.extension ?? ".json";
1306
+ if (extension && path.endsWith(extension)) {
1307
+ path = path.slice(0, -extension.length);
1308
+ }
1294
1309
  return new _AssetKey(namespace, path, assetType, type, "assets", extension, origin?.root);
1295
1310
  }
1296
1311
  toString() {
1297
1312
  let a = [
1298
- typeof this.root !== "undefined" || AssetLoader.ROOT !== DEFAULT_ROOT ? this.root ?? AssetLoader.ROOT : "__root__",
1313
+ this.root ?? AssetLoader.ROOT,
1299
1314
  this.rootType ?? "__rootType__",
1300
1315
  this.assetType ?? "__assetType__",
1301
1316
  this.type ?? "__type__",
@@ -1305,12 +1320,12 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1305
1320
  return a.join("/");
1306
1321
  }
1307
1322
  getFullPath() {
1308
- let p13 = [];
1323
+ let p12 = [];
1309
1324
  if (this.type) {
1310
- p13.push(this.type);
1325
+ p12.push(this.type);
1311
1326
  }
1312
- p13.push(this.path);
1313
- return p13.join("/");
1327
+ p12.push(this.path);
1328
+ return p12.join("/");
1314
1329
  }
1315
1330
  toNamespacedString() {
1316
1331
  return this.namespace + ":" + this.getFullPath();
@@ -1320,10 +1335,10 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1320
1335
  }
1321
1336
  };
1322
1337
  function isBasicAssetKey(obj) {
1323
- return "namespace" in obj && "path" in obj;
1338
+ return obj !== null && typeof obj === "object" && typeof obj.namespace === "string" && typeof obj.path === "string";
1324
1339
  }
1325
1340
  function isAssetKey(obj) {
1326
- return isBasicAssetKey(obj) && "parse" in obj;
1341
+ return isBasicAssetKey(obj) && obj.isAssetKey === true;
1327
1342
  }
1328
1343
 
1329
1344
  // src/model/ModelMerger.ts
@@ -1332,10 +1347,10 @@ var ModelMerger = class {
1332
1347
  const models = await this.collectAllParents(model);
1333
1348
  let merged = {};
1334
1349
  for (let parentModel of models) {
1335
- merged = (0, import_ts_deepmerge.default)(merged, parentModel);
1350
+ merged = import_ts_deepmerge.default.withOptions({ mergeArrays: false }, merged, parentModel);
1336
1351
  }
1337
- merged = (0, import_ts_deepmerge.default)(merged, model);
1338
- merged.hierarchy = models.map((m) => m.parent).filter((p13) => `${p13}`);
1352
+ merged = import_ts_deepmerge.default.withOptions({ mergeArrays: false }, merged, model);
1353
+ merged.hierarchy = models.map((m) => m.parent).filter((p12) => `${p12}`);
1339
1354
  merged.hierarchy.push(`${merged.parent}`);
1340
1355
  return merged;
1341
1356
  }
@@ -1345,6 +1360,7 @@ var ModelMerger = class {
1345
1360
  }
1346
1361
  const models = [];
1347
1362
  const parentKey = AssetKey.parse("models", model.parent);
1363
+ parentKey.root = model.key?.root;
1348
1364
  const parentModel = await Models.getRaw(parentKey);
1349
1365
  if (parentModel) {
1350
1366
  models.unshift(parentModel);
@@ -1354,9 +1370,6 @@ var ModelMerger = class {
1354
1370
  }
1355
1371
  };
1356
1372
 
1357
- // src/assets/Models.ts
1358
- var import_typescript_memoize = require("typescript-memoize");
1359
-
1360
1373
  // src/assets/source/parser/AssetParsers.ts
1361
1374
  var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1362
1375
  AssetParser2["MODEL"] = "model";
@@ -1370,30 +1383,65 @@ var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1370
1383
  })(AssetParser || {});
1371
1384
 
1372
1385
  // src/assets/Models.ts
1373
- var _Models = class _Models {
1386
+ var Models = class _Models {
1374
1387
  // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading
1375
1388
  // the library, and would require an EnvProvider before any entry has had a chance to register
1376
1389
  static get PERSISTENT_CACHE() {
1377
1390
  return this._persistentCache ?? (this._persistentCache = PersistentCache.open("minerender-models"));
1378
1391
  }
1379
1392
  static async getItemList() {
1380
- return AssetLoader.get(new AssetKey(
1381
- DEFAULT_NAMESPACE,
1382
- "_list",
1383
- "models",
1384
- "item",
1385
- "assets",
1386
- ".json",
1387
- DEFAULT_ROOT
1388
- ), "list" /* LIST */).then((r) => r?.files ?? []);
1393
+ const key = new AssetKey(DEFAULT_NAMESPACE, "_list", "items");
1394
+ const legacyKey = new AssetKey(DEFAULT_NAMESPACE, "_list", "models", "item");
1395
+ return Caching.listAssetCache.get(key.serialize(), async () => {
1396
+ return (await AssetLoader.getFirst([key, legacyKey], "list" /* LIST */))?.asset;
1397
+ }).then((r) => r?.files ?? []);
1389
1398
  }
1390
1399
  static async loadAndMerge(key) {
1391
- const model = await this.getRaw(key);
1400
+ const model = key.type === "item" ? await this.getItemModel(key) : await this.getRaw(key);
1392
1401
  if (!model) {
1393
1402
  return void 0;
1394
1403
  }
1395
1404
  return ModelMerger.mergeWithParents(model);
1396
1405
  }
1406
+ static async getItemModel(key) {
1407
+ const itemKey = new AssetKey(key.namespace, key.path, "items", void 0, key.rootType, ".json", key.root);
1408
+ const model = await this.PERSISTENT_CACHE.getOrLoad(itemKey.serialize(), async () => {
1409
+ const result = await AssetLoader.getFirst([itemKey, key], "json" /* JSON */);
1410
+ if (!result) return void 0;
1411
+ if (result.key.assetType !== "items") return { ...result.asset, key };
1412
+ const reference = this.defaultItemModel(result.asset.model, key);
1413
+ const modelKey = AssetKey.parse("models", reference);
1414
+ modelKey.root = key.root;
1415
+ const model2 = await this.getRaw(modelKey);
1416
+ if (!model2) throw new Error(`Item ${key.toNamespacedString()} references missing model ${reference}`);
1417
+ return model2;
1418
+ });
1419
+ return model ? { ...model, key: Object.assign(new AssetKey("", ""), model.key) } : void 0;
1420
+ }
1421
+ // Item previews use the GUI context, false conditions, and zero numeric properties.
1422
+ static defaultItemModel(node, key) {
1423
+ if (!node || typeof node.type !== "string") {
1424
+ throw new Error(`Unsupported item model definition for ${key.toNamespacedString()}`);
1425
+ }
1426
+ switch (node.type.replace(/^minecraft:/, "")) {
1427
+ case "model":
1428
+ if (typeof node.model === "string" && node.model) return node.model;
1429
+ break;
1430
+ case "condition":
1431
+ return this.defaultItemModel(node.on_false, key);
1432
+ case "select": {
1433
+ 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;
1434
+ return this.defaultItemModel(selected ?? node.fallback, key);
1435
+ }
1436
+ case "range_dispatch": {
1437
+ const selected = node.entries?.reduce((match, entry) => {
1438
+ return entry.threshold <= 0 && (!match || entry.threshold >= match.threshold) ? entry : match;
1439
+ }, void 0);
1440
+ return this.defaultItemModel(selected?.model ?? node.fallback, key);
1441
+ }
1442
+ }
1443
+ throw new Error(`Unsupported item model ${node?.type ?? "definition"} for ${key.toNamespacedString()}`);
1444
+ }
1397
1445
  static async getRaw(key) {
1398
1446
  if (!key.assetType) {
1399
1447
  key.assetType = "models";
@@ -1432,19 +1480,15 @@ var _Models = class _Models {
1432
1480
  return this.PERSISTENT_CACHE.clear();
1433
1481
  }
1434
1482
  };
1435
- __decorateClass([
1436
- (0, import_typescript_memoize.Memoize)()
1437
- ], _Models, "getItemList", 1);
1438
- var Models = _Models;
1439
1483
 
1440
1484
  // src/assets/BlockStates.ts
1441
- var import_typescript_memoize2 = require("typescript-memoize");
1442
1485
  var BlockStates = class {
1443
1486
  static get PERSISTENT_CACHE() {
1444
1487
  return this._persistentCache ?? (this._persistentCache = PersistentCache.open("minerender-blockstates"));
1445
1488
  }
1489
+ // BlockState names are hardcoded
1446
1490
  static async getList() {
1447
- return AssetLoader.get(new AssetKey(
1491
+ const key = new AssetKey(
1448
1492
  DEFAULT_NAMESPACE,
1449
1493
  "_list",
1450
1494
  "blockstates",
@@ -1452,11 +1496,16 @@ var BlockStates = class {
1452
1496
  "assets",
1453
1497
  ".json",
1454
1498
  DEFAULT_ROOT
1455
- ), "list" /* LIST */).then((r) => r?.files ?? []);
1499
+ );
1500
+ return Caching.listAssetCache.get(key.serialize(), () => {
1501
+ return AssetLoader.get(key, "list" /* LIST */);
1502
+ }).then((r) => r?.files ?? []);
1456
1503
  }
1457
1504
  static async getDefaultStates() {
1458
1505
  const key = AssetKey.parse("blockstates", "minerender:defaultBlockStates");
1459
- return AssetLoader.get(key, "json" /* JSON */);
1506
+ return Caching.defaultBlockStatesCache.get(key.serialize(), () => {
1507
+ return AssetLoader.get(key, "json" /* JSON */);
1508
+ });
1460
1509
  }
1461
1510
  static async getDefaultState(key) {
1462
1511
  const defaultStates = await this.getDefaultStates();
@@ -1495,17 +1544,11 @@ var BlockStates = class {
1495
1544
  await this.PERSISTENT_CACHE.clear();
1496
1545
  }
1497
1546
  };
1498
- __decorateClass([
1499
- (0, import_typescript_memoize2.Memoize)()
1500
- ], BlockStates, "getList", 1);
1501
- __decorateClass([
1502
- (0, import_typescript_memoize2.Memoize)()
1503
- ], BlockStates, "getDefaultStates", 1);
1504
1547
  var DefaultBlockStates = class {
1505
1548
  };
1506
1549
 
1507
1550
  // src/assets/Assets.ts
1508
- var DEFAULT_ROOT = "https://assets.mcasset.cloud/1.17.1";
1551
+ var DEFAULT_ROOT = "https://assets.mcasset.cloud/1.21.11";
1509
1552
  var DEFAULT_NAMESPACE = "minecraft";
1510
1553
  var Assets = class {
1511
1554
  /**
@@ -1527,82 +1570,213 @@ var AssetSource = class {
1527
1570
  constructor() {
1528
1571
  }
1529
1572
  };
1530
-
1531
- // src/nbt/NBTHelper.ts
1532
- var NBTHelper = class {
1533
- static async fromBuffer(buffer) {
1534
- const prismarineNbt = await import("prismarine-nbt");
1535
- const { parsed, type, metadata } = await prismarineNbt.parse(buffer);
1536
- return parsed;
1573
+ var AssetLoadError = class extends Error {
1574
+ constructor(source, key, path, cause) {
1575
+ super(`Failed to load ${key.toNamespacedString()} from ${path}${cause instanceof Error ? `: ${cause.message}` : ""}`);
1576
+ this.source = source;
1577
+ this.key = key;
1578
+ this.path = path;
1579
+ this.cause = cause;
1580
+ this.name = "AssetLoadError";
1537
1581
  }
1538
1582
  };
1539
1583
 
1540
- // src/assets/source/HostedAssetSource.ts
1541
- var import_ts_deepmerge2 = __toESM(require_dist());
1542
- var p3 = prefix("HostedAssetSource");
1543
- var DEFAULT_OPTIONS = {
1544
- retryDefaults: true
1545
- };
1546
- var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1547
- async loadOrRetryWithDefaults(key, parser) {
1548
- const direct = await this.load(key, parser);
1549
- if (typeof direct !== "undefined") {
1550
- return direct;
1551
- }
1552
- if (key.namespace !== DEFAULT_NAMESPACE) {
1553
- console.info(p3, "Retrying", key, "with default namespace");
1554
- const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);
1555
- const namespaced = await this.load(namespaceKey, parser);
1556
- if (typeof namespaced !== "undefined") {
1557
- return namespaced;
1558
- }
1559
- if (typeof key.root !== "undefined" && key.root !== DEFAULT_ROOT || typeof this.root !== "undefined" && this.root !== DEFAULT_ROOT) {
1560
- console.info(p3, "Retrying", key, "with default root+namespace");
1561
- const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, DEFAULT_ROOT);
1562
- const namespacedRooted = await this.load(namespacedRootedKey, parser);
1563
- if (typeof namespacedRooted !== "undefined") {
1564
- return namespacedRooted;
1565
- }
1566
- }
1567
- } else if (typeof key.root !== "undefined" && key.root !== DEFAULT_ROOT || typeof this.root !== "undefined" && this.root !== DEFAULT_ROOT) {
1568
- console.info(p3, "Retrying", key, "with default root");
1569
- const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, DEFAULT_ROOT);
1570
- const rooted = await this.load(rootKey, parser);
1571
- if (typeof rooted !== "undefined") {
1572
- return rooted;
1573
- }
1574
- }
1575
- return void 0;
1584
+ // src/util/BatchedExecutor.ts
1585
+ var BatchedExecutor = class {
1586
+ constructor(interval = 1, batch = 30) {
1587
+ this.interval = interval;
1588
+ this.batch = batch;
1589
+ this.queue = [];
1590
+ this.task = setInterval(() => this.run());
1576
1591
  }
1577
- async load(key, parser) {
1592
+ submit(task) {
1593
+ this.queue.push(task);
1594
+ }
1595
+ run() {
1596
+ for (let i = 0; i < this.batch; i++) {
1597
+ this.runNext();
1598
+ }
1599
+ }
1600
+ runNext() {
1601
+ let next = this.queue.shift();
1602
+ if (next) next();
1603
+ }
1604
+ };
1605
+
1606
+ // src/util/model.ts
1607
+ var import_three7 = require("three");
1608
+ function applyElementRotation(rotation, geometry) {
1609
+ const origin = new import_three7.Vector3(rotation.origin[0], rotation.origin[1], rotation.origin[2]);
1610
+ geometry.translate(-origin.x, -origin.y, -origin.z);
1611
+ switch (rotation.axis) {
1612
+ case "x" /* X */:
1613
+ geometry.rotateX(toRadians(rotation.angle));
1614
+ break;
1615
+ case "y" /* Y */:
1616
+ geometry.rotateY(toRadians(rotation.angle));
1617
+ break;
1618
+ case "z" /* Z */:
1619
+ geometry.rotateZ(toRadians(rotation.angle));
1620
+ break;
1621
+ }
1622
+ if (rotation.rescale) {
1623
+ if (Math.abs(rotation.angle) === 22.5) {
1624
+ const s = 1 / Math.cos(0.39269909262657166);
1625
+ geometry.scale(s, 1, s);
1626
+ } else {
1627
+ const s = 1 / Math.cos(0.7853981852531433);
1628
+ geometry.scale(s, 1, s);
1629
+ }
1630
+ }
1631
+ geometry.translate(origin.x, origin.y, origin.z);
1632
+ }
1633
+ function applyModelPartRotation(modelPart, geometry) {
1634
+ const origin = new import_three7.Vector3(modelPart.pivotX, modelPart.pivotY, modelPart.pivotZ);
1635
+ geometry.translate(-origin.x, -origin.y, -origin.z);
1636
+ geometry.rotateX(toRadians(modelPart.pitch));
1637
+ geometry.rotateY(toRadians(modelPart.yaw));
1638
+ geometry.rotateZ(toRadians(modelPart.roll));
1639
+ geometry.translate(origin.x, origin.y, origin.z);
1640
+ }
1641
+ function applyGenericRotation(axis, rotation, obj) {
1642
+ switch (axis) {
1643
+ case "x" /* X */:
1644
+ obj.rotateOnAxis(new import_three7.Vector3(1, 0, 0), toRadians(rotation));
1645
+ break;
1646
+ case "y" /* Y */:
1647
+ obj.rotateOnAxis(new import_three7.Vector3(0, 1, 0), toRadians(rotation));
1648
+ break;
1649
+ case "z" /* Z */:
1650
+ obj.rotateOnAxis(new import_three7.Vector3(0, 0, 1), toRadians(rotation));
1651
+ break;
1652
+ }
1653
+ }
1654
+ function addBox3WireframeToObject(box, obj, color = 16777215, w = 2) {
1655
+ let size = new import_three7.Vector3();
1656
+ box.getSize(size);
1657
+ let boxGeo = new import_three7.BoxGeometry(size.x, size.y, size.z, 1, 1, 1);
1658
+ let wireGeo = new import_three7.EdgesGeometry(boxGeo);
1659
+ let wireMat = new import_three7.LineBasicMaterial({ color, linewidth: w });
1660
+ let wireframe = new import_three7.LineSegments(wireGeo, wireMat);
1661
+ obj.add(wireframe);
1662
+ let axes = new import_three7.AxesHelper(1);
1663
+ obj.add(axes);
1664
+ }
1665
+ function addWireframeToObject(obj, color = 16777215, w = 2) {
1666
+ let boxGeo = new import_three7.BoxGeometry(16, 16, 16, 1, 1, 1);
1667
+ let wireGeo = new import_three7.EdgesGeometry(boxGeo);
1668
+ let wireMat = new import_three7.LineBasicMaterial({ color, linewidth: w });
1669
+ let wireframe = new import_three7.LineSegments(wireGeo, wireMat);
1670
+ obj.add(wireframe);
1671
+ let axes = new import_three7.AxesHelper(1);
1672
+ obj.add(axes);
1673
+ }
1674
+ function addWireframeToMesh(geo, mesh, color = 16777215, w = 2) {
1675
+ let wireGeo = new import_three7.EdgesGeometry(geo);
1676
+ let wireMat = new import_three7.LineBasicMaterial({ color, linewidth: w });
1677
+ let wireframe = new import_three7.LineSegments(wireGeo, wireMat);
1678
+ mesh.add(wireframe);
1679
+ let axes = new import_three7.AxesHelper(1);
1680
+ mesh.add(axes);
1681
+ }
1682
+
1683
+ // src/util/performance.ts
1684
+ function captureException(e, ...extra) {
1685
+ console.error(e, extra);
1686
+ }
1687
+ function timingStart(marker) {
1688
+ console.time(marker);
1689
+ }
1690
+ function timingEnd(marker) {
1691
+ console.timeEnd(marker);
1692
+ }
1693
+
1694
+ // src/util/three.ts
1695
+ function isObject3D(obj) {
1696
+ return obj.isObject3D;
1697
+ }
1698
+ function isMesh(obj) {
1699
+ return obj.isMesh;
1700
+ }
1701
+ function isInstancedMesh(obj) {
1702
+ return obj.isInstancedMesh;
1703
+ }
1704
+ function isPerspectiveCamera(obj) {
1705
+ return obj.isPerspectiveCamera;
1706
+ }
1707
+ function isOrthographicCamera(obj) {
1708
+ return obj.isOrthographicCamera;
1709
+ }
1710
+
1711
+ // src/nbt/NBTHelper.ts
1712
+ var NBTHelper = class {
1713
+ static async fromBuffer(buffer) {
1714
+ const prismarineNbt = await import("prismarine-nbt");
1715
+ const { parsed, type, metadata } = await prismarineNbt.parse(buffer);
1716
+ return parsed;
1717
+ }
1718
+ };
1719
+
1720
+ // src/assets/source/HostedAssetSource.ts
1721
+ var import_ts_deepmerge2 = __toESM(require_dist());
1722
+ var p3 = prefix("HostedAssetSource");
1723
+ var DEFAULT_OPTIONS = {
1724
+ retryDefaults: true
1725
+ };
1726
+ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1727
+ async loadOrRetryWithDefaults(key, parser) {
1728
+ const direct = await this.load(key, parser);
1729
+ if (typeof direct !== "undefined") {
1730
+ return direct;
1731
+ }
1732
+ if (key.namespace !== DEFAULT_NAMESPACE) {
1733
+ console.info(p3, "Retrying", key, "with default namespace");
1734
+ const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);
1735
+ const namespaced = await this.load(namespaceKey, parser);
1736
+ if (typeof namespaced !== "undefined") {
1737
+ return namespaced;
1738
+ }
1739
+ if (typeof key.root !== "undefined" && key.root !== DEFAULT_ROOT || typeof this.root !== "undefined" && this.root !== DEFAULT_ROOT) {
1740
+ console.info(p3, "Retrying", key, "with default root+namespace");
1741
+ const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, DEFAULT_ROOT);
1742
+ const namespacedRooted = await this.load(namespacedRootedKey, parser);
1743
+ if (typeof namespacedRooted !== "undefined") {
1744
+ return namespacedRooted;
1745
+ }
1746
+ }
1747
+ } else if (typeof key.root !== "undefined" && key.root !== DEFAULT_ROOT || typeof this.root !== "undefined" && this.root !== DEFAULT_ROOT) {
1748
+ console.info(p3, "Retrying", key, "with default root");
1749
+ const rootKey = new AssetKey(key.namespace, key.path, key.assetType, key.type, key.rootType, key.extension, DEFAULT_ROOT);
1750
+ const rooted = await this.load(rootKey, parser);
1751
+ if (typeof rooted !== "undefined") {
1752
+ return rooted;
1753
+ }
1754
+ }
1755
+ return void 0;
1756
+ }
1757
+ async load(key, parser) {
1578
1758
  console.info(p3, "Loading", key);
1579
1759
  const url = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1580
1760
  console.debug(p3, url);
1581
- let req = {
1582
- url
1583
- };
1584
- parser.config(req);
1585
- return await Requests.mcAssetRequest(req).then((response) => {
1586
- if (response && response.data) {
1587
- try {
1588
- return parser.parse(response);
1589
- } catch (e) {
1590
- console.warn("Parser failed to process response", response, e);
1591
- throw e;
1592
- }
1593
- }
1594
- return void 0;
1595
- }).catch((err) => {
1596
- if (err.response) {
1597
- let response = err.response;
1598
- if (response.status === 404) {
1599
- console.debug(p3, key, "not found");
1761
+ const request = { url };
1762
+ try {
1763
+ parser.config(request);
1764
+ let response;
1765
+ try {
1766
+ response = await Requests.mcAssetRequest(request);
1767
+ } catch (cause) {
1768
+ if (cause instanceof RequestError && cause.response?.status === 404) {
1600
1769
  return void 0;
1601
1770
  }
1771
+ throw cause;
1602
1772
  }
1603
- console.debug(p3, "Failed to load", key, err?.message);
1604
- return void 0;
1605
- });
1773
+ if (response.data === void 0) {
1774
+ throw new Error("Asset response has no data");
1775
+ }
1776
+ return await parser.parse(response);
1777
+ } catch (cause) {
1778
+ throw new AssetLoadError(this, key, request.url, cause);
1779
+ }
1606
1780
  }
1607
1781
  assetBasePath(key) {
1608
1782
  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 + "/" : ""}`;
@@ -1709,7 +1883,6 @@ var BrowserArchiveProxy = class {
1709
1883
  };
1710
1884
 
1711
1885
  // src/assets/source/archive/ArchiveAssetSource.ts
1712
- var p4 = prefix("ArchiveAssetSource");
1713
1886
  var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1714
1887
  constructor(archiveProxy) {
1715
1888
  super();
@@ -1728,74 +1901,31 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1728
1901
  }
1729
1902
  async get(key, parser) {
1730
1903
  const responseParser = HostedAssetSource.PARSER_MAP.get(parser);
1731
- console.log("ArchiveAssetSource.get", key, parser);
1732
- let entries = await this.getEntries();
1733
- const path = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1734
- console.log(path);
1735
- const entry = await this.getEntry(path);
1736
- console.log(entry);
1737
- if (!entry) {
1738
- return void 0;
1739
- }
1740
- let blob = await entry.getData();
1741
- const url = URL.createObjectURL(blob);
1742
- console.log(url);
1743
- let req = {
1744
- url
1745
- };
1746
- responseParser.config(req);
1747
- return Requests.genericRequest(req).then((response) => {
1748
- if (response && response.data) {
1749
- try {
1750
- return responseParser.parse(response);
1751
- } catch (e) {
1752
- console.warn("Parser failed to process response", response, e);
1753
- throw e;
1754
- }
1755
- }
1756
- return void 0;
1757
- }).catch((err) => {
1758
- if (err.response) {
1759
- let response = err.response;
1760
- if (response.status === 404) {
1761
- console.debug(p4, key, "not found");
1762
- return void 0;
1763
- }
1764
- }
1765
- console.debug(p4, "Failed to load", key, err?.message);
1766
- return void 0;
1767
- });
1904
+ return this.load(key, responseParser);
1768
1905
  }
1769
- //TODO: abstract this
1770
1906
  async load(key, parser) {
1771
- console.info(p4, "Loading", key);
1772
- const url = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1773
- console.debug(p4, url);
1774
- let req = {
1775
- url
1776
- };
1777
- parser.config(req);
1778
- return await Requests.genericRequest(req).then((response) => {
1779
- if (response && response.data) {
1780
- try {
1781
- return parser.parse(response);
1782
- } catch (e) {
1783
- console.warn("Parser failed to process response", response, e);
1784
- throw e;
1785
- }
1907
+ const path = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1908
+ let url;
1909
+ try {
1910
+ const entry = await this.getEntry(path);
1911
+ if (!entry) {
1912
+ return void 0;
1786
1913
  }
1787
- return void 0;
1788
- }).catch((err) => {
1789
- if (err.response) {
1790
- let response = err.response;
1791
- if (response.status === 404) {
1792
- console.debug(p4, key, "not found");
1793
- return void 0;
1794
- }
1914
+ url = URL.createObjectURL(await entry.getData());
1915
+ const request = { url };
1916
+ parser.config(request);
1917
+ const response = await Requests.genericRequest(request);
1918
+ if (response.data === void 0) {
1919
+ throw new Error("Asset response has no data");
1795
1920
  }
1796
- console.debug(p4, "Failed to load", key, err?.message);
1797
- return void 0;
1798
- });
1921
+ return await parser.parse(response);
1922
+ } catch (cause) {
1923
+ throw new AssetLoadError(this, key, path, cause);
1924
+ } finally {
1925
+ if (url !== void 0) {
1926
+ URL.revokeObjectURL(url);
1927
+ }
1928
+ }
1799
1929
  }
1800
1930
  assetBasePath(key) {
1801
1931
  return `${key.rootType !== void 0 ? key.rootType + "/" : ""}${key.namespace !== void 0 ? key.namespace + "/" : ""}${key.assetType !== void 0 ? key.assetType + "/" : ""}`;
@@ -1803,18 +1933,17 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1803
1933
  };
1804
1934
 
1805
1935
  // src/assets/AssetLoader.ts
1806
- var import_ts_deepmerge3 = __toESM(require_dist());
1807
- var p5 = prefix("AssetLoader");
1936
+ var p4 = prefix("AssetLoader");
1808
1937
  var _AssetLoader = class _AssetLoader {
1809
1938
  static addSource(key, source, override = true) {
1810
1939
  if (override) {
1811
1940
  const existing = this.removeSource(key);
1812
1941
  if (existing) {
1813
- console.log(p5, "Removed existing AssetSource", key);
1942
+ console.log(p4, "Removed existing AssetSource", key);
1814
1943
  }
1815
1944
  }
1816
1945
  this._SOURCES.unshift({ key, source });
1817
- console.log(p5, "Added AssetSource", key);
1946
+ console.log(p4, "Added AssetSource", key);
1818
1947
  }
1819
1948
  static removeSource(key) {
1820
1949
  const index = this._SOURCES.findIndex((s) => s.key === key);
@@ -1827,7 +1956,6 @@ var _AssetLoader = class _AssetLoader {
1827
1956
  return void 0;
1828
1957
  }
1829
1958
  static async getAll(key, parser) {
1830
- console.log(this._SOURCES);
1831
1959
  let promises = [];
1832
1960
  for (const source of this._SOURCES) {
1833
1961
  promises.push(source.source.get(key, parser));
@@ -1836,24 +1964,34 @@ var _AssetLoader = class _AssetLoader {
1836
1964
  return results.filter((r) => r != void 0);
1837
1965
  });
1838
1966
  }
1967
+ /** Returns the first defined result in source-priority order, without merging assets. */
1839
1968
  static async get(key, parser) {
1840
- console.log(this._SOURCES);
1841
- let promises = [];
1842
- for (const source of this._SOURCES) {
1843
- promises.push(source.source.get(key, parser));
1844
- }
1845
- return Promise.all(promises).then((results) => {
1846
- const fallback = results[results.length - 1];
1847
- for (const result of results) {
1848
- if (result) {
1849
- if (fallback) {
1850
- return (0, import_ts_deepmerge3.default)({}, fallback, result);
1851
- }
1852
- return result;
1969
+ const keys = [key];
1970
+ if (key.rootType === "data" && (key.assetType === "structure" || key.assetType === "structures")) {
1971
+ keys.push(new AssetKey(
1972
+ key.namespace,
1973
+ key.path,
1974
+ key.assetType === "structure" ? "structures" : "structure",
1975
+ key.type,
1976
+ key.rootType,
1977
+ key.extension,
1978
+ key.root
1979
+ ));
1980
+ }
1981
+ return (await this.getFirst(keys, parser))?.asset;
1982
+ }
1983
+ /** Tries each path within a source before considering lower-priority sources. */
1984
+ static async getFirst(keys, parser) {
1985
+ const sources = [...this._SOURCES];
1986
+ for (const source of sources) {
1987
+ for (const key of keys) {
1988
+ const result = await source.source.get(key, parser);
1989
+ if (result !== void 0) {
1990
+ return { key, asset: result };
1853
1991
  }
1854
1992
  }
1855
- return void 0;
1856
- });
1993
+ }
1994
+ return void 0;
1857
1995
  }
1858
1996
  };
1859
1997
  _AssetLoader.ROOT = DEFAULT_ROOT;
@@ -1868,11 +2006,21 @@ var ModelTextures = class {
1868
2006
  return this._persistentMetaCache ?? (this._persistentMetaCache = PersistentCache.open("minerender-texturemeta"));
1869
2007
  }
1870
2008
  static async get(key) {
1871
- const asset = await this.preload(key);
1872
- if (asset) {
1873
- return ImageLoader.infoToCanvasData(asset);
2009
+ const keyStr = key.serialize();
2010
+ const pending = this.preload(key);
2011
+ const cached = Caching.textureAssetCache.getIfPresent(keyStr);
2012
+ try {
2013
+ const asset = await pending;
2014
+ if (asset) {
2015
+ return await ImageLoader.infoToCanvasData(asset);
2016
+ }
2017
+ return void 0;
2018
+ } catch (err) {
2019
+ if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {
2020
+ Caching.textureAssetCache.invalidate(keyStr);
2021
+ }
2022
+ throw err;
1874
2023
  }
1875
- return void 0;
1876
2024
  }
1877
2025
  static async preload(key) {
1878
2026
  const keyStr = key.serialize();
@@ -2042,17 +2190,20 @@ var TextureAtlas = class {
2042
2190
  // src/model/ModelGenerator.ts
2043
2191
  var ModelGenerator = class {
2044
2192
  static generateItemModel(imageData, layer) {
2193
+ const tintindex = this.ITEM_LAYERS.indexOf(layer);
2045
2194
  const mainElement = {
2046
2195
  from: [0, 0, 7.5],
2047
2196
  to: [16, 16, 8.5],
2048
2197
  faces: {
2049
2198
  "south": {
2050
2199
  uv: [0, 0, 16, 16],
2051
- texture: `#${layer}`
2200
+ texture: `#${layer}`,
2201
+ tintindex
2052
2202
  },
2053
2203
  "north": {
2054
2204
  uv: [16, 0, 0, 16],
2055
- texture: `#${layer}`
2205
+ texture: `#${layer}`,
2206
+ tintindex
2056
2207
  }
2057
2208
  },
2058
2209
  shade: true
@@ -2063,11 +2214,19 @@ var ModelGenerator = class {
2063
2214
  ModelGenerator.ITEM_LAYERS = ["layer0", "layer1", "layer2", "layer3", "layer4"];
2064
2215
 
2065
2216
  // src/UVMapper.ts
2066
- var p6 = prefix("UVMapper");
2217
+ var p5 = prefix("UVMapper");
2067
2218
  var DEFAULT_UV = [0, 0, 16, 16];
2068
2219
  var X = 0;
2069
2220
  var Y = 1;
2070
2221
  var Z = 2;
2222
+ var FACE_UV_AXES = {
2223
+ east: [new import_three8.Vector3(0, 0, -1), new import_three8.Vector3(0, -1, 0)],
2224
+ west: [new import_three8.Vector3(0, 0, 1), new import_three8.Vector3(0, -1, 0)],
2225
+ up: [new import_three8.Vector3(1, 0, 0), new import_three8.Vector3(0, 0, 1)],
2226
+ down: [new import_three8.Vector3(1, 0, 0), new import_three8.Vector3(0, 0, -1)],
2227
+ south: [new import_three8.Vector3(1, 0, 0), new import_three8.Vector3(0, -1, 0)],
2228
+ north: [new import_three8.Vector3(-1, 0, 0), new import_three8.Vector3(0, -1, 0)]
2229
+ };
2071
2230
  var UVMapper = class {
2072
2231
  static makeUv(uvCoord, originalTextureSize, actualTextureSize) {
2073
2232
  if (uvCoord === 0) return 0;
@@ -2165,6 +2324,42 @@ var UVMapper = class {
2165
2324
  static facesToUv(faces, originalTextureSize, actualTextureSize) {
2166
2325
  return new import_three8.Float32BufferAttribute(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);
2167
2326
  }
2327
+ static lockUvs(geometry, faces, atlas, rotation) {
2328
+ const uv = geometry.getAttribute("uv");
2329
+ for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {
2330
+ const faceName = CUBE_FACES[faceIndex];
2331
+ const texture = faces[faceName]?.texture?.substring(1);
2332
+ const position = texture && atlas.positions[texture];
2333
+ const size = texture && atlas.sizes[texture];
2334
+ if (!position || !size) continue;
2335
+ const [sourceU, sourceV] = FACE_UV_AXES[faceName];
2336
+ const uAxis = sourceU.clone().applyEuler(rotation);
2337
+ const vAxis = sourceV.clone().applyEuler(rotation);
2338
+ const normal = vAxis.clone().cross(uAxis);
2339
+ const targetFace = CUBE_FACES.find((name) => {
2340
+ const [u, v] = FACE_UV_AXES[name];
2341
+ return v.clone().cross(u).dot(normal) > 0.5;
2342
+ });
2343
+ const [targetU, targetV] = FACE_UV_AXES[targetFace];
2344
+ const uu = Math.round(targetU.dot(uAxis));
2345
+ const uvCross = Math.round(targetU.dot(vAxis));
2346
+ const vu = Math.round(targetV.dot(uAxis));
2347
+ const vv = Math.round(targetV.dot(vAxis));
2348
+ for (let corner = 0; corner < 4; corner++) {
2349
+ const index = faceIndex * 4 + corner;
2350
+ const u = (uv.getX(index) * atlas.image.width - position[0]) / size[0] - 0.5;
2351
+ const v = ((1 - uv.getY(index)) * atlas.image.height - position[1]) / size[1] - 0.5;
2352
+ const lockedU = uu * u + uvCross * v + 0.5;
2353
+ const lockedV = vu * u + vv * v + 0.5;
2354
+ uv.setXY(
2355
+ index,
2356
+ (position[0] + lockedU * size[0]) / atlas.image.width,
2357
+ 1 - (position[1] + lockedV * size[1]) / atlas.image.height
2358
+ );
2359
+ }
2360
+ }
2361
+ uv.needsUpdate = true;
2362
+ }
2168
2363
  static async getAtlas(model) {
2169
2364
  const keyStr = model.key.serialize();
2170
2365
  return Caching.modelTextureAtlasCache.get(keyStr, (k) => {
@@ -2240,7 +2435,7 @@ var UVMapper = class {
2240
2435
  const metaMap = {};
2241
2436
  const model = { ...originalModel };
2242
2437
  const isItemModel = !("elements" in model);
2243
- console.debug(p6, "Creating Atlas for", model.key);
2438
+ console.debug(p5, "Creating Atlas for", model.key);
2244
2439
  if (model.textures) {
2245
2440
  const promises = [];
2246
2441
  const uniqueTextureNames = [];
@@ -2254,7 +2449,7 @@ var UVMapper = class {
2254
2449
  const assetKey = AssetKey.parse("textures", textureValue, model.key);
2255
2450
  promises.push(ModelTextures.get(assetKey).then((asset) => {
2256
2451
  if (!asset) {
2257
- console.warn(p6, "Missing texture", assetKey);
2452
+ console.warn(p5, "Missing texture", assetKey);
2258
2453
  return;
2259
2454
  }
2260
2455
  textureMap[textureKey] = new WrappedImage(asset);
@@ -2266,7 +2461,7 @@ var UVMapper = class {
2266
2461
  }
2267
2462
  await Promise.all(promises);
2268
2463
  const textureCount = uniqueTextureNames.length;
2269
- console.debug(p6, "Creating Atlas for", textureCount, "textures");
2464
+ console.debug(p5, "Creating Atlas for", textureCount, "textures");
2270
2465
  this.fillMissingTextureKeys(model.textures, textureMap);
2271
2466
  this.fillMissingTextureKeys(model.textures, metaMap);
2272
2467
  const sizes = {};
@@ -2286,7 +2481,7 @@ var UVMapper = class {
2286
2481
  this.fillMissingTextureKeys(model.textures, sizes);
2287
2482
  const s = Math.ceil(Math.sqrt(textureCount + 1));
2288
2483
  const size = Math.ceil(s * maxWidth);
2289
- console.debug(p6, "Atlas size:", size);
2484
+ console.debug(p5, "Atlas size:", size);
2290
2485
  const squaredSize = size * size;
2291
2486
  const missing = await ImageLoader.getData("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX/AP8AAACfphTyAAAAFUlEQVQoz2MIhQKGVVAwKjIqQrwIAHRz/wFI17TEAAAAAElFTkSuQmCC");
2292
2487
  const empty = await ImageLoader.getData("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAA5JREFUKM9jGAWjgAIAAAJAAAFSSwuTAAAAAElFTkSuQmCC");
@@ -2341,10 +2536,10 @@ var UVMapper = class {
2341
2536
  }
2342
2537
  }
2343
2538
  const atlasImageData = image.toDataURL();
2344
- console.log(p6, "Atlas Image for", model.key, atlasImageData);
2539
+ console.log(p5, "Atlas Image for", model.key, atlasImageData);
2345
2540
  this.fillMissingTextureKeys(model.textures, positions);
2346
2541
  if (isItemModel) {
2347
- console.debug(p6, "Generating item model for", model);
2542
+ console.debug(p5, "Generating item model for", model);
2348
2543
  model.elements = [];
2349
2544
  for (let layerName of ModelGenerator.ITEM_LAYERS) {
2350
2545
  const textureImage = textureMap[layerName];
@@ -2352,7 +2547,7 @@ var UVMapper = class {
2352
2547
  model.elements.push(...ModelGenerator.generateItemModel(textureImage.data, layerName));
2353
2548
  }
2354
2549
  }
2355
- console.debug(p6, "Item model elements", model.elements);
2550
+ console.debug(p5, "Item model elements", model.elements);
2356
2551
  }
2357
2552
  if (!model.elements) {
2358
2553
  }
@@ -2370,17 +2565,13 @@ var UVMapper = class {
2370
2565
  this.setCubeFaceUvInArray(uv, faceIndex * 4, [0, 1, 8 / size, (size - 8) / size]);
2371
2566
  continue;
2372
2567
  }
2568
+ if (!face.texture) continue;
2373
2569
  if (!face.uv) {
2374
2570
  face.uv = this.getFallbackUv(element, faceName);
2375
2571
  }
2376
- let faceTexture = face.texture;
2377
- let texPosition;
2378
- let texSize;
2379
- if (faceTexture) {
2380
- faceTexture = faceTexture.substr(1);
2381
- texPosition = positions[faceTexture] || [0, 0];
2382
- texSize = sizes[faceTexture] || [16, 16];
2383
- }
2572
+ const faceTexture = face.texture.substr(1);
2573
+ const texPosition = positions[faceTexture] || [0, 0];
2574
+ const texSize = sizes[faceTexture] || [16, 16];
2384
2575
  let texPosV = new import_three8.Vector2(texPosition[0], texPosition[1]);
2385
2576
  const [tl, tr, bl, br] = this.expandAndRotateMcUvs(face.uv, face.rotation, texSize[0], texSize[1]);
2386
2577
  tl.add(texPosV);
@@ -2412,7 +2603,7 @@ var UVMapper = class {
2412
2603
  hasTransparency
2413
2604
  );
2414
2605
  } else {
2415
- console.warn(p6, "Model does not have any textures", model);
2606
+ console.warn(p5, "Model does not have any textures", model);
2416
2607
  }
2417
2608
  return void 0;
2418
2609
  }
@@ -2550,17 +2741,20 @@ function shutdown() {
2550
2741
  }
2551
2742
 
2552
2743
  // src/assets/Entities.ts
2553
- var import_typescript_memoize3 = require("typescript-memoize");
2554
2744
  var Entities = class {
2555
2745
  static async getBlockEntityModels() {
2556
2746
  const key = AssetKey.parse("models", "minerender:blockEntityModels");
2557
2747
  console.log(key);
2558
- return AssetLoader.get(key, "json" /* JSON */);
2748
+ return Caching.entityModelsCache.get(key.serialize(), () => {
2749
+ return AssetLoader.get(key, "json" /* JSON */);
2750
+ });
2559
2751
  }
2560
2752
  static async getEntityModels() {
2561
2753
  const key = AssetKey.parse("models", "minerender:entityModels");
2562
2754
  console.log(key);
2563
- return AssetLoader.get(key, "json" /* JSON */);
2755
+ return Caching.entityModelsCache.get(key.serialize(), () => {
2756
+ return AssetLoader.get(key, "json" /* JSON */);
2757
+ });
2564
2758
  }
2565
2759
  // BlockEntity names are hardcoded
2566
2760
  static async getBlockList() {
@@ -2606,12 +2800,6 @@ var Entities = class {
2606
2800
  };
2607
2801
  }
2608
2802
  };
2609
- __decorateClass([
2610
- (0, import_typescript_memoize3.Memoize)()
2611
- ], Entities, "getBlockEntityModels", 1);
2612
- __decorateClass([
2613
- (0, import_typescript_memoize3.Memoize)()
2614
- ], Entities, "getEntityModels", 1);
2615
2803
  var EntityModels = class {
2616
2804
  };
2617
2805
  var BlockEntityModels = class {
@@ -2675,8 +2863,8 @@ var MineRenderError = class _MineRenderError extends Error {
2675
2863
  };
2676
2864
 
2677
2865
  // src/renderer/SceneObject.ts
2678
- var import_ts_deepmerge4 = __toESM(require_dist());
2679
- var p7 = prefix("SceneObject");
2866
+ var import_ts_deepmerge3 = __toESM(require_dist());
2867
+ var p6 = prefix("SceneObject");
2680
2868
  var _SceneObject = class _SceneObject extends import_three9.Object3D {
2681
2869
  constructor(options) {
2682
2870
  super();
@@ -2684,7 +2872,7 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2684
2872
  this.materialCallbacks = {};
2685
2873
  this._isInstanced = false;
2686
2874
  this._instanceCounter = 0;
2687
- this.options = (0, import_ts_deepmerge4.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
2875
+ this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
2688
2876
  console.log("SceneObject options", this.options);
2689
2877
  }
2690
2878
  set scene(scene) {
@@ -2778,6 +2966,7 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2778
2966
  }
2779
2967
  createInstancedMesh(name, geometry, material, count) {
2780
2968
  const mesh = new import_three9.InstancedMesh(geometry, material, count);
2969
+ mesh.count = 0;
2781
2970
  if (name) {
2782
2971
  mesh.name = `mesh:${name}`;
2783
2972
  }
@@ -2855,9 +3044,13 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2855
3044
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2856
3045
  const i = this._instanceCounter++;
2857
3046
  this.setMatrixAt(i, new import_three9.Matrix4());
2858
- console.debug(p7, "nextInstance " + i);
3047
+ const mesh = this.children[0];
3048
+ if (mesh && isInstancedMesh(mesh)) {
3049
+ mesh.count = Math.min(this._instanceCounter, mesh.instanceMatrix.count);
3050
+ }
3051
+ console.debug(p6, "nextInstance " + i);
2859
3052
  if (i === this.options.maxInstanceCount) {
2860
- console.warn(p7, "Max instance count reached for " + this);
3053
+ console.warn(p6, "Max instance count reached for " + this);
2861
3054
  }
2862
3055
  if (this.scene) {
2863
3056
  this.scene.stats.instanceCount++;
@@ -3033,7 +3226,7 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
3033
3226
  }
3034
3227
  //</editor-fold>
3035
3228
  };
3036
- _SceneObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, {
3229
+ _SceneObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge3.default)({}, {
3037
3230
  instanceMeshes: true,
3038
3231
  maxInstanceCount: 50,
3039
3232
  mergeMeshes: true,
@@ -3045,16 +3238,16 @@ function isSceneObject(obj) {
3045
3238
  }
3046
3239
 
3047
3240
  // src/entity/scene/EntityObject.ts
3048
- var import_ts_deepmerge5 = __toESM(require_dist());
3241
+ var import_ts_deepmerge4 = __toESM(require_dist());
3049
3242
  var import_three11 = require("three");
3050
- var THREE2 = __toESM(require("three"));
3243
+ var THREE3 = __toESM(require("three"));
3051
3244
  var EntityObject = class extends SceneObject {
3052
3245
  constructor(entity, options) {
3053
3246
  super();
3054
3247
  this.entity = entity;
3055
3248
  this.isEntityObject = true;
3056
3249
  this.meshesCreated = false;
3057
- this.options = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
3250
+ this.options = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
3058
3251
  }
3059
3252
  async init() {
3060
3253
  this.createMeshes();
@@ -3063,8 +3256,8 @@ var EntityObject = class extends SceneObject {
3063
3256
  dispose() {
3064
3257
  super.dispose();
3065
3258
  }
3066
- async loadTextures() {
3067
- this.imageData = await ModelTextures.get(new AssetKey(
3259
+ get textureKey() {
3260
+ return new AssetKey(
3068
3261
  this.entity.key?.namespace ?? DEFAULT_NAMESPACE,
3069
3262
  this.entity.key.path,
3070
3263
  //TODO: texture may differ from entity name; most of them are in subdirectories for multiple variants etc.
@@ -3072,7 +3265,10 @@ var EntityObject = class extends SceneObject {
3072
3265
  "entity",
3073
3266
  "assets",
3074
3267
  ".png"
3075
- ));
3268
+ );
3269
+ }
3270
+ async loadTextures() {
3271
+ this.imageData = await ModelTextures.get(this.textureKey);
3076
3272
  }
3077
3273
  //TODO: abstract this, since extracted model data can be used for entities, blocks, players
3078
3274
  createMeshes(force = false) {
@@ -3091,8 +3287,8 @@ var EntityObject = class extends SceneObject {
3091
3287
  const l = cube.maxZ - cube.minZ;
3092
3288
  const uv = texture.toUvArray(w, h, l);
3093
3289
  const cubeGeo = this._getBoxGeometryForDimensionsAndUv(w, h, l, uv).clone();
3094
- cubeGeo.applyMatrix4(new THREE2.Matrix4().makeTranslation(w / 2, h / 2, l / 2));
3095
- cubeGeo.applyMatrix4(new THREE2.Matrix4().makeTranslation(cube.minX, cube.minY, cube.minZ));
3290
+ cubeGeo.applyMatrix4(new THREE3.Matrix4().makeTranslation(w / 2, h / 2, l / 2));
3291
+ cubeGeo.applyMatrix4(new THREE3.Matrix4().makeTranslation(cube.minX, cube.minY, cube.minZ));
3096
3292
  applyModelPartRotation(part, cubeGeo);
3097
3293
  const mesh = this.createMesh(partName, cubeGeo, mat);
3098
3294
  partAnchor.add(mesh);
@@ -3105,23 +3301,26 @@ var EntityObject = class extends SceneObject {
3105
3301
  this.meshesCreated = true;
3106
3302
  }
3107
3303
  async applyTextures() {
3108
- const textureAsset = await ModelTextures.preload(new AssetKey(
3109
- this.entity.key?.namespace ?? DEFAULT_NAMESPACE,
3110
- this.entity.key.path,
3111
- "textures",
3112
- "entity",
3113
- "assets",
3114
- ".png"
3115
- ));
3116
- if (textureAsset) {
3117
- let mat = Materials.getImage({ texture: { src: textureAsset.src } });
3118
- this.iterateAllMeshes((mesh) => {
3119
- mesh.material = mat;
3120
- });
3121
- }
3304
+ const assetKeyStr = this.textureKey.serialize();
3305
+ const keyStr = `entity:${assetKeyStr}`;
3306
+ let mat = Caching.materialCache.getIfPresent(keyStr);
3307
+ if (!mat) {
3308
+ const pending = this.loadTextures();
3309
+ const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
3310
+ await pending;
3311
+ if (!this.imageData) return;
3312
+ const canvas = this.imageData.data.canvas;
3313
+ const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
3314
+ mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
3315
+ this.imageData = void 0;
3316
+ }
3317
+ this.iterateAllMeshes((mesh) => {
3318
+ mesh.material = mat;
3319
+ });
3320
+ this.notifyDirty();
3122
3321
  }
3123
3322
  };
3124
- EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, {});
3323
+ EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, {});
3125
3324
  function isEntityObject(obj) {
3126
3325
  return obj.isEntityObject;
3127
3326
  }
@@ -3133,7 +3332,7 @@ var GuiObject = class extends SceneObject {
3133
3332
 
3134
3333
  // src/inspector/SceneInspector.ts
3135
3334
  var import_three12 = require("three");
3136
- var p8 = prefix("SceneInspector");
3335
+ var p7 = prefix("SceneInspector");
3137
3336
  var help = "<span>Ctrl+Click to Select<br/></span><br/>";
3138
3337
  var SceneInspector = class {
3139
3338
  constructor(renderer) {
@@ -3202,7 +3401,7 @@ var SceneInspector = class {
3202
3401
  }
3203
3402
  selectObject(targetObject, targetIntersection) {
3204
3403
  this.selectedObject = targetObject;
3205
- console.log(p8, "selected", targetObject);
3404
+ console.log(p7, "selected", targetObject);
3206
3405
  this.redraw(targetObject, targetIntersection);
3207
3406
  }
3208
3407
  redraw(targetObject, targetIntersection) {
@@ -3500,7 +3699,7 @@ var SceneStatsDisplay = class {
3500
3699
  };
3501
3700
 
3502
3701
  // src/instance/InstanceManager.ts
3503
- var p9 = prefix("InstanceManager");
3702
+ var p8 = prefix("InstanceManager");
3504
3703
  var InstanceManager = class {
3505
3704
  constructor() {
3506
3705
  this.isInstanceManager = true;
@@ -3508,7 +3707,7 @@ var InstanceManager = class {
3508
3707
  }
3509
3708
  async get(key) {
3510
3709
  if (key in this.instanceCache) {
3511
- console.debug(p9, "key in cache", key);
3710
+ console.debug(p8, "key in cache", key);
3512
3711
  return (await this.instanceCache[key]).nextInstance();
3513
3712
  }
3514
3713
  return void 0;
@@ -3517,13 +3716,17 @@ var InstanceManager = class {
3517
3716
  if (key in this.instanceCache) {
3518
3717
  return await this.get(key);
3519
3718
  }
3520
- console.debug(p9, "key not in cache", key);
3521
- this.instanceCache[key] = new Promise(async (resolve) => {
3522
- const obj = await supplier();
3523
- const instance = obj.nextInstance();
3524
- resolve(instance);
3525
- });
3526
- return await this.instanceCache[key];
3719
+ console.debug(p8, "key not in cache", key);
3720
+ const pending = Promise.resolve().then(supplier).then((obj) => obj.nextInstance());
3721
+ this.instanceCache[key] = pending;
3722
+ try {
3723
+ return await pending;
3724
+ } catch (error) {
3725
+ if (this.instanceCache[key] === pending) {
3726
+ delete this.instanceCache[key];
3727
+ }
3728
+ throw error;
3729
+ }
3527
3730
  }
3528
3731
  reset() {
3529
3732
  for (let instanceCacheKey in this.instanceCache) {
@@ -3576,20 +3779,105 @@ function isQuadArray(obj) {
3576
3779
  return Array.isArray(obj) && obj.length === 4;
3577
3780
  }
3578
3781
 
3579
- // src/model/scene/ModelObject.ts
3580
- var import_three15 = require("three");
3782
+ // src/model/block/blockTints.json
3783
+ var blockTints_default = {
3784
+ "minecraft:large_fern": { source: "grass" },
3785
+ "minecraft:tall_grass": { source: "grass" },
3786
+ "minecraft:grass_block": { source: "grass" },
3787
+ "minecraft:fern": { source: "grass" },
3788
+ "minecraft:grass": { source: "grass" },
3789
+ "minecraft:short_grass": { source: "grass" },
3790
+ "minecraft:potted_fern": { source: "grass" },
3791
+ "minecraft:bush": { source: "grass" },
3792
+ "minecraft:pink_petals": { source: "grass", untinted: [0] },
3793
+ "minecraft:wildflowers": { source: "grass", untinted: [0] },
3794
+ "minecraft:spruce_leaves": { source: "constant", color: 6396257 },
3795
+ "minecraft:birch_leaves": { source: "constant", color: 8431445 },
3796
+ "minecraft:oak_leaves": { source: "constant", color: 4764952 },
3797
+ "minecraft:jungle_leaves": { source: "constant", color: 4764952 },
3798
+ "minecraft:acacia_leaves": { source: "constant", color: 4764952 },
3799
+ "minecraft:dark_oak_leaves": { source: "constant", color: 4764952 },
3800
+ "minecraft:vine": { source: "constant", color: 4764952 },
3801
+ "minecraft:mangrove_leaves": { source: "constant", color: 4764952 },
3802
+ "minecraft:leaf_litter": { source: "constant", color: 6044722 },
3803
+ "minecraft:water_cauldron": { source: "constant", color: 4159204 },
3804
+ "minecraft:redstone_wire": { source: "redstone" },
3805
+ "minecraft:attached_melon_stem": { source: "constant", color: 14731036 },
3806
+ "minecraft:attached_pumpkin_stem": { source: "constant", color: 14731036 },
3807
+ "minecraft:melon_stem": { source: "stem" },
3808
+ "minecraft:pumpkin_stem": { source: "stem" },
3809
+ "minecraft:lily_pad": { source: "constant", color: 7455580 }
3810
+ };
3581
3811
 
3582
- // src/three/BufferGeometryUtils.js
3583
- var import_three14 = require("three");
3584
- function computeTangents(geometry) {
3585
- geometry.computeTangents();
3586
- console.warn("THREE.BufferGeometryUtils: .computeTangents() has been removed. Use BufferGeometry.computeTangents() instead.");
3587
- }
3588
- function mergeBufferGeometries(geometries, useGroups = false) {
3589
- const isIndexed = geometries[0].index !== null;
3590
- const attributesUsed = new Set(Object.keys(geometries[0].attributes));
3591
- const morphAttributesUsed = new Set(Object.keys(geometries[0].morphAttributes));
3592
- const attributes = {};
3812
+ // src/model/block/BlockTints.ts
3813
+ var rules = blockTints_default;
3814
+ var BlockTints = class {
3815
+ /** Resolves block preview colors without biome context; explicit tints take precedence. */
3816
+ static async get(key, state, model, tints) {
3817
+ const rule = key && rules[key.toNamespacedString()];
3818
+ if (!key || !rule) return tints;
3819
+ const indices = /* @__PURE__ */ new Set();
3820
+ for (const element of model.elements ?? []) {
3821
+ for (const face of Object.values(element.faces)) {
3822
+ const index = face?.tintindex;
3823
+ if (index !== void 0 && index >= 0 && tints?.[index] === void 0 && !rule.untinted?.includes(index)) {
3824
+ indices.add(index);
3825
+ }
3826
+ }
3827
+ }
3828
+ if (!indices.size) return tints;
3829
+ let color;
3830
+ switch (rule.source) {
3831
+ case "constant":
3832
+ color = rule.color;
3833
+ break;
3834
+ case "grass":
3835
+ color = await this.grassColor(key);
3836
+ break;
3837
+ case "redstone": {
3838
+ const power = Number(state.power ?? 0) / 15;
3839
+ const red = power * 0.6 + (power > 0 ? 0.4 : 0.3);
3840
+ const green = Math.max(0, power * power * 0.7 - 0.5);
3841
+ const blue = Math.max(0, power * power * 0.6 - 0.7);
3842
+ color = Math.floor(red * 255) << 16 | Math.floor(green * 255) << 8 | Math.floor(blue * 255);
3843
+ break;
3844
+ }
3845
+ case "stem": {
3846
+ const age = Number(state.age ?? 0);
3847
+ color = age * 32 << 16 | 255 - age * 8 << 8 | age * 4;
3848
+ break;
3849
+ }
3850
+ }
3851
+ return { ...Object.fromEntries([...indices].map((index) => [index, color])), ...tints };
3852
+ }
3853
+ static async grassColor(origin) {
3854
+ const key = AssetKey.parse("textures", "minecraft:colormap/grass", origin);
3855
+ return await Caching.blockTintCache.get(key.serialize(), async () => {
3856
+ const image = await ModelTextures.get(key);
3857
+ if (!image) throw new MineRenderError(`Missing grass colormap: ${key.toNamespacedString()}`);
3858
+ if (image.width !== 256 || image.height !== 256) {
3859
+ throw new MineRenderError("Grass colormaps must be 256 \xD7 256 pixels");
3860
+ }
3861
+ const [red, green, blue] = image.data.getImageData(127, 127, 1, 1).data;
3862
+ return red << 16 | green << 8 | blue;
3863
+ });
3864
+ }
3865
+ };
3866
+
3867
+ // src/model/scene/ModelObject.ts
3868
+ var import_three15 = require("three");
3869
+
3870
+ // src/three/BufferGeometryUtils.js
3871
+ var import_three14 = require("three");
3872
+ function computeTangents(geometry) {
3873
+ geometry.computeTangents();
3874
+ console.warn("THREE.BufferGeometryUtils: .computeTangents() has been removed. Use BufferGeometry.computeTangents() instead.");
3875
+ }
3876
+ function mergeBufferGeometries(geometries, useGroups = false) {
3877
+ const isIndexed = geometries[0].index !== null;
3878
+ const attributesUsed = new Set(Object.keys(geometries[0].attributes));
3879
+ const morphAttributesUsed = new Set(Object.keys(geometries[0].morphAttributes));
3880
+ const attributes = {};
3593
3881
  const morphAttributes = {};
3594
3882
  const morphTargetsRelative = geometries[0].morphTargetsRelative;
3595
3883
  const mergedGeometry = new import_three14.BufferGeometry();
@@ -4112,15 +4400,16 @@ function computeMorphedAttributes(object) {
4112
4400
  }
4113
4401
 
4114
4402
  // src/model/scene/ModelObject.ts
4115
- var import_ts_deepmerge6 = __toESM(require_dist());
4116
- var p10 = prefix("ModelObject");
4403
+ var import_ts_deepmerge5 = __toESM(require_dist());
4404
+ var p9 = prefix("ModelObject");
4117
4405
  var _ModelObject = class _ModelObject extends SceneObject {
4118
4406
  constructor(originalModel, options) {
4119
4407
  super(options);
4120
4408
  this.originalModel = originalModel;
4121
4409
  this.isModelObject = true;
4122
4410
  this.meshesCreated = false;
4123
- this.options = (0, import_ts_deepmerge6.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
4411
+ this.options = (0, import_ts_deepmerge5.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
4412
+ if (this.options.tints) this.options.tints = { ...this.options.tints };
4124
4413
  console.log("ModelObject options", this.options);
4125
4414
  }
4126
4415
  async init() {
@@ -4147,6 +4436,23 @@ var _ModelObject = class _ModelObject extends SceneObject {
4147
4436
  if (this.atlas.model.elements) {
4148
4437
  this.atlas.model.elements?.forEach((el) => {
4149
4438
  const elGeo = this._getBoxGeometryFromElement(el).clone();
4439
+ if (this.options.uvLockRotation) {
4440
+ UVMapper.lockUvs(elGeo, el.faces, this.atlas, new import_three15.Euler(...this.options.uvLockRotation));
4441
+ }
4442
+ if (this.options.tints) {
4443
+ const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
4444
+ for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
4445
+ const tintIndex = el.faces[faceName]?.tintindex;
4446
+ if (tintIndex === void 0 || tintIndex < 0) continue;
4447
+ const tint = this.options.tints[tintIndex];
4448
+ if (tint === void 0) continue;
4449
+ const color = new import_three15.Color(tint);
4450
+ for (let vertex = 0; vertex < 4; vertex++) {
4451
+ color.toArray(colors, (faceIndex * 4 + vertex) * 3);
4452
+ }
4453
+ }
4454
+ elGeo.setAttribute("color", new import_three15.BufferAttribute(colors, 3));
4455
+ }
4150
4456
  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));
4151
4457
  elGeo.applyMatrix4(new import_three15.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
4152
4458
  if (el.rotation) {
@@ -4163,10 +4469,10 @@ var _ModelObject = class _ModelObject extends SceneObject {
4163
4469
  }
4164
4470
  });
4165
4471
  } else {
4166
- console.debug(p10, this.atlas.model, "has no elements");
4472
+ console.debug(p9, this.atlas.model, "has no elements");
4167
4473
  }
4168
4474
  } else {
4169
- console.debug(p10, "Missing atlas for", this);
4475
+ console.debug(p9, "Missing atlas for", this);
4170
4476
  }
4171
4477
  if (this.options.mergeMeshes) {
4172
4478
  let combinedGeo;
@@ -4203,6 +4509,7 @@ var _ModelObject = class _ModelObject extends SceneObject {
4203
4509
  /*TODO: get this from render options*/
4204
4510
  );
4205
4511
  this.iterateAllMeshes((mesh) => {
4512
+ if (mesh.geometry.hasAttribute("color")) mat.vertexColors = true;
4206
4513
  mesh.material = mat;
4207
4514
  });
4208
4515
  if (this.atlas.hasAnimation) {
@@ -4218,16 +4525,26 @@ var _ModelObject = class _ModelObject extends SceneObject {
4218
4525
  }
4219
4526
  }
4220
4527
  };
4221
- _ModelObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge6.default)({}, SceneObject.DEFAULT_OPTIONS, {});
4528
+ _ModelObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, {});
4222
4529
  var ModelObject = _ModelObject;
4223
4530
  function isModelObject(obj) {
4224
4531
  return obj.isModelObject;
4225
4532
  }
4226
4533
 
4227
4534
  // src/model/block/scene/BlockObject.ts
4228
- var import_ts_deepmerge7 = __toESM(require_dist());
4535
+ var import_ts_deepmerge6 = __toESM(require_dist());
4229
4536
  var import_three16 = require("three");
4230
- var p11 = prefix("BlockObject");
4537
+ var p10 = prefix("BlockObject");
4538
+ function matchesCondition(condition, state) {
4539
+ return Object.entries(condition).every(([key, value]) => {
4540
+ if (Array.isArray(value)) {
4541
+ if (key === "OR") return value.some((child) => matchesCondition(child, state));
4542
+ if (key === "AND") return value.every((child) => matchesCondition(child, state));
4543
+ return false;
4544
+ }
4545
+ return typeof value === "string" && state[key] !== void 0 && value.split("|").includes(`${state[key]}`);
4546
+ });
4547
+ }
4231
4548
  var _BlockObject = class _BlockObject extends SceneObject {
4232
4549
  constructor(blockState, options) {
4233
4550
  super(options);
@@ -4241,11 +4558,11 @@ var _BlockObject = class _BlockObject extends SceneObject {
4241
4558
  this._instanceModel = [];
4242
4559
  this._variants = [];
4243
4560
  this._models = [];
4244
- this.options = (0, import_ts_deepmerge7.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
4561
+ this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
4245
4562
  }
4246
4563
  async init() {
4247
4564
  if (this.options.applyDefaultState) {
4248
- const defaultState = this.blockState.key ? BlockStates.getDefaultState(this.blockState.key) : void 0;
4565
+ const defaultState = this.blockState.key ? await BlockStates.getDefaultState(this.blockState.key) : void 0;
4249
4566
  if (defaultState && Object.keys(defaultState).length > 0) {
4250
4567
  const state = {};
4251
4568
  for (let k in defaultState) {
@@ -4256,15 +4573,9 @@ var _BlockObject = class _BlockObject extends SceneObject {
4256
4573
  if (this.blockState.variants) {
4257
4574
  await this.setState(Object.keys(this.blockState.variants)[0]);
4258
4575
  } else if (this.blockState.multipart) {
4259
- for (let part of this.blockState.multipart) {
4260
- if (part.when && !("OR" in part.when)) {
4261
- const k = Object.keys(part.when)[0];
4262
- if (k) {
4263
- await this.setState(k, part.when[k].split("|")[0]);
4264
- break;
4265
- }
4266
- }
4267
- }
4576
+ const condition = this.blockState.multipart.map((part) => part.when).find((when) => when !== void 0 && Object.values(when).every((value) => typeof value === "string"));
4577
+ const state = Object.fromEntries(Object.entries(condition ?? {}).map(([key, value]) => [key, value.split("|")[0]]));
4578
+ await this.setState(state);
4268
4579
  }
4269
4580
  }
4270
4581
  } else {
@@ -4321,55 +4632,11 @@ var _BlockObject = class _BlockObject extends SceneObject {
4321
4632
  } else if (this.blockState.multipart) {
4322
4633
  for (let part of this.blockState.multipart) {
4323
4634
  if (!part.apply) {
4324
- console.debug(p11, "Missing apply for blockState part", part);
4635
+ console.debug(p10, "Missing apply for blockState part", part);
4325
4636
  continue;
4326
4637
  }
4327
- if (!part.when) {
4638
+ if (!part.when || matchesCondition(part.when, state)) {
4328
4639
  out.push(this.getSingleVariant(part.apply));
4329
- } else {
4330
- let matches = true;
4331
- if ("OR" in part.when) {
4332
- const or = part.when.OR;
4333
- let anyMatch = false;
4334
- for (let o of or) {
4335
- for (let k in o) {
4336
- const split = o[k].split("|");
4337
- let m = false;
4338
- for (let s of split) {
4339
- if (`${state[k]}` === `${s}`) {
4340
- m = true;
4341
- break;
4342
- }
4343
- }
4344
- if (m) {
4345
- anyMatch = true;
4346
- break;
4347
- }
4348
- }
4349
- }
4350
- if (!anyMatch) {
4351
- matches = false;
4352
- }
4353
- } else {
4354
- for (let k in part.when) {
4355
- const split = part.when[k].split("|");
4356
- let m = false;
4357
- for (let s of split) {
4358
- if (`${state[k]}` === `${s}`) {
4359
- m = true;
4360
- break;
4361
- }
4362
- }
4363
- if (!m) {
4364
- matches = false;
4365
- break;
4366
- }
4367
- }
4368
- }
4369
- if (matches) {
4370
- const variants = part.apply;
4371
- out.push(this.getSingleVariant(variants));
4372
- }
4373
4640
  }
4374
4641
  }
4375
4642
  }
@@ -4399,11 +4666,21 @@ var _BlockObject = class _BlockObject extends SceneObject {
4399
4666
  }
4400
4667
  }
4401
4668
  getSingleVariant(variants) {
4402
- if (Array.isArray(variants)) {
4403
- return variants[0];
4404
- } else {
4405
- return variants;
4406
- }
4669
+ if (!Array.isArray(variants)) return variants;
4670
+ if (!variants.length) throw new MineRenderError("Blockstate variant arrays must not be empty");
4671
+ const total = variants.reduce((sum, variant) => {
4672
+ const weight = variant.weight ?? 1;
4673
+ if (!Number.isInteger(weight) || weight < 1) {
4674
+ throw new MineRenderError(`Invalid blockstate variant weight: ${weight}`);
4675
+ }
4676
+ return sum + weight;
4677
+ }, 0);
4678
+ let choice = Math.random() * total;
4679
+ for (const variant of variants) {
4680
+ choice -= variant.weight ?? 1;
4681
+ if (choice < 0) return variant;
4682
+ }
4683
+ return variants[variants.length - 1];
4407
4684
  }
4408
4685
  // @deprecated
4409
4686
  async createAVariant(variants, instanceInfo) {
@@ -4411,28 +4688,25 @@ var _BlockObject = class _BlockObject extends SceneObject {
4411
4688
  await this.createVariant(variant);
4412
4689
  }
4413
4690
  async createVariant(variant) {
4414
- const model = await Models.getMerged(AssetKey.parse("models", variant.model));
4415
- const obj = await this.scene.addModel(model, this.options);
4416
- if (isInstanceReference(obj) || obj.isInstanced) {
4417
- this._isInstanced = true;
4418
- this._instanceCounter = 1;
4419
- }
4420
- let rotation = new import_three16.Euler(0, 0, 0);
4691
+ const rotation = new import_three16.Euler();
4421
4692
  if (typeof variant.x !== "undefined") {
4422
4693
  rotation.x = toRadians(clampRotationDegrees(variant.x));
4423
4694
  }
4424
4695
  if (typeof variant.y !== "undefined") {
4425
- if (typeof variant.x !== "undefined") {
4426
- rotation.y = toRadians(clampRotationDegrees(variant.y));
4427
- } else {
4428
- rotation.y = toRadians(clampRotationDegrees(360 - variant.y));
4429
- }
4696
+ rotation.y = toRadians(clampRotationDegrees(typeof variant.x !== "undefined" ? variant.y : 360 - variant.y));
4697
+ }
4698
+ const model = await Models.getMerged(AssetKey.parse("models", variant.model));
4699
+ const options = {
4700
+ ...this.options,
4701
+ tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints) : this.options.tints,
4702
+ uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0) ? [rotation.x, rotation.y, rotation.z] : void 0
4703
+ };
4704
+ const obj = await this.scene.addModel(model, options);
4705
+ if (isInstanceReference(obj) || obj.isInstanced) {
4706
+ this._isInstanced = true;
4707
+ this._instanceCounter = 1;
4430
4708
  }
4431
4709
  obj.setRotation(rotation);
4432
- setTimeout(() => {
4433
- obj.setRotation(rotation);
4434
- }, 150);
4435
- console.log(obj);
4436
4710
  return obj;
4437
4711
  }
4438
4712
  async resetState() {
@@ -4522,15 +4796,16 @@ var _BlockObject = class _BlockObject extends SceneObject {
4522
4796
  }
4523
4797
  }
4524
4798
  setPosition(position) {
4525
- super.setPosition(position);
4799
+ this.position.copy(position);
4526
4800
  for (let model of this._models) {
4527
4801
  model.setPosition(position);
4528
4802
  }
4803
+ this.notifyDirty();
4529
4804
  }
4530
4805
  //TODO: should override rotation + scale methods
4531
4806
  //TODO
4532
4807
  };
4533
- _BlockObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge7.default)({}, ModelObject.DEFAULT_OPTIONS, {
4808
+ _BlockObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge6.default)({}, ModelObject.DEFAULT_OPTIONS, {
4534
4809
  applyDefaultState: true
4535
4810
  });
4536
4811
  var BlockObject = _BlockObject;
@@ -4580,7 +4855,7 @@ var StructureParser = class {
4580
4855
 
4581
4856
  // src/renderer/MineRenderScene.ts
4582
4857
  var import_three17 = require("three");
4583
- var import_ts_deepmerge9 = __toESM(require_dist());
4858
+ var import_ts_deepmerge8 = __toESM(require_dist());
4584
4859
 
4585
4860
  // src/skin/SkinPart.ts
4586
4861
  var SkinPart = /* @__PURE__ */ ((SkinPart2) => {
@@ -5311,7 +5586,7 @@ var slimSkinGeometries = {
5311
5586
  };
5312
5587
 
5313
5588
  // src/skin/scene/SkinObject.ts
5314
- var import_ts_deepmerge8 = __toESM(require_dist());
5589
+ var import_ts_deepmerge7 = __toESM(require_dist());
5315
5590
  var SkinObject = class extends SceneObject {
5316
5591
  constructor(options) {
5317
5592
  super();
@@ -5319,7 +5594,7 @@ var SkinObject = class extends SceneObject {
5319
5594
  this.legacy = false;
5320
5595
  this.skinTextureWidth = 64;
5321
5596
  this.skinTextureHeight = 64;
5322
- this.options = (0, import_ts_deepmerge8.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
5597
+ this.options = (0, import_ts_deepmerge7.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
5323
5598
  }
5324
5599
  async init() {
5325
5600
  this.createMeshes();
@@ -5436,7 +5711,7 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5436
5711
  this.dirty = true;
5437
5712
  }
5438
5713
  };
5439
- this.options = (0, import_ts_deepmerge9.default)({}, _MineRenderScene.DEFAULT_OPTIONS, options ?? {});
5714
+ this.options = (0, import_ts_deepmerge8.default)({}, _MineRenderScene.DEFAULT_OPTIONS, options ?? {});
5440
5715
  }
5441
5716
  add(...objects) {
5442
5717
  for (const object of objects) {
@@ -5494,7 +5769,13 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5494
5769
  const obj = await objectSupplier();
5495
5770
  if (obj?.options?.instanceMeshes && asset.key && asset.key?.assetType === "models") {
5496
5771
  console.log("instanceMeshes + key");
5497
- const key = asset.key.serialize();
5772
+ let key = asset.key.serialize();
5773
+ if (isModelObject(obj)) {
5774
+ const { uvLockRotation, tints } = obj.options;
5775
+ if (uvLockRotation) key += `|uvlock:${uvLockRotation.join(",")}`;
5776
+ const palette = Object.entries(tints ?? {}).sort(([a], [b]) => Number(a) - Number(b));
5777
+ if (palette.length) key += `|tints:${JSON.stringify(palette)}`;
5778
+ }
5498
5779
  return this.instanceManager.getOrCreate(key, async () => {
5499
5780
  obj.scene = this;
5500
5781
  await obj.init();
@@ -5532,1106 +5813,1163 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5532
5813
  return this.addSceneObject(entity, () => new EntityObject(entity, options), options, parent);
5533
5814
  }
5534
5815
  };
5535
- _MineRenderScene.DEFAULT_OPTIONS = (0, import_ts_deepmerge9.default)({}, {});
5816
+ _MineRenderScene.DEFAULT_OPTIONS = (0, import_ts_deepmerge8.default)({}, {});
5536
5817
  var MineRenderScene = _MineRenderScene;
5537
5818
  function isMineRenderScene(obj) {
5538
5819
  return obj.isMineRenderScene;
5539
5820
  }
5540
5821
 
5541
5822
  // src/renderer/Renderer.ts
5542
- var import_three18 = require("three");
5543
- var import_ts_deepmerge10 = __toESM(require_dist());
5823
+ var import_three19 = require("three");
5824
+ var import_ts_deepmerge9 = __toESM(require_dist());
5544
5825
  var import_stats = __toESM(require("stats.js"));
5545
5826
  var import_postprocessing = require("postprocessing");
5546
- var _Renderer = class _Renderer {
5547
- constructor(options) {
5548
- this._dirty = true;
5549
- this._animationTimer = void 0;
5550
- this._animationFrame = void 0;
5551
- this._resizeListener = void 0;
5552
- this._disposed = false;
5553
- this._debugHelpers = [];
5554
- this._eventDispatchers = /* @__PURE__ */ new Map();
5555
- this._changeListener = () => {
5556
- this._dirty = true;
5827
+
5828
+ // src/three/OrbitControls.js
5829
+ var import_three18 = require("three");
5830
+ var _changeEvent = { type: "change" };
5831
+ var _startEvent = { type: "start" };
5832
+ var _endEvent = { type: "end" };
5833
+ var OrbitControls = class extends import_three18.EventDispatcher {
5834
+ constructor(object, domElement) {
5835
+ super();
5836
+ if (domElement === void 0) console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.');
5837
+ if (domElement === document) console.error('THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.');
5838
+ this.object = object;
5839
+ this.domElement = domElement;
5840
+ this.domElement.style.touchAction = "none";
5841
+ this.enabled = true;
5842
+ this.target = new import_three18.Vector3();
5843
+ this.minDistance = 0;
5844
+ this.maxDistance = Infinity;
5845
+ this.minZoom = 0;
5846
+ this.maxZoom = Infinity;
5847
+ this.minPolarAngle = 0;
5848
+ this.maxPolarAngle = Math.PI;
5849
+ this.minAzimuthAngle = -Infinity;
5850
+ this.maxAzimuthAngle = Infinity;
5851
+ this.enableDamping = false;
5852
+ this.dampingFactor = 0.05;
5853
+ this.enableZoom = true;
5854
+ this.zoomSpeed = 1;
5855
+ this.enableRotate = true;
5856
+ this.rotateSpeed = 1;
5857
+ this.enablePan = true;
5858
+ this.panSpeed = 1;
5859
+ this.screenSpacePanning = true;
5860
+ this.keyPanSpeed = 7;
5861
+ this.autoRotate = false;
5862
+ this.autoRotateSpeed = 2;
5863
+ this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" };
5864
+ this.mouseButtons = { LEFT: import_three18.MOUSE.ROTATE, MIDDLE: import_three18.MOUSE.DOLLY, RIGHT: import_three18.MOUSE.PAN };
5865
+ this.touches = { ONE: import_three18.TOUCH.ROTATE, TWO: import_three18.TOUCH.DOLLY_PAN };
5866
+ this.target0 = this.target.clone();
5867
+ this.position0 = this.object.position.clone();
5868
+ this.zoom0 = this.object.zoom;
5869
+ this._domElementKeyEvents = null;
5870
+ this.getPolarAngle = function() {
5871
+ return spherical.phi;
5557
5872
  };
5558
- this.options = (0, import_ts_deepmerge10.default)({}, _Renderer.DEFAULT_OPTIONS, options ?? {});
5559
- this._animationLoop = this.animate.bind(this);
5560
- this._fpsTimer = this.options.render.fpsLimit > 0 ? 1e3 / this.options.render.fpsLimit : void 0;
5561
- this._scene = this.createScene();
5562
- this._camera = this.createCamera();
5563
- this._renderer = this.createRenderer();
5564
- this._composer = this.createComposer();
5565
- if (this.options.render.stats) {
5566
- this._stats = new import_stats.default();
5567
- document.body.appendChild(this._stats.dom);
5568
- }
5569
- this.init();
5570
- }
5571
- //<editor-fold desc="INIT">
5572
- createScene() {
5573
- return new MineRenderScene();
5574
- }
5575
- createCamera() {
5576
- switch (this.options.camera.type) {
5577
- case "perspective":
5578
- default:
5579
- return new import_three18.PerspectiveCamera(
5580
- this.options.camera.perspective.fov,
5581
- this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
5582
- this.options.camera.near,
5583
- this.options.camera.far
5584
- );
5585
- case "orthographic":
5586
- return new import_three18.OrthographicCamera(
5587
- this.options.camera.orthographic.left ?? this.viewWidth / -2,
5588
- this.options.camera.orthographic.right ?? this.viewWidth / 2,
5589
- this.options.camera.orthographic.top ?? this.viewHeight / 2,
5590
- this.options.camera.orthographic.bottom ?? this.viewHeight / -2,
5591
- this.options.camera.near,
5592
- this.options.camera.far
5593
- );
5594
- }
5595
- }
5596
- createRenderer() {
5597
- const renderer = new import_three18.WebGLRenderer({
5598
- antialias: this.options.render.antialias,
5599
- alpha: true,
5600
- powerPreference: "high-performance",
5601
- depth: true
5602
- });
5603
- renderer.setClearColor(0, 0);
5604
- renderer.shadowMap.enabled = true;
5605
- renderer.shadowMap.type = import_three18.PCFSoftShadowMap;
5606
- renderer.outputEncoding = import_three18.LinearEncoding;
5607
- renderer.setSize(this.viewWidth, this.viewHeight);
5608
- return renderer;
5609
- }
5610
- createComposer() {
5611
- const composer = new import_postprocessing.EffectComposer(this.renderer);
5612
- if (!this.options.composer.enabled) return composer;
5613
- composer.setSize(this.viewWidth, this.viewHeight);
5614
- composer.addPass(new import_postprocessing.RenderPass(this.scene, this.camera));
5615
- return composer;
5616
- }
5617
- //</editor-fold>
5618
- init() {
5619
- if (this._disposed) return;
5620
- if (typeof window["__THREE_DEVTOOLS__"] !== "undefined") {
5621
- window["__THREE_DEVTOOLS__"].dispatchEvent(new CustomEvent("observe", { detail: this.scene }));
5622
- }
5623
- if (this.options.debug.grid) {
5624
- const gridHelper = new import_three18.GridHelper(128, 16);
5625
- this._debugHelpers.push(gridHelper);
5626
- this.scene.add(gridHelper);
5627
- const gridHelper2 = new import_three18.GridHelper(128, 16);
5628
- this._debugHelpers.push(gridHelper2);
5629
- gridHelper2.rotation.x = 90 * (Math.PI / 180);
5630
- this.scene.add(gridHelper2);
5631
- const gridHelper3 = new import_three18.GridHelper(128, 16);
5632
- this._debugHelpers.push(gridHelper3);
5633
- gridHelper3.rotation.z = 90 * (Math.PI / 180);
5634
- this.scene.add(gridHelper3);
5635
- }
5636
- if (this.options.debug.axes) {
5637
- const axesHelper = new import_three18.AxesHelper(64);
5638
- this._debugHelpers.push(axesHelper);
5639
- this.scene.add(axesHelper);
5640
- }
5641
- if (this.options.camera.position) {
5642
- if (isVector3(this.options.camera.position)) {
5643
- this.camera.position.set(this.options.camera.position.x, this.options.camera.position.y, this.options.camera.position.z);
5644
- } else if (isTripleArray(this.options.camera.position)) {
5645
- this.camera.position.set(this.options.camera.position[0], this.options.camera.position[1], this.options.camera.position[2]);
5646
- }
5647
- }
5648
- if (this.options.camera.lookingAt) {
5649
- if (isVector3(this.options.camera.lookingAt)) {
5650
- this.camera.lookAt(this.options.camera.lookingAt);
5651
- } else if (isTripleArray(this.options.camera.lookingAt)) {
5652
- this.camera.lookAt(this.options.camera.lookingAt[0], this.options.camera.lookingAt[1], this.options.camera.lookingAt[2]);
5653
- }
5654
- }
5655
- if (this.options.render.autoResize && !this._resizeListener) {
5656
- this._resizeListener = () => {
5657
- this.resize(this.viewWidth, this.viewHeight);
5658
- };
5659
- window.addEventListener("resize", this._resizeListener);
5660
- }
5661
- }
5662
- get element() {
5663
- return this._element;
5664
- }
5665
- appendTo(element) {
5666
- if (this._disposed) return;
5667
- this._element = element;
5668
- this._element.appendChild(this.renderer.domElement);
5669
- if (this.viewWidth == 0) {
5670
- console.warn("0 element width");
5671
- }
5672
- if (this.viewHeight == 0) {
5673
- console.warn("0 element height");
5674
- }
5675
- this.resize(this.viewWidth, this.viewHeight);
5676
- }
5677
- /**
5678
- * Redraws when the dispatcher emits the selected event. Registering the same pair twice has no effect.
5679
- * The renderer removes its listener on disposal; the caller retains ownership of the dispatcher.
5680
- */
5681
- registerEventDispatcher(dispatcher, changeEvent2 = "change") {
5682
- if (this._disposed) return;
5683
- let events = this._eventDispatchers.get(dispatcher);
5684
- if (!events) {
5685
- events = /* @__PURE__ */ new Set();
5686
- this._eventDispatchers.set(dispatcher, events);
5687
- }
5688
- if (events.has(changeEvent2)) return;
5689
- events.add(changeEvent2);
5690
- dispatcher.addEventListener(changeEvent2, this._changeListener);
5691
- }
5692
- resize(width, height) {
5693
- if (this._disposed) return;
5694
- if (isPerspectiveCamera(this.camera)) {
5695
- this.camera.aspect = width / height;
5696
- this.camera.updateProjectionMatrix();
5697
- } else if (isOrthographicCamera(this.camera)) {
5698
- this.camera.left = width / -2;
5699
- this.camera.right = width / 2;
5700
- this.camera.top = height / 2;
5701
- this.camera.bottom = height / -2;
5702
- this.camera.updateProjectionMatrix();
5873
+ this.getAzimuthalAngle = function() {
5874
+ return spherical.theta;
5875
+ };
5876
+ this.getDistance = function() {
5877
+ return this.object.position.distanceTo(this.target);
5878
+ };
5879
+ this.saveState = function() {
5880
+ scope.target0.copy(scope.target);
5881
+ scope.position0.copy(scope.object.position);
5882
+ scope.zoom0 = scope.object.zoom;
5883
+ };
5884
+ this.reset = function() {
5885
+ scope.target.copy(scope.target0);
5886
+ scope.object.position.copy(scope.position0);
5887
+ scope.object.zoom = scope.zoom0;
5888
+ scope.object.updateProjectionMatrix();
5889
+ scope.dispatchEvent(_changeEvent);
5890
+ scope.update();
5891
+ state = STATE.NONE;
5892
+ };
5893
+ this.update = function() {
5894
+ const offset = new import_three18.Vector3();
5895
+ const quat = new import_three18.Quaternion().setFromUnitVectors(object.up, new import_three18.Vector3(0, 1, 0));
5896
+ const quatInverse = quat.clone().invert();
5897
+ const lastPosition = new import_three18.Vector3();
5898
+ const lastQuaternion = new import_three18.Quaternion();
5899
+ const twoPI = 2 * Math.PI;
5900
+ return function update() {
5901
+ const position = scope.object.position;
5902
+ offset.copy(position).sub(scope.target);
5903
+ offset.applyQuaternion(quat);
5904
+ spherical.setFromVector3(offset);
5905
+ if (scope.autoRotate && state === STATE.NONE) {
5906
+ rotateLeft(getAutoRotationAngle());
5907
+ }
5908
+ if (scope.enableDamping) {
5909
+ spherical.theta += sphericalDelta.theta * scope.dampingFactor;
5910
+ spherical.phi += sphericalDelta.phi * scope.dampingFactor;
5911
+ } else {
5912
+ spherical.theta += sphericalDelta.theta;
5913
+ spherical.phi += sphericalDelta.phi;
5914
+ }
5915
+ let min = scope.minAzimuthAngle;
5916
+ let max = scope.maxAzimuthAngle;
5917
+ if (isFinite(min) && isFinite(max)) {
5918
+ if (min < -Math.PI) min += twoPI;
5919
+ else if (min > Math.PI) min -= twoPI;
5920
+ if (max < -Math.PI) max += twoPI;
5921
+ else if (max > Math.PI) max -= twoPI;
5922
+ if (min <= max) {
5923
+ spherical.theta = Math.max(min, Math.min(max, spherical.theta));
5924
+ } else {
5925
+ spherical.theta = spherical.theta > (min + max) / 2 ? Math.max(min, spherical.theta) : Math.min(max, spherical.theta);
5926
+ }
5927
+ }
5928
+ spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
5929
+ spherical.makeSafe();
5930
+ spherical.radius *= scale;
5931
+ spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));
5932
+ if (scope.enableDamping === true) {
5933
+ scope.target.addScaledVector(panOffset, scope.dampingFactor);
5934
+ } else {
5935
+ scope.target.add(panOffset);
5936
+ }
5937
+ offset.setFromSpherical(spherical);
5938
+ offset.applyQuaternion(quatInverse);
5939
+ position.copy(scope.target).add(offset);
5940
+ scope.object.lookAt(scope.target);
5941
+ if (scope.enableDamping === true) {
5942
+ sphericalDelta.theta *= 1 - scope.dampingFactor;
5943
+ sphericalDelta.phi *= 1 - scope.dampingFactor;
5944
+ panOffset.multiplyScalar(1 - scope.dampingFactor);
5945
+ } else {
5946
+ sphericalDelta.set(0, 0, 0);
5947
+ panOffset.set(0, 0, 0);
5948
+ }
5949
+ scale = 1;
5950
+ if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
5951
+ scope.dispatchEvent(_changeEvent);
5952
+ lastPosition.copy(scope.object.position);
5953
+ lastQuaternion.copy(scope.object.quaternion);
5954
+ zoomChanged = false;
5955
+ return true;
5956
+ }
5957
+ return false;
5958
+ };
5959
+ }();
5960
+ this.dispose = function() {
5961
+ scope.domElement.removeEventListener("contextmenu", onContextMenu);
5962
+ scope.domElement.removeEventListener("pointerdown", onPointerDown);
5963
+ scope.domElement.removeEventListener("pointercancel", onPointerCancel);
5964
+ scope.domElement.removeEventListener("wheel", onMouseWheel);
5965
+ scope.domElement.removeEventListener("pointermove", onPointerMove);
5966
+ scope.domElement.removeEventListener("pointerup", onPointerUp);
5967
+ if (scope._domElementKeyEvents !== null) {
5968
+ scope._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
5969
+ }
5970
+ };
5971
+ const scope = this;
5972
+ const STATE = {
5973
+ NONE: -1,
5974
+ ROTATE: 0,
5975
+ DOLLY: 1,
5976
+ PAN: 2,
5977
+ TOUCH_ROTATE: 3,
5978
+ TOUCH_PAN: 4,
5979
+ TOUCH_DOLLY_PAN: 5,
5980
+ TOUCH_DOLLY_ROTATE: 6
5981
+ };
5982
+ let state = STATE.NONE;
5983
+ const EPS = 1e-6;
5984
+ const spherical = new import_three18.Spherical();
5985
+ const sphericalDelta = new import_three18.Spherical();
5986
+ let scale = 1;
5987
+ const panOffset = new import_three18.Vector3();
5988
+ let zoomChanged = false;
5989
+ const rotateStart = new import_three18.Vector2();
5990
+ const rotateEnd = new import_three18.Vector2();
5991
+ const rotateDelta = new import_three18.Vector2();
5992
+ const panStart = new import_three18.Vector2();
5993
+ const panEnd = new import_three18.Vector2();
5994
+ const panDelta = new import_three18.Vector2();
5995
+ const dollyStart = new import_three18.Vector2();
5996
+ const dollyEnd = new import_three18.Vector2();
5997
+ const dollyDelta = new import_three18.Vector2();
5998
+ const pointers = [];
5999
+ const pointerPositions = {};
6000
+ function getAutoRotationAngle() {
6001
+ return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
5703
6002
  }
5704
- this.renderer.setSize(width, height);
5705
- this.composer.setSize(width, height);
5706
- this._dirty = true;
5707
- }
5708
- //<editor-fold desc="RENDER">
5709
- get dirty() {
5710
- return this._dirty || this.scene.dirty;
5711
- }
5712
- set dirty(dirty) {
5713
- this._dirty = dirty;
5714
- this.scene.dirty = dirty;
5715
- }
5716
- start() {
5717
- if (this._disposed) return;
5718
- this.stop();
5719
- this.renderer.setAnimationLoop(this._animationLoop);
5720
- }
5721
- stop() {
5722
- if (this._disposed) return;
5723
- this.renderer.setAnimationLoop(null);
5724
- if (this._animationTimer)
5725
- clearTimeout(this._animationTimer);
5726
- this._animationTimer = void 0;
5727
- if (this._animationFrame)
5728
- cancelAnimationFrame(this._animationFrame);
5729
- this._animationFrame = void 0;
5730
- }
5731
- /**
5732
- * Stops rendering and releases owned resources. Repeated calls have no effect, and a disposed
5733
- * renderer cannot be restarted. Scene objects are detached; shared assets and caller-owned
5734
- * controls must be managed by their owners.
5735
- */
5736
- dispose() {
5737
- if (this._disposed) return;
5738
- this.stop();
5739
- this._disposed = true;
5740
- if (this._resizeListener) {
5741
- window.removeEventListener("resize", this._resizeListener);
5742
- this._resizeListener = void 0;
6003
+ function getZoomScale() {
6004
+ return Math.pow(0.95, scope.zoomSpeed);
5743
6005
  }
5744
- for (const [dispatcher, events] of this._eventDispatchers) {
5745
- for (const event of events) {
5746
- dispatcher.removeEventListener(event, this._changeListener);
5747
- }
6006
+ function rotateLeft(angle) {
6007
+ sphericalDelta.theta -= angle;
5748
6008
  }
5749
- this._eventDispatchers.clear();
5750
- this._stats?.dom.remove();
5751
- this._stats = void 0;
5752
- this.renderer.domElement.remove();
5753
- this._element = void 0;
5754
- this.scene.clear();
5755
- for (const helper of this._debugHelpers) {
5756
- helper.geometry.dispose();
5757
- const materials = Array.isArray(helper.material) ? helper.material : [helper.material];
5758
- for (const material of materials) {
5759
- material.dispose();
5760
- }
6009
+ function rotateUp(angle) {
6010
+ sphericalDelta.phi -= angle;
5761
6011
  }
5762
- this._debugHelpers.length = 0;
5763
- this.composer.dispose();
5764
- this.renderer.dispose();
5765
- this.renderer.forceContextLoss();
5766
- }
5767
- animate(t) {
5768
- if (this._disposed) return;
5769
- if (this._stats) {
5770
- this._stats.begin();
6012
+ const panLeft = function() {
6013
+ const v = new import_three18.Vector3();
6014
+ return function panLeft2(distance, objectMatrix) {
6015
+ v.setFromMatrixColumn(objectMatrix, 0);
6016
+ v.multiplyScalar(-distance);
6017
+ panOffset.add(v);
6018
+ };
6019
+ }();
6020
+ const panUp = function() {
6021
+ const v = new import_three18.Vector3();
6022
+ return function panUp2(distance, objectMatrix) {
6023
+ if (scope.screenSpacePanning === true) {
6024
+ v.setFromMatrixColumn(objectMatrix, 1);
6025
+ } else {
6026
+ v.setFromMatrixColumn(objectMatrix, 0);
6027
+ v.crossVectors(scope.object.up, v);
6028
+ }
6029
+ v.multiplyScalar(distance);
6030
+ panOffset.add(v);
6031
+ };
6032
+ }();
6033
+ const pan = function() {
6034
+ const offset = new import_three18.Vector3();
6035
+ return function pan2(deltaX, deltaY) {
6036
+ const element = scope.domElement;
6037
+ if (scope.object.isPerspectiveCamera) {
6038
+ const position = scope.object.position;
6039
+ offset.copy(position).sub(scope.target);
6040
+ let targetDistance = offset.length();
6041
+ targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180);
6042
+ panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
6043
+ panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);
6044
+ } else if (scope.object.isOrthographicCamera) {
6045
+ panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);
6046
+ panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);
6047
+ } else {
6048
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.");
6049
+ scope.enablePan = false;
6050
+ }
6051
+ };
6052
+ }();
6053
+ function dollyOut(dollyScale) {
6054
+ if (scope.object.isPerspectiveCamera) {
6055
+ scale /= dollyScale;
6056
+ } else if (scope.object.isOrthographicCamera) {
6057
+ scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
6058
+ scope.object.updateProjectionMatrix();
6059
+ zoomChanged = true;
6060
+ } else {
6061
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
6062
+ scope.enableZoom = false;
6063
+ }
5771
6064
  }
5772
- if (this.dirty || this.options.render.renderAlways) {
5773
- if (this.options.composer.enabled) {
5774
- this.composer.render();
6065
+ function dollyIn(dollyScale) {
6066
+ if (scope.object.isPerspectiveCamera) {
6067
+ scale *= dollyScale;
6068
+ } else if (scope.object.isOrthographicCamera) {
6069
+ scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
6070
+ scope.object.updateProjectionMatrix();
6071
+ zoomChanged = true;
5775
6072
  } else {
5776
- this.renderer.render(this.scene, this.camera);
6073
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
6074
+ scope.enableZoom = false;
5777
6075
  }
5778
6076
  }
5779
- this.dirty = false;
5780
- if (this._stats) {
5781
- this._stats.end();
6077
+ function handleMouseDownRotate(event) {
6078
+ rotateStart.set(event.clientX, event.clientY);
5782
6079
  }
5783
- }
5784
- //</editor-fold>
5785
- toImage() {
5786
- return this.renderer.domElement.toDataURL();
5787
- }
5788
- ///
5789
- get attachedToBody() {
5790
- return this.element === document.body;
5791
- }
5792
- get viewWidth() {
5793
- return this.attachedToBody ? window.innerWidth : this.element?.offsetWidth || 0;
5794
- }
5795
- get viewHeight() {
5796
- return this.attachedToBody ? window.innerHeight : this.element?.offsetHeight || 0;
5797
- }
5798
- get scene() {
5799
- return this._scene;
5800
- }
5801
- get camera() {
5802
- return this._camera;
5803
- }
5804
- get renderer() {
5805
- return this._renderer;
5806
- }
5807
- get composer() {
5808
- return this._composer;
5809
- }
5810
- ///
5811
- };
5812
- _Renderer.DEFAULT_OPTIONS = (0, import_ts_deepmerge10.default)({}, {
5813
- camera: {
5814
- type: "perspective",
5815
- near: 1,
5816
- far: 5e3,
5817
- perspective: {
5818
- aspect: void 0,
5819
- fov: 50
5820
- },
5821
- orthographic: {
5822
- left: void 0,
5823
- right: void 0,
5824
- top: void 0,
5825
- bottom: void 0
5826
- },
5827
- position: new import_three18.Vector3(50, 50, 50),
5828
- lookingAt: new import_three18.Vector3(0, 0, 0)
5829
- },
5830
- render: {
5831
- fpsLimit: 60,
5832
- stats: false,
5833
- antialias: true,
5834
- shade: true,
5835
- autoResize: true,
5836
- renderAlways: false
5837
- },
5838
- composer: {
5839
- enabled: true
5840
- },
5841
- debug: {
5842
- grid: false,
5843
- axes: false
5844
- }
5845
- });
5846
- var Renderer = _Renderer;
5847
-
5848
- // src/skin/Skins.ts
5849
- var Skins = class {
5850
- //<editor-fold desc="Skins">
5851
- static async fromUuidOrUsername(uuidOrUsername) {
5852
- if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
5853
- return this.fromUuid(uuidOrUsername);
6080
+ function handleMouseDownDolly(event) {
6081
+ dollyStart.set(event.clientX, event.clientY);
5854
6082
  }
5855
- return this.fromUsername(uuidOrUsername);
5856
- }
5857
- static async fromUuid(uuid) {
5858
- return this.getSkinProxySkinUrl(uuid);
5859
- }
5860
- static async fromUsername(username) {
5861
- return this.usernameToUuid(username).then((uuid) => {
5862
- if (uuid) {
5863
- return this.fromUuid(uuid);
6083
+ function handleMouseDownPan(event) {
6084
+ panStart.set(event.clientX, event.clientY);
6085
+ }
6086
+ function handleMouseMoveRotate(event) {
6087
+ rotateEnd.set(event.clientX, event.clientY);
6088
+ rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
6089
+ const element = scope.domElement;
6090
+ rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
6091
+ rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
6092
+ rotateStart.copy(rotateEnd);
6093
+ scope.update();
6094
+ }
6095
+ function handleMouseMoveDolly(event) {
6096
+ dollyEnd.set(event.clientX, event.clientY);
6097
+ dollyDelta.subVectors(dollyEnd, dollyStart);
6098
+ if (dollyDelta.y > 0) {
6099
+ dollyOut(getZoomScale());
6100
+ } else if (dollyDelta.y < 0) {
6101
+ dollyIn(getZoomScale());
5864
6102
  }
5865
- return void 0;
5866
- });
5867
- }
5868
- static async fromMineSkin(mineskinId) {
5869
- return this.getMineSkin(mineskinId).then((mineskin) => {
5870
- if (mineskin) {
5871
- return mineskin["data"]["texture"]["value"]["urls"]["skins"];
6103
+ dollyStart.copy(dollyEnd);
6104
+ scope.update();
6105
+ }
6106
+ function handleMouseMovePan(event) {
6107
+ panEnd.set(event.clientX, event.clientY);
6108
+ panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
6109
+ pan(panDelta.x, panDelta.y);
6110
+ panStart.copy(panEnd);
6111
+ scope.update();
6112
+ }
6113
+ function handleMouseUp() {
6114
+ }
6115
+ function handleMouseWheel(event) {
6116
+ if (event.deltaY < 0) {
6117
+ dollyIn(getZoomScale());
6118
+ } else if (event.deltaY > 0) {
6119
+ dollyOut(getZoomScale());
5872
6120
  }
5873
- return void 0;
5874
- });
5875
- }
5876
- //</editor-fold>
5877
- //<editor-fold desc="Capes">
5878
- static async capeFromUuidOrUsername(uuidOrUsername) {
5879
- if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
5880
- return this.capeFromUuid(uuidOrUsername);
6121
+ scope.update();
5881
6122
  }
5882
- return this.capeFromUsername(uuidOrUsername);
5883
- }
5884
- static async capeFromUuid(uuid) {
5885
- return this.getSkinProxyCapeUrl(uuid);
5886
- }
5887
- static async capeFromUsername(username) {
5888
- return this.usernameToUuid(username).then((uuid) => {
5889
- if (uuid) {
5890
- return this.capeFromUuid(uuid);
6123
+ function handleKeyDown(event) {
6124
+ let needsUpdate = false;
6125
+ switch (event.code) {
6126
+ case scope.keys.UP:
6127
+ pan(0, scope.keyPanSpeed);
6128
+ needsUpdate = true;
6129
+ break;
6130
+ case scope.keys.BOTTOM:
6131
+ pan(0, -scope.keyPanSpeed);
6132
+ needsUpdate = true;
6133
+ break;
6134
+ case scope.keys.LEFT:
6135
+ pan(scope.keyPanSpeed, 0);
6136
+ needsUpdate = true;
6137
+ break;
6138
+ case scope.keys.RIGHT:
6139
+ pan(-scope.keyPanSpeed, 0);
6140
+ needsUpdate = true;
6141
+ break;
5891
6142
  }
5892
- return void 0;
5893
- });
5894
- }
5895
- static async capeFromCapesDev(uuid, capeType = "minecraft") {
5896
- return this.getCapesDev(uuid, capeType).then((cape) => {
5897
- if (cape) {
5898
- return cape?.stillImageUrl;
6143
+ if (needsUpdate) {
6144
+ event.preventDefault();
6145
+ scope.update();
5899
6146
  }
5900
- return void 0;
5901
- });
5902
- }
5903
- //</editor-fold>
5904
- //<editor-fold desc="Helpers">
5905
- static async usernameToUuid(username) {
5906
- return this.usernameToUuidSkinProxy(username);
5907
- }
5908
- static async usernameToUuidSkinProxy(username) {
5909
- return Requests.genericRequest({
5910
- baseURL: "https://minecraft-skin-proxy.inventive.workers.dev",
5911
- url: "/uuid/" + username
5912
- }).then((res) => {
5913
- if (res.status === 200) {
5914
- return res.data["id"];
6147
+ }
6148
+ function handleTouchStartRotate() {
6149
+ if (pointers.length === 1) {
6150
+ rotateStart.set(pointers[0].pageX, pointers[0].pageY);
6151
+ } else {
6152
+ const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
6153
+ const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
6154
+ rotateStart.set(x, y);
5915
6155
  }
5916
- return void 0;
5917
- }).catch((err) => {
5918
- console.warn(err);
5919
- return void 0;
5920
- });
5921
- }
5922
- static async usernameToUuidMineTools(username) {
5923
- return Requests.genericRequest({
5924
- baseURL: "https://api.minetools.eu",
5925
- url: "/uuid/" + username
5926
- }).then((res) => {
5927
- if (res.status === 200) {
5928
- return res.data["id"];
6156
+ }
6157
+ function handleTouchStartPan() {
6158
+ if (pointers.length === 1) {
6159
+ panStart.set(pointers[0].pageX, pointers[0].pageY);
6160
+ } else {
6161
+ const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
6162
+ const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
6163
+ panStart.set(x, y);
5929
6164
  }
5930
- return void 0;
5931
- }).catch((err) => {
5932
- console.warn(err);
5933
- return void 0;
5934
- });
5935
- }
5936
- static async getProfileFromMinetools(uuid) {
5937
- return Requests.genericRequest({
5938
- baseURL: "https://api.minetools.eu",
5939
- url: "/profile/" + uuid
5940
- }).then((res) => {
5941
- if (res.status === 200) {
5942
- return res.data;
6165
+ }
6166
+ function handleTouchStartDolly() {
6167
+ const dx = pointers[0].pageX - pointers[1].pageX;
6168
+ const dy = pointers[0].pageY - pointers[1].pageY;
6169
+ const distance = Math.sqrt(dx * dx + dy * dy);
6170
+ dollyStart.set(0, distance);
6171
+ }
6172
+ function handleTouchStartDollyPan() {
6173
+ if (scope.enableZoom) handleTouchStartDolly();
6174
+ if (scope.enablePan) handleTouchStartPan();
6175
+ }
6176
+ function handleTouchStartDollyRotate() {
6177
+ if (scope.enableZoom) handleTouchStartDolly();
6178
+ if (scope.enableRotate) handleTouchStartRotate();
6179
+ }
6180
+ function handleTouchMoveRotate(event) {
6181
+ if (pointers.length == 1) {
6182
+ rotateEnd.set(event.pageX, event.pageY);
6183
+ } else {
6184
+ const position = getSecondPointerPosition(event);
6185
+ const x = 0.5 * (event.pageX + position.x);
6186
+ const y = 0.5 * (event.pageY + position.y);
6187
+ rotateEnd.set(x, y);
5943
6188
  }
5944
- });
5945
- }
5946
- static async getMineSkin(mineskinId) {
5947
- return Requests.genericRequest({
5948
- baseURL: "https://api.mineskin.org",
5949
- url: "/get/uuid/" + mineskinId
5950
- }).then((res) => {
5951
- if (res.status === 200) {
5952
- return res.data;
6189
+ rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
6190
+ const element = scope.domElement;
6191
+ rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
6192
+ rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
6193
+ rotateStart.copy(rotateEnd);
6194
+ }
6195
+ function handleTouchMovePan(event) {
6196
+ if (pointers.length === 1) {
6197
+ panEnd.set(event.pageX, event.pageY);
6198
+ } else {
6199
+ const position = getSecondPointerPosition(event);
6200
+ const x = 0.5 * (event.pageX + position.x);
6201
+ const y = 0.5 * (event.pageY + position.y);
6202
+ panEnd.set(x, y);
5953
6203
  }
5954
- return void 0;
5955
- }).catch((err) => {
5956
- console.warn(err);
5957
- return void 0;
5958
- });
5959
- }
5960
- static async getCapesDev(uuid, type = "all") {
5961
- return Requests.genericRequest({
5962
- baseURL: "https://api.capes.dev",
5963
- url: "/load/" + uuid + "/" + type
5964
- }).then((res) => {
5965
- if (res.status === 200) {
5966
- return res.data;
6204
+ panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
6205
+ pan(panDelta.x, panDelta.y);
6206
+ panStart.copy(panEnd);
6207
+ }
6208
+ function handleTouchMoveDolly(event) {
6209
+ const position = getSecondPointerPosition(event);
6210
+ const dx = event.pageX - position.x;
6211
+ const dy = event.pageY - position.y;
6212
+ const distance = Math.sqrt(dx * dx + dy * dy);
6213
+ dollyEnd.set(0, distance);
6214
+ dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed));
6215
+ dollyOut(dollyDelta.y);
6216
+ dollyStart.copy(dollyEnd);
6217
+ }
6218
+ function handleTouchMoveDollyPan(event) {
6219
+ if (scope.enableZoom) handleTouchMoveDolly(event);
6220
+ if (scope.enablePan) handleTouchMovePan(event);
6221
+ }
6222
+ function handleTouchMoveDollyRotate(event) {
6223
+ if (scope.enableZoom) handleTouchMoveDolly(event);
6224
+ if (scope.enableRotate) handleTouchMoveRotate(event);
6225
+ }
6226
+ function handleTouchEnd() {
6227
+ }
6228
+ function onPointerDown(event) {
6229
+ if (scope.enabled === false) return;
6230
+ if (pointers.length === 0) {
6231
+ scope.domElement.setPointerCapture(event.pointerId);
6232
+ scope.domElement.addEventListener("pointermove", onPointerMove);
6233
+ scope.domElement.addEventListener("pointerup", onPointerUp);
5967
6234
  }
5968
- return void 0;
5969
- }).catch((err) => {
5970
- console.warn(err);
5971
- return void 0;
5972
- });
5973
- }
5974
- static getCrafatarSkinUrl(uuid) {
5975
- return "https://crafatar.com/skins/" + uuid;
5976
- }
5977
- static getCrafatarCapeUrl(uuid) {
5978
- return "https://crafatar.com/capes/" + uuid;
5979
- }
5980
- static getMcHeadsSkinUrl(uuid) {
5981
- return "https://mc-heads.net/skin/" + uuid;
5982
- }
5983
- static getMineSkinPlayerSkinUrl(uuid) {
5984
- return "https://mineskin.org/skin/player/" + uuid;
5985
- }
5986
- static getSkinProxySkinUrl(uuid) {
5987
- return "https://minecraft-skin-proxy.inventive.workers.dev/skin/" + uuid;
5988
- }
5989
- static getSkinProxyCapeUrl(uuid) {
5990
- return "https://minecraft-skin-proxy.inventive.workers.dev/cape/" + uuid;
5991
- }
5992
- //</editor-fold>
5993
- };
5994
-
5995
- // src/three/OrbitControls.js
5996
- var import_three20 = require("three");
5997
- var _changeEvent = { type: "change" };
5998
- var _startEvent = { type: "start" };
5999
- var _endEvent = { type: "end" };
6000
- var OrbitControls = class extends import_three20.EventDispatcher {
6001
- constructor(object, domElement) {
6002
- super();
6003
- if (domElement === void 0) console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.');
6004
- if (domElement === document) console.error('THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.');
6005
- this.object = object;
6006
- this.domElement = domElement;
6007
- this.domElement.style.touchAction = "none";
6008
- this.enabled = true;
6009
- this.target = new import_three20.Vector3();
6010
- this.minDistance = 0;
6011
- this.maxDistance = Infinity;
6012
- this.minZoom = 0;
6013
- this.maxZoom = Infinity;
6014
- this.minPolarAngle = 0;
6015
- this.maxPolarAngle = Math.PI;
6016
- this.minAzimuthAngle = -Infinity;
6017
- this.maxAzimuthAngle = Infinity;
6018
- this.enableDamping = false;
6019
- this.dampingFactor = 0.05;
6020
- this.enableZoom = true;
6021
- this.zoomSpeed = 1;
6022
- this.enableRotate = true;
6023
- this.rotateSpeed = 1;
6024
- this.enablePan = true;
6025
- this.panSpeed = 1;
6026
- this.screenSpacePanning = true;
6027
- this.keyPanSpeed = 7;
6028
- this.autoRotate = false;
6029
- this.autoRotateSpeed = 2;
6030
- this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" };
6031
- this.mouseButtons = { LEFT: import_three20.MOUSE.ROTATE, MIDDLE: import_three20.MOUSE.DOLLY, RIGHT: import_three20.MOUSE.PAN };
6032
- this.touches = { ONE: import_three20.TOUCH.ROTATE, TWO: import_three20.TOUCH.DOLLY_PAN };
6033
- this.target0 = this.target.clone();
6034
- this.position0 = this.object.position.clone();
6035
- this.zoom0 = this.object.zoom;
6036
- this._domElementKeyEvents = null;
6037
- this.getPolarAngle = function() {
6038
- return spherical.phi;
6039
- };
6040
- this.getAzimuthalAngle = function() {
6041
- return spherical.theta;
6042
- };
6043
- this.getDistance = function() {
6044
- return this.object.position.distanceTo(this.target);
6045
- };
6046
- this.saveState = function() {
6047
- scope.target0.copy(scope.target);
6048
- scope.position0.copy(scope.object.position);
6049
- scope.zoom0 = scope.object.zoom;
6050
- };
6051
- this.reset = function() {
6052
- scope.target.copy(scope.target0);
6053
- scope.object.position.copy(scope.position0);
6054
- scope.object.zoom = scope.zoom0;
6055
- scope.object.updateProjectionMatrix();
6056
- scope.dispatchEvent(_changeEvent);
6057
- scope.update();
6058
- state = STATE.NONE;
6059
- };
6060
- this.update = function() {
6061
- const offset = new import_three20.Vector3();
6062
- const quat = new import_three20.Quaternion().setFromUnitVectors(object.up, new import_three20.Vector3(0, 1, 0));
6063
- const quatInverse = quat.clone().invert();
6064
- const lastPosition = new import_three20.Vector3();
6065
- const lastQuaternion = new import_three20.Quaternion();
6066
- const twoPI = 2 * Math.PI;
6067
- return function update() {
6068
- const position = scope.object.position;
6069
- offset.copy(position).sub(scope.target);
6070
- offset.applyQuaternion(quat);
6071
- spherical.setFromVector3(offset);
6072
- if (scope.autoRotate && state === STATE.NONE) {
6073
- rotateLeft(getAutoRotationAngle());
6074
- }
6075
- if (scope.enableDamping) {
6076
- spherical.theta += sphericalDelta.theta * scope.dampingFactor;
6077
- spherical.phi += sphericalDelta.phi * scope.dampingFactor;
6078
- } else {
6079
- spherical.theta += sphericalDelta.theta;
6080
- spherical.phi += sphericalDelta.phi;
6081
- }
6082
- let min = scope.minAzimuthAngle;
6083
- let max = scope.maxAzimuthAngle;
6084
- if (isFinite(min) && isFinite(max)) {
6085
- if (min < -Math.PI) min += twoPI;
6086
- else if (min > Math.PI) min -= twoPI;
6087
- if (max < -Math.PI) max += twoPI;
6088
- else if (max > Math.PI) max -= twoPI;
6089
- if (min <= max) {
6090
- spherical.theta = Math.max(min, Math.min(max, spherical.theta));
6235
+ addPointer(event);
6236
+ if (event.pointerType === "touch") {
6237
+ onTouchStart(event);
6238
+ } else {
6239
+ onMouseDown(event);
6240
+ }
6241
+ }
6242
+ function onPointerMove(event) {
6243
+ if (scope.enabled === false) return;
6244
+ if (event.pointerType === "touch") {
6245
+ onTouchMove(event);
6246
+ } else {
6247
+ onMouseMove(event);
6248
+ }
6249
+ }
6250
+ function onPointerUp(event) {
6251
+ if (scope.enabled === false) return;
6252
+ if (event.pointerType === "touch") {
6253
+ onTouchEnd();
6254
+ } else {
6255
+ onMouseUp(event);
6256
+ }
6257
+ removePointer(event);
6258
+ if (pointers.length === 0) {
6259
+ scope.domElement.releasePointerCapture(event.pointerId);
6260
+ scope.domElement.removeEventListener("pointermove", onPointerMove);
6261
+ scope.domElement.removeEventListener("pointerup", onPointerUp);
6262
+ }
6263
+ }
6264
+ function onPointerCancel(event) {
6265
+ removePointer(event);
6266
+ }
6267
+ function onMouseDown(event) {
6268
+ let mouseAction;
6269
+ switch (event.button) {
6270
+ case 0:
6271
+ mouseAction = scope.mouseButtons.LEFT;
6272
+ break;
6273
+ case 1:
6274
+ mouseAction = scope.mouseButtons.MIDDLE;
6275
+ break;
6276
+ case 2:
6277
+ mouseAction = scope.mouseButtons.RIGHT;
6278
+ break;
6279
+ default:
6280
+ mouseAction = -1;
6281
+ }
6282
+ switch (mouseAction) {
6283
+ case import_three18.MOUSE.DOLLY:
6284
+ if (scope.enableZoom === false) return;
6285
+ handleMouseDownDolly(event);
6286
+ state = STATE.DOLLY;
6287
+ break;
6288
+ case import_three18.MOUSE.ROTATE:
6289
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
6290
+ if (scope.enablePan === false) return;
6291
+ handleMouseDownPan(event);
6292
+ state = STATE.PAN;
6293
+ } else {
6294
+ if (scope.enableRotate === false) return;
6295
+ handleMouseDownRotate(event);
6296
+ state = STATE.ROTATE;
6297
+ }
6298
+ break;
6299
+ case import_three18.MOUSE.PAN:
6300
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
6301
+ if (scope.enableRotate === false) return;
6302
+ handleMouseDownRotate(event);
6303
+ state = STATE.ROTATE;
6091
6304
  } else {
6092
- spherical.theta = spherical.theta > (min + max) / 2 ? Math.max(min, spherical.theta) : Math.min(max, spherical.theta);
6305
+ if (scope.enablePan === false) return;
6306
+ handleMouseDownPan(event);
6307
+ state = STATE.PAN;
6093
6308
  }
6094
- }
6095
- spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
6096
- spherical.makeSafe();
6097
- spherical.radius *= scale;
6098
- spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));
6099
- if (scope.enableDamping === true) {
6100
- scope.target.addScaledVector(panOffset, scope.dampingFactor);
6101
- } else {
6102
- scope.target.add(panOffset);
6103
- }
6104
- offset.setFromSpherical(spherical);
6105
- offset.applyQuaternion(quatInverse);
6106
- position.copy(scope.target).add(offset);
6107
- scope.object.lookAt(scope.target);
6108
- if (scope.enableDamping === true) {
6109
- sphericalDelta.theta *= 1 - scope.dampingFactor;
6110
- sphericalDelta.phi *= 1 - scope.dampingFactor;
6111
- panOffset.multiplyScalar(1 - scope.dampingFactor);
6112
- } else {
6113
- sphericalDelta.set(0, 0, 0);
6114
- panOffset.set(0, 0, 0);
6115
- }
6116
- scale = 1;
6117
- if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
6118
- scope.dispatchEvent(_changeEvent);
6119
- lastPosition.copy(scope.object.position);
6120
- lastQuaternion.copy(scope.object.quaternion);
6121
- zoomChanged = false;
6122
- return true;
6123
- }
6124
- return false;
6125
- };
6126
- }();
6127
- this.dispose = function() {
6128
- scope.domElement.removeEventListener("contextmenu", onContextMenu);
6129
- scope.domElement.removeEventListener("pointerdown", onPointerDown);
6130
- scope.domElement.removeEventListener("pointercancel", onPointerCancel);
6131
- scope.domElement.removeEventListener("wheel", onMouseWheel);
6132
- scope.domElement.removeEventListener("pointermove", onPointerMove);
6133
- scope.domElement.removeEventListener("pointerup", onPointerUp);
6134
- if (scope._domElementKeyEvents !== null) {
6135
- scope._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
6309
+ break;
6310
+ default:
6311
+ state = STATE.NONE;
6312
+ }
6313
+ if (state !== STATE.NONE) {
6314
+ scope.dispatchEvent(_startEvent);
6136
6315
  }
6137
- };
6138
- const scope = this;
6139
- const STATE = {
6140
- NONE: -1,
6141
- ROTATE: 0,
6142
- DOLLY: 1,
6143
- PAN: 2,
6144
- TOUCH_ROTATE: 3,
6145
- TOUCH_PAN: 4,
6146
- TOUCH_DOLLY_PAN: 5,
6147
- TOUCH_DOLLY_ROTATE: 6
6148
- };
6149
- let state = STATE.NONE;
6150
- const EPS = 1e-6;
6151
- const spherical = new import_three20.Spherical();
6152
- const sphericalDelta = new import_three20.Spherical();
6153
- let scale = 1;
6154
- const panOffset = new import_three20.Vector3();
6155
- let zoomChanged = false;
6156
- const rotateStart = new import_three20.Vector2();
6157
- const rotateEnd = new import_three20.Vector2();
6158
- const rotateDelta = new import_three20.Vector2();
6159
- const panStart = new import_three20.Vector2();
6160
- const panEnd = new import_three20.Vector2();
6161
- const panDelta = new import_three20.Vector2();
6162
- const dollyStart = new import_three20.Vector2();
6163
- const dollyEnd = new import_three20.Vector2();
6164
- const dollyDelta = new import_three20.Vector2();
6165
- const pointers = [];
6166
- const pointerPositions = {};
6167
- function getAutoRotationAngle() {
6168
- return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
6169
6316
  }
6170
- function getZoomScale() {
6171
- return Math.pow(0.95, scope.zoomSpeed);
6317
+ function onMouseMove(event) {
6318
+ if (scope.enabled === false) return;
6319
+ switch (state) {
6320
+ case STATE.ROTATE:
6321
+ if (scope.enableRotate === false) return;
6322
+ handleMouseMoveRotate(event);
6323
+ break;
6324
+ case STATE.DOLLY:
6325
+ if (scope.enableZoom === false) return;
6326
+ handleMouseMoveDolly(event);
6327
+ break;
6328
+ case STATE.PAN:
6329
+ if (scope.enablePan === false) return;
6330
+ handleMouseMovePan(event);
6331
+ break;
6332
+ }
6172
6333
  }
6173
- function rotateLeft(angle) {
6174
- sphericalDelta.theta -= angle;
6334
+ function onMouseUp(event) {
6335
+ handleMouseUp(event);
6336
+ scope.dispatchEvent(_endEvent);
6337
+ state = STATE.NONE;
6175
6338
  }
6176
- function rotateUp(angle) {
6177
- sphericalDelta.phi -= angle;
6339
+ function onMouseWheel(event) {
6340
+ if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE) return;
6341
+ event.preventDefault();
6342
+ scope.dispatchEvent(_startEvent);
6343
+ handleMouseWheel(event);
6344
+ scope.dispatchEvent(_endEvent);
6178
6345
  }
6179
- const panLeft = function() {
6180
- const v = new import_three20.Vector3();
6181
- return function panLeft2(distance, objectMatrix) {
6182
- v.setFromMatrixColumn(objectMatrix, 0);
6183
- v.multiplyScalar(-distance);
6184
- panOffset.add(v);
6185
- };
6186
- }();
6187
- const panUp = function() {
6188
- const v = new import_three20.Vector3();
6189
- return function panUp2(distance, objectMatrix) {
6190
- if (scope.screenSpacePanning === true) {
6191
- v.setFromMatrixColumn(objectMatrix, 1);
6192
- } else {
6193
- v.setFromMatrixColumn(objectMatrix, 0);
6194
- v.crossVectors(scope.object.up, v);
6195
- }
6196
- v.multiplyScalar(distance);
6197
- panOffset.add(v);
6198
- };
6199
- }();
6200
- const pan = function() {
6201
- const offset = new import_three20.Vector3();
6202
- return function pan2(deltaX, deltaY) {
6203
- const element = scope.domElement;
6204
- if (scope.object.isPerspectiveCamera) {
6205
- const position = scope.object.position;
6206
- offset.copy(position).sub(scope.target);
6207
- let targetDistance = offset.length();
6208
- targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180);
6209
- panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
6210
- panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);
6211
- } else if (scope.object.isOrthographicCamera) {
6212
- panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);
6213
- panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);
6214
- } else {
6215
- console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.");
6216
- scope.enablePan = false;
6346
+ function onKeyDown(event) {
6347
+ if (scope.enabled === false || scope.enablePan === false) return;
6348
+ handleKeyDown(event);
6349
+ }
6350
+ function onTouchStart(event) {
6351
+ trackPointer(event);
6352
+ switch (pointers.length) {
6353
+ case 1:
6354
+ switch (scope.touches.ONE) {
6355
+ case import_three18.TOUCH.ROTATE:
6356
+ if (scope.enableRotate === false) return;
6357
+ handleTouchStartRotate();
6358
+ state = STATE.TOUCH_ROTATE;
6359
+ break;
6360
+ case import_three18.TOUCH.PAN:
6361
+ if (scope.enablePan === false) return;
6362
+ handleTouchStartPan();
6363
+ state = STATE.TOUCH_PAN;
6364
+ break;
6365
+ default:
6366
+ state = STATE.NONE;
6367
+ }
6368
+ break;
6369
+ case 2:
6370
+ switch (scope.touches.TWO) {
6371
+ case import_three18.TOUCH.DOLLY_PAN:
6372
+ if (scope.enableZoom === false && scope.enablePan === false) return;
6373
+ handleTouchStartDollyPan();
6374
+ state = STATE.TOUCH_DOLLY_PAN;
6375
+ break;
6376
+ case import_three18.TOUCH.DOLLY_ROTATE:
6377
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
6378
+ handleTouchStartDollyRotate();
6379
+ state = STATE.TOUCH_DOLLY_ROTATE;
6380
+ break;
6381
+ default:
6382
+ state = STATE.NONE;
6383
+ }
6384
+ break;
6385
+ default:
6386
+ state = STATE.NONE;
6387
+ }
6388
+ if (state !== STATE.NONE) {
6389
+ scope.dispatchEvent(_startEvent);
6390
+ }
6391
+ }
6392
+ function onTouchMove(event) {
6393
+ trackPointer(event);
6394
+ switch (state) {
6395
+ case STATE.TOUCH_ROTATE:
6396
+ if (scope.enableRotate === false) return;
6397
+ handleTouchMoveRotate(event);
6398
+ scope.update();
6399
+ break;
6400
+ case STATE.TOUCH_PAN:
6401
+ if (scope.enablePan === false) return;
6402
+ handleTouchMovePan(event);
6403
+ scope.update();
6404
+ break;
6405
+ case STATE.TOUCH_DOLLY_PAN:
6406
+ if (scope.enableZoom === false && scope.enablePan === false) return;
6407
+ handleTouchMoveDollyPan(event);
6408
+ scope.update();
6409
+ break;
6410
+ case STATE.TOUCH_DOLLY_ROTATE:
6411
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
6412
+ handleTouchMoveDollyRotate(event);
6413
+ scope.update();
6414
+ break;
6415
+ default:
6416
+ state = STATE.NONE;
6417
+ }
6418
+ }
6419
+ function onTouchEnd(event) {
6420
+ handleTouchEnd(event);
6421
+ scope.dispatchEvent(_endEvent);
6422
+ state = STATE.NONE;
6423
+ }
6424
+ function onContextMenu(event) {
6425
+ if (scope.enabled === false) return;
6426
+ event.preventDefault();
6427
+ }
6428
+ function addPointer(event) {
6429
+ pointers.push(event);
6430
+ }
6431
+ function removePointer(event) {
6432
+ delete pointerPositions[event.pointerId];
6433
+ for (let i = 0; i < pointers.length; i++) {
6434
+ if (pointers[i].pointerId == event.pointerId) {
6435
+ pointers.splice(i, 1);
6436
+ return;
6217
6437
  }
6218
- };
6219
- }();
6220
- function dollyOut(dollyScale) {
6221
- if (scope.object.isPerspectiveCamera) {
6222
- scale /= dollyScale;
6223
- } else if (scope.object.isOrthographicCamera) {
6224
- scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
6225
- scope.object.updateProjectionMatrix();
6226
- zoomChanged = true;
6227
- } else {
6228
- console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
6229
- scope.enableZoom = false;
6230
6438
  }
6231
6439
  }
6232
- function dollyIn(dollyScale) {
6233
- if (scope.object.isPerspectiveCamera) {
6234
- scale *= dollyScale;
6235
- } else if (scope.object.isOrthographicCamera) {
6236
- scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
6237
- scope.object.updateProjectionMatrix();
6238
- zoomChanged = true;
6239
- } else {
6240
- console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
6241
- scope.enableZoom = false;
6440
+ function trackPointer(event) {
6441
+ let position = pointerPositions[event.pointerId];
6442
+ if (position === void 0) {
6443
+ position = new import_three18.Vector2();
6444
+ pointerPositions[event.pointerId] = position;
6242
6445
  }
6446
+ position.set(event.pageX, event.pageY);
6243
6447
  }
6244
- function handleMouseDownRotate(event) {
6245
- rotateStart.set(event.clientX, event.clientY);
6246
- }
6247
- function handleMouseDownDolly(event) {
6248
- dollyStart.set(event.clientX, event.clientY);
6448
+ function getSecondPointerPosition(event) {
6449
+ const pointer = event.pointerId === pointers[0].pointerId ? pointers[1] : pointers[0];
6450
+ return pointerPositions[pointer.pointerId];
6249
6451
  }
6250
- function handleMouseDownPan(event) {
6251
- panStart.set(event.clientX, event.clientY);
6452
+ scope.domElement.addEventListener("contextmenu", onContextMenu);
6453
+ scope.domElement.addEventListener("pointerdown", onPointerDown);
6454
+ scope.domElement.addEventListener("pointercancel", onPointerCancel);
6455
+ scope.domElement.addEventListener("wheel", onMouseWheel, { passive: false });
6456
+ this.update();
6457
+ }
6458
+ };
6459
+ var MapControls = class extends OrbitControls {
6460
+ constructor(object, domElement) {
6461
+ super(object, domElement);
6462
+ this.screenSpacePanning = false;
6463
+ this.mouseButtons.LEFT = import_three18.MOUSE.PAN;
6464
+ this.mouseButtons.RIGHT = import_three18.MOUSE.ROTATE;
6465
+ this.touches.ONE = import_three18.TOUCH.PAN;
6466
+ this.touches.TWO = import_three18.TOUCH.DOLLY_ROTATE;
6467
+ }
6468
+ };
6469
+
6470
+ // src/renderer/Renderer.ts
6471
+ var _Renderer = class _Renderer {
6472
+ constructor(options) {
6473
+ this._dirty = true;
6474
+ this._resizeListener = void 0;
6475
+ this._disposed = false;
6476
+ this._debugHelpers = [];
6477
+ this._eventDispatchers = /* @__PURE__ */ new Map();
6478
+ this._changeListener = () => {
6479
+ this._dirty = true;
6480
+ };
6481
+ this.options = (0, import_ts_deepmerge9.default)({}, _Renderer.DEFAULT_OPTIONS, options ?? {});
6482
+ this._animationLoop = this.animate.bind(this);
6483
+ this._frameInterval = this.options.render.fpsLimit > 0 ? 1e3 / this.options.render.fpsLimit : void 0;
6484
+ this._scene = this.createScene();
6485
+ this._camera = this.createCamera();
6486
+ this._renderer = this.createRenderer();
6487
+ this._composer = this.createComposer();
6488
+ if (this.options.render.stats) {
6489
+ this._stats = new import_stats.default();
6490
+ document.body.appendChild(this._stats.dom);
6252
6491
  }
6253
- function handleMouseMoveRotate(event) {
6254
- rotateEnd.set(event.clientX, event.clientY);
6255
- rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
6256
- const element = scope.domElement;
6257
- rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
6258
- rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
6259
- rotateStart.copy(rotateEnd);
6260
- scope.update();
6492
+ this.init();
6493
+ this._controls = this.createControls();
6494
+ }
6495
+ //<editor-fold desc="INIT">
6496
+ createScene() {
6497
+ return new MineRenderScene();
6498
+ }
6499
+ createCamera() {
6500
+ switch (this.options.camera.type) {
6501
+ case "perspective":
6502
+ default:
6503
+ return new import_three19.PerspectiveCamera(
6504
+ this.options.camera.perspective.fov,
6505
+ this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
6506
+ this.options.camera.near,
6507
+ this.options.camera.far
6508
+ );
6509
+ case "orthographic":
6510
+ return new import_three19.OrthographicCamera(
6511
+ this.options.camera.orthographic.left ?? this.viewWidth / -2,
6512
+ this.options.camera.orthographic.right ?? this.viewWidth / 2,
6513
+ this.options.camera.orthographic.top ?? this.viewHeight / 2,
6514
+ this.options.camera.orthographic.bottom ?? this.viewHeight / -2,
6515
+ this.options.camera.near,
6516
+ this.options.camera.far
6517
+ );
6261
6518
  }
6262
- function handleMouseMoveDolly(event) {
6263
- dollyEnd.set(event.clientX, event.clientY);
6264
- dollyDelta.subVectors(dollyEnd, dollyStart);
6265
- if (dollyDelta.y > 0) {
6266
- dollyOut(getZoomScale());
6267
- } else if (dollyDelta.y < 0) {
6268
- dollyIn(getZoomScale());
6269
- }
6270
- dollyStart.copy(dollyEnd);
6271
- scope.update();
6519
+ }
6520
+ createRenderer() {
6521
+ const renderer = new import_three19.WebGLRenderer({
6522
+ antialias: this.options.render.antialias,
6523
+ alpha: true,
6524
+ powerPreference: "high-performance",
6525
+ depth: true
6526
+ });
6527
+ renderer.setClearColor(0, 0);
6528
+ renderer.shadowMap.enabled = true;
6529
+ renderer.shadowMap.type = import_three19.PCFSoftShadowMap;
6530
+ renderer.outputColorSpace = import_three19.SRGBColorSpace;
6531
+ renderer.setSize(this.viewWidth, this.viewHeight);
6532
+ return renderer;
6533
+ }
6534
+ createComposer() {
6535
+ if (!this.options.composer.enabled) return void 0;
6536
+ const composer = new import_postprocessing.EffectComposer(this.renderer);
6537
+ composer.setSize(this.viewWidth, this.viewHeight);
6538
+ composer.addPass(new import_postprocessing.RenderPass(this.scene, this.camera));
6539
+ return composer;
6540
+ }
6541
+ createControls() {
6542
+ if (!this.options.controls?.enabled) return void 0;
6543
+ const position = this.camera.position.clone();
6544
+ const controls = new OrbitControls(this.camera, this.renderer.domElement);
6545
+ this.camera.position.copy(position);
6546
+ const target = this.options.camera.lookingAt;
6547
+ if (isVector3(target)) {
6548
+ controls.target.copy(target);
6549
+ } else if (isTripleArray(target)) {
6550
+ controls.target.set(target[0], target[1], target[2]);
6551
+ }
6552
+ controls.update();
6553
+ controls.saveState();
6554
+ this.registerEventDispatcher(controls);
6555
+ return controls;
6556
+ }
6557
+ //</editor-fold>
6558
+ init() {
6559
+ if (this._disposed) return;
6560
+ if (typeof window["__THREE_DEVTOOLS__"] !== "undefined") {
6561
+ window["__THREE_DEVTOOLS__"].dispatchEvent(new CustomEvent("observe", { detail: this.scene }));
6272
6562
  }
6273
- function handleMouseMovePan(event) {
6274
- panEnd.set(event.clientX, event.clientY);
6275
- panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
6276
- pan(panDelta.x, panDelta.y);
6277
- panStart.copy(panEnd);
6278
- scope.update();
6563
+ if (this.options.debug.grid) {
6564
+ const gridHelper = new import_three19.GridHelper(128, 16);
6565
+ this._debugHelpers.push(gridHelper);
6566
+ this.scene.add(gridHelper);
6567
+ const gridHelper2 = new import_three19.GridHelper(128, 16);
6568
+ this._debugHelpers.push(gridHelper2);
6569
+ gridHelper2.rotation.x = 90 * (Math.PI / 180);
6570
+ this.scene.add(gridHelper2);
6571
+ const gridHelper3 = new import_three19.GridHelper(128, 16);
6572
+ this._debugHelpers.push(gridHelper3);
6573
+ gridHelper3.rotation.z = 90 * (Math.PI / 180);
6574
+ this.scene.add(gridHelper3);
6279
6575
  }
6280
- function handleMouseUp() {
6576
+ if (this.options.debug.axes) {
6577
+ const axesHelper = new import_three19.AxesHelper(64);
6578
+ this._debugHelpers.push(axesHelper);
6579
+ this.scene.add(axesHelper);
6281
6580
  }
6282
- function handleMouseWheel(event) {
6283
- if (event.deltaY < 0) {
6284
- dollyIn(getZoomScale());
6285
- } else if (event.deltaY > 0) {
6286
- dollyOut(getZoomScale());
6581
+ if (this.options.camera.position) {
6582
+ if (isVector3(this.options.camera.position)) {
6583
+ this.camera.position.set(this.options.camera.position.x, this.options.camera.position.y, this.options.camera.position.z);
6584
+ } else if (isTripleArray(this.options.camera.position)) {
6585
+ this.camera.position.set(this.options.camera.position[0], this.options.camera.position[1], this.options.camera.position[2]);
6287
6586
  }
6288
- scope.update();
6289
6587
  }
6290
- function handleKeyDown(event) {
6291
- let needsUpdate = false;
6292
- switch (event.code) {
6293
- case scope.keys.UP:
6294
- pan(0, scope.keyPanSpeed);
6295
- needsUpdate = true;
6296
- break;
6297
- case scope.keys.BOTTOM:
6298
- pan(0, -scope.keyPanSpeed);
6299
- needsUpdate = true;
6300
- break;
6301
- case scope.keys.LEFT:
6302
- pan(scope.keyPanSpeed, 0);
6303
- needsUpdate = true;
6304
- break;
6305
- case scope.keys.RIGHT:
6306
- pan(-scope.keyPanSpeed, 0);
6307
- needsUpdate = true;
6308
- break;
6309
- }
6310
- if (needsUpdate) {
6311
- event.preventDefault();
6312
- scope.update();
6588
+ if (this.options.camera.lookingAt) {
6589
+ if (isVector3(this.options.camera.lookingAt)) {
6590
+ this.camera.lookAt(this.options.camera.lookingAt);
6591
+ } else if (isTripleArray(this.options.camera.lookingAt)) {
6592
+ this.camera.lookAt(this.options.camera.lookingAt[0], this.options.camera.lookingAt[1], this.options.camera.lookingAt[2]);
6313
6593
  }
6314
6594
  }
6315
- function handleTouchStartRotate() {
6316
- if (pointers.length === 1) {
6317
- rotateStart.set(pointers[0].pageX, pointers[0].pageY);
6318
- } else {
6319
- const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
6320
- const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
6321
- rotateStart.set(x, y);
6322
- }
6595
+ if (this.options.render.autoResize && !this._resizeListener) {
6596
+ this._resizeListener = () => {
6597
+ this.resize(this.viewWidth, this.viewHeight);
6598
+ };
6599
+ window.addEventListener("resize", this._resizeListener);
6600
+ }
6601
+ }
6602
+ get element() {
6603
+ return this._element;
6604
+ }
6605
+ appendTo(element) {
6606
+ if (this._disposed) return;
6607
+ this._element = element;
6608
+ this._element.appendChild(this.renderer.domElement);
6609
+ if (this.viewWidth == 0) {
6610
+ console.warn("0 element width");
6611
+ }
6612
+ if (this.viewHeight == 0) {
6613
+ console.warn("0 element height");
6614
+ }
6615
+ this.resize(this.viewWidth, this.viewHeight);
6616
+ }
6617
+ /**
6618
+ * Redraws when the dispatcher emits the selected event. Registering the same pair twice has no effect.
6619
+ * The renderer removes its listener on disposal; the caller retains ownership of the dispatcher.
6620
+ */
6621
+ registerEventDispatcher(dispatcher, changeEvent2 = "change") {
6622
+ if (this._disposed) return;
6623
+ let events = this._eventDispatchers.get(dispatcher);
6624
+ if (!events) {
6625
+ events = /* @__PURE__ */ new Set();
6626
+ this._eventDispatchers.set(dispatcher, events);
6627
+ }
6628
+ if (events.has(changeEvent2)) return;
6629
+ events.add(changeEvent2);
6630
+ dispatcher.addEventListener(changeEvent2, this._changeListener);
6631
+ }
6632
+ resize(width, height) {
6633
+ if (this._disposed) return;
6634
+ if (isPerspectiveCamera(this.camera)) {
6635
+ this.camera.aspect = width / height;
6636
+ this.camera.updateProjectionMatrix();
6637
+ } else if (isOrthographicCamera(this.camera)) {
6638
+ this.camera.left = width / -2;
6639
+ this.camera.right = width / 2;
6640
+ this.camera.top = height / 2;
6641
+ this.camera.bottom = height / -2;
6642
+ this.camera.updateProjectionMatrix();
6643
+ }
6644
+ this.renderer.setSize(width, height);
6645
+ this.composer?.setSize(width, height);
6646
+ this._dirty = true;
6647
+ }
6648
+ //<editor-fold desc="RENDER">
6649
+ get dirty() {
6650
+ return this._dirty || this.scene.dirty;
6651
+ }
6652
+ set dirty(dirty) {
6653
+ this._dirty = dirty;
6654
+ this.scene.dirty = dirty;
6655
+ }
6656
+ start() {
6657
+ if (this._disposed) return;
6658
+ this.stop();
6659
+ this.renderer.setAnimationLoop(this._animationLoop);
6660
+ }
6661
+ stop() {
6662
+ if (this._disposed) return;
6663
+ this.renderer.setAnimationLoop(null);
6664
+ this._nextFrameTime = void 0;
6665
+ }
6666
+ /**
6667
+ * Stops rendering and releases owned resources. Repeated calls have no effect, and a disposed
6668
+ * renderer cannot be restarted. Scene objects are detached; shared assets and caller-owned
6669
+ * controls must be managed by their owners.
6670
+ */
6671
+ dispose() {
6672
+ if (this._disposed) return;
6673
+ this.stop();
6674
+ this._disposed = true;
6675
+ if (this._resizeListener) {
6676
+ window.removeEventListener("resize", this._resizeListener);
6677
+ this._resizeListener = void 0;
6323
6678
  }
6324
- function handleTouchStartPan() {
6325
- if (pointers.length === 1) {
6326
- panStart.set(pointers[0].pageX, pointers[0].pageY);
6327
- } else {
6328
- const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
6329
- const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
6330
- panStart.set(x, y);
6679
+ for (const [dispatcher, events] of this._eventDispatchers) {
6680
+ for (const event of events) {
6681
+ dispatcher.removeEventListener(event, this._changeListener);
6331
6682
  }
6332
6683
  }
6333
- function handleTouchStartDolly() {
6334
- const dx = pointers[0].pageX - pointers[1].pageX;
6335
- const dy = pointers[0].pageY - pointers[1].pageY;
6336
- const distance = Math.sqrt(dx * dx + dy * dy);
6337
- dollyStart.set(0, distance);
6338
- }
6339
- function handleTouchStartDollyPan() {
6340
- if (scope.enableZoom) handleTouchStartDolly();
6341
- if (scope.enablePan) handleTouchStartPan();
6342
- }
6343
- function handleTouchStartDollyRotate() {
6344
- if (scope.enableZoom) handleTouchStartDolly();
6345
- if (scope.enableRotate) handleTouchStartRotate();
6346
- }
6347
- function handleTouchMoveRotate(event) {
6348
- if (pointers.length == 1) {
6349
- rotateEnd.set(event.pageX, event.pageY);
6350
- } else {
6351
- const position = getSecondPointerPosition(event);
6352
- const x = 0.5 * (event.pageX + position.x);
6353
- const y = 0.5 * (event.pageY + position.y);
6354
- rotateEnd.set(x, y);
6355
- }
6356
- rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
6357
- const element = scope.domElement;
6358
- rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
6359
- rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
6360
- rotateStart.copy(rotateEnd);
6684
+ this._eventDispatchers.clear();
6685
+ this._stats?.dom.remove();
6686
+ this._stats = void 0;
6687
+ this.renderer.domElement.remove();
6688
+ this._element = void 0;
6689
+ if (this._controls) {
6690
+ const controls = this._controls;
6691
+ this._controls = void 0;
6692
+ controls.enabled = false;
6693
+ controls.dispose();
6361
6694
  }
6362
- function handleTouchMovePan(event) {
6363
- if (pointers.length === 1) {
6364
- panEnd.set(event.pageX, event.pageY);
6365
- } else {
6366
- const position = getSecondPointerPosition(event);
6367
- const x = 0.5 * (event.pageX + position.x);
6368
- const y = 0.5 * (event.pageY + position.y);
6369
- panEnd.set(x, y);
6695
+ this.scene.clear();
6696
+ for (const helper of this._debugHelpers) {
6697
+ helper.geometry.dispose();
6698
+ const materials = Array.isArray(helper.material) ? helper.material : [helper.material];
6699
+ for (const material of materials) {
6700
+ material.dispose();
6370
6701
  }
6371
- panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
6372
- pan(panDelta.x, panDelta.y);
6373
- panStart.copy(panEnd);
6374
- }
6375
- function handleTouchMoveDolly(event) {
6376
- const position = getSecondPointerPosition(event);
6377
- const dx = event.pageX - position.x;
6378
- const dy = event.pageY - position.y;
6379
- const distance = Math.sqrt(dx * dx + dy * dy);
6380
- dollyEnd.set(0, distance);
6381
- dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed));
6382
- dollyOut(dollyDelta.y);
6383
- dollyStart.copy(dollyEnd);
6384
6702
  }
6385
- function handleTouchMoveDollyPan(event) {
6386
- if (scope.enableZoom) handleTouchMoveDolly(event);
6387
- if (scope.enablePan) handleTouchMovePan(event);
6388
- }
6389
- function handleTouchMoveDollyRotate(event) {
6390
- if (scope.enableZoom) handleTouchMoveDolly(event);
6391
- if (scope.enableRotate) handleTouchMoveRotate(event);
6703
+ this._debugHelpers.length = 0;
6704
+ this.composer?.dispose();
6705
+ this.renderer.dispose();
6706
+ this.renderer.forceContextLoss();
6707
+ }
6708
+ animate(t = performance.now()) {
6709
+ if (this._disposed) return;
6710
+ if (this._controls?.enabled) {
6711
+ this._controls.update();
6392
6712
  }
6393
- function handleTouchEnd() {
6713
+ if (this._disposed) return;
6714
+ if (!this.dirty && !this.options.render.renderAlways) return;
6715
+ const interval = this._frameInterval;
6716
+ if (interval) {
6717
+ const next = this._nextFrameTime;
6718
+ if (next !== void 0 && t + 0.1 < next) return;
6719
+ this._nextFrameTime = next !== void 0 && t - next < interval ? next + interval : t + interval;
6394
6720
  }
6395
- function onPointerDown(event) {
6396
- if (scope.enabled === false) return;
6397
- if (pointers.length === 0) {
6398
- scope.domElement.setPointerCapture(event.pointerId);
6399
- scope.domElement.addEventListener("pointermove", onPointerMove);
6400
- scope.domElement.addEventListener("pointerup", onPointerUp);
6401
- }
6402
- addPointer(event);
6403
- if (event.pointerType === "touch") {
6404
- onTouchStart(event);
6405
- } else {
6406
- onMouseDown(event);
6407
- }
6721
+ if (this._stats) {
6722
+ this._stats.begin();
6408
6723
  }
6409
- function onPointerMove(event) {
6410
- if (scope.enabled === false) return;
6411
- if (event.pointerType === "touch") {
6412
- onTouchMove(event);
6413
- } else {
6414
- onMouseMove(event);
6415
- }
6724
+ if (this.options.composer.enabled && this.composer) {
6725
+ this.composer.render();
6726
+ } else {
6727
+ this.renderer.render(this.scene, this.camera);
6416
6728
  }
6417
- function onPointerUp(event) {
6418
- if (scope.enabled === false) return;
6419
- if (event.pointerType === "touch") {
6420
- onTouchEnd();
6421
- } else {
6422
- onMouseUp(event);
6423
- }
6424
- removePointer(event);
6425
- if (pointers.length === 0) {
6426
- scope.domElement.releasePointerCapture(event.pointerId);
6427
- scope.domElement.removeEventListener("pointermove", onPointerMove);
6428
- scope.domElement.removeEventListener("pointerup", onPointerUp);
6429
- }
6729
+ this.dirty = false;
6730
+ if (this._stats) {
6731
+ this._stats.end();
6430
6732
  }
6431
- function onPointerCancel(event) {
6432
- removePointer(event);
6733
+ }
6734
+ //</editor-fold>
6735
+ toImage() {
6736
+ return this.renderer.domElement.toDataURL();
6737
+ }
6738
+ ///
6739
+ get attachedToBody() {
6740
+ return this.element === document.body;
6741
+ }
6742
+ get viewWidth() {
6743
+ return this.attachedToBody ? window.innerWidth : this.element?.offsetWidth || 0;
6744
+ }
6745
+ get viewHeight() {
6746
+ return this.attachedToBody ? window.innerHeight : this.element?.offsetHeight || 0;
6747
+ }
6748
+ get scene() {
6749
+ return this._scene;
6750
+ }
6751
+ get camera() {
6752
+ return this._camera;
6753
+ }
6754
+ get renderer() {
6755
+ return this._renderer;
6756
+ }
6757
+ get composer() {
6758
+ return this._composer;
6759
+ }
6760
+ /** Renderer-owned controls, or undefined when disabled at construction or after disposal. */
6761
+ get controls() {
6762
+ return this._controls;
6763
+ }
6764
+ ///
6765
+ };
6766
+ _Renderer.DEFAULT_OPTIONS = (0, import_ts_deepmerge9.default)({}, {
6767
+ camera: {
6768
+ type: "perspective",
6769
+ near: 1,
6770
+ far: 5e3,
6771
+ perspective: {
6772
+ aspect: void 0,
6773
+ fov: 50
6774
+ },
6775
+ orthographic: {
6776
+ left: void 0,
6777
+ right: void 0,
6778
+ top: void 0,
6779
+ bottom: void 0
6780
+ },
6781
+ position: new import_three19.Vector3(50, 50, 50),
6782
+ lookingAt: new import_three19.Vector3(0, 0, 0)
6783
+ },
6784
+ render: {
6785
+ fpsLimit: 60,
6786
+ stats: false,
6787
+ antialias: true,
6788
+ shade: true,
6789
+ autoResize: true,
6790
+ renderAlways: false
6791
+ },
6792
+ composer: {
6793
+ enabled: true
6794
+ },
6795
+ controls: {
6796
+ enabled: false
6797
+ },
6798
+ debug: {
6799
+ grid: false,
6800
+ axes: false
6801
+ }
6802
+ });
6803
+ var Renderer = _Renderer;
6804
+
6805
+ // src/skin/Skins.ts
6806
+ var Skins = class {
6807
+ //<editor-fold desc="Skins">
6808
+ static async fromUuidOrUsername(uuidOrUsername) {
6809
+ if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
6810
+ return this.fromUuid(uuidOrUsername);
6433
6811
  }
6434
- function onMouseDown(event) {
6435
- let mouseAction;
6436
- switch (event.button) {
6437
- case 0:
6438
- mouseAction = scope.mouseButtons.LEFT;
6439
- break;
6440
- case 1:
6441
- mouseAction = scope.mouseButtons.MIDDLE;
6442
- break;
6443
- case 2:
6444
- mouseAction = scope.mouseButtons.RIGHT;
6445
- break;
6446
- default:
6447
- mouseAction = -1;
6448
- }
6449
- switch (mouseAction) {
6450
- case import_three20.MOUSE.DOLLY:
6451
- if (scope.enableZoom === false) return;
6452
- handleMouseDownDolly(event);
6453
- state = STATE.DOLLY;
6454
- break;
6455
- case import_three20.MOUSE.ROTATE:
6456
- if (event.ctrlKey || event.metaKey || event.shiftKey) {
6457
- if (scope.enablePan === false) return;
6458
- handleMouseDownPan(event);
6459
- state = STATE.PAN;
6460
- } else {
6461
- if (scope.enableRotate === false) return;
6462
- handleMouseDownRotate(event);
6463
- state = STATE.ROTATE;
6464
- }
6465
- break;
6466
- case import_three20.MOUSE.PAN:
6467
- if (event.ctrlKey || event.metaKey || event.shiftKey) {
6468
- if (scope.enableRotate === false) return;
6469
- handleMouseDownRotate(event);
6470
- state = STATE.ROTATE;
6471
- } else {
6472
- if (scope.enablePan === false) return;
6473
- handleMouseDownPan(event);
6474
- state = STATE.PAN;
6475
- }
6476
- break;
6477
- default:
6478
- state = STATE.NONE;
6812
+ return this.fromUsername(uuidOrUsername);
6813
+ }
6814
+ static async fromUuid(uuid) {
6815
+ return this.getMcProxySkinUrl(uuid);
6816
+ }
6817
+ static async fromUsername(username) {
6818
+ return this.usernameToUuid(username).then((uuid) => {
6819
+ if (uuid) {
6820
+ return this.fromUuid(uuid);
6479
6821
  }
6480
- if (state !== STATE.NONE) {
6481
- scope.dispatchEvent(_startEvent);
6822
+ return void 0;
6823
+ });
6824
+ }
6825
+ static async fromMineSkin(mineskinId) {
6826
+ return this.getMineSkin(mineskinId).then((mineskin) => {
6827
+ if (mineskin) {
6828
+ return mineskin["data"]["texture"]["value"]["urls"]["skins"];
6482
6829
  }
6830
+ return void 0;
6831
+ });
6832
+ }
6833
+ //</editor-fold>
6834
+ //<editor-fold desc="Capes">
6835
+ static async capeFromUuidOrUsername(uuidOrUsername) {
6836
+ if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
6837
+ return this.capeFromUuid(uuidOrUsername);
6483
6838
  }
6484
- function onMouseMove(event) {
6485
- if (scope.enabled === false) return;
6486
- switch (state) {
6487
- case STATE.ROTATE:
6488
- if (scope.enableRotate === false) return;
6489
- handleMouseMoveRotate(event);
6490
- break;
6491
- case STATE.DOLLY:
6492
- if (scope.enableZoom === false) return;
6493
- handleMouseMoveDolly(event);
6494
- break;
6495
- case STATE.PAN:
6496
- if (scope.enablePan === false) return;
6497
- handleMouseMovePan(event);
6498
- break;
6839
+ return this.capeFromUsername(uuidOrUsername);
6840
+ }
6841
+ static async capeFromUuid(uuid) {
6842
+ return this.getMcProxyCapeUrl(uuid);
6843
+ }
6844
+ static async capeFromUsername(username) {
6845
+ return this.usernameToUuid(username).then((uuid) => {
6846
+ if (uuid) {
6847
+ return this.capeFromUuid(uuid);
6499
6848
  }
6500
- }
6501
- function onMouseUp(event) {
6502
- handleMouseUp(event);
6503
- scope.dispatchEvent(_endEvent);
6504
- state = STATE.NONE;
6505
- }
6506
- function onMouseWheel(event) {
6507
- if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE) return;
6508
- event.preventDefault();
6509
- scope.dispatchEvent(_startEvent);
6510
- handleMouseWheel(event);
6511
- scope.dispatchEvent(_endEvent);
6512
- }
6513
- function onKeyDown(event) {
6514
- if (scope.enabled === false || scope.enablePan === false) return;
6515
- handleKeyDown(event);
6516
- }
6517
- function onTouchStart(event) {
6518
- trackPointer(event);
6519
- switch (pointers.length) {
6520
- case 1:
6521
- switch (scope.touches.ONE) {
6522
- case import_three20.TOUCH.ROTATE:
6523
- if (scope.enableRotate === false) return;
6524
- handleTouchStartRotate();
6525
- state = STATE.TOUCH_ROTATE;
6526
- break;
6527
- case import_three20.TOUCH.PAN:
6528
- if (scope.enablePan === false) return;
6529
- handleTouchStartPan();
6530
- state = STATE.TOUCH_PAN;
6531
- break;
6532
- default:
6533
- state = STATE.NONE;
6534
- }
6535
- break;
6536
- case 2:
6537
- switch (scope.touches.TWO) {
6538
- case import_three20.TOUCH.DOLLY_PAN:
6539
- if (scope.enableZoom === false && scope.enablePan === false) return;
6540
- handleTouchStartDollyPan();
6541
- state = STATE.TOUCH_DOLLY_PAN;
6542
- break;
6543
- case import_three20.TOUCH.DOLLY_ROTATE:
6544
- if (scope.enableZoom === false && scope.enableRotate === false) return;
6545
- handleTouchStartDollyRotate();
6546
- state = STATE.TOUCH_DOLLY_ROTATE;
6547
- break;
6548
- default:
6549
- state = STATE.NONE;
6550
- }
6551
- break;
6552
- default:
6553
- state = STATE.NONE;
6849
+ return void 0;
6850
+ });
6851
+ }
6852
+ static async capeFromCapesDev(uuid, capeType = "minecraft") {
6853
+ return this.getCapesDev(uuid, capeType).then((cape) => {
6854
+ if (cape) {
6855
+ return cape?.stillImageUrl;
6554
6856
  }
6555
- if (state !== STATE.NONE) {
6556
- scope.dispatchEvent(_startEvent);
6857
+ return void 0;
6858
+ });
6859
+ }
6860
+ //</editor-fold>
6861
+ //<editor-fold desc="Helpers">
6862
+ static async usernameToUuid(username) {
6863
+ return this.usernameToUuidMcProxy(username);
6864
+ }
6865
+ static async usernameToUuidMcProxy(username) {
6866
+ return Requests.genericRequest({
6867
+ baseURL: "https://mcproxy.dev",
6868
+ url: "/uuid/" + username
6869
+ }).then((res) => {
6870
+ if (res.status === 200) {
6871
+ return res.data["data"]["id"];
6557
6872
  }
6558
- }
6559
- function onTouchMove(event) {
6560
- trackPointer(event);
6561
- switch (state) {
6562
- case STATE.TOUCH_ROTATE:
6563
- if (scope.enableRotate === false) return;
6564
- handleTouchMoveRotate(event);
6565
- scope.update();
6566
- break;
6567
- case STATE.TOUCH_PAN:
6568
- if (scope.enablePan === false) return;
6569
- handleTouchMovePan(event);
6570
- scope.update();
6571
- break;
6572
- case STATE.TOUCH_DOLLY_PAN:
6573
- if (scope.enableZoom === false && scope.enablePan === false) return;
6574
- handleTouchMoveDollyPan(event);
6575
- scope.update();
6576
- break;
6577
- case STATE.TOUCH_DOLLY_ROTATE:
6578
- if (scope.enableZoom === false && scope.enableRotate === false) return;
6579
- handleTouchMoveDollyRotate(event);
6580
- scope.update();
6581
- break;
6582
- default:
6583
- state = STATE.NONE;
6873
+ return void 0;
6874
+ }).catch((err) => {
6875
+ console.warn(err);
6876
+ return void 0;
6877
+ });
6878
+ }
6879
+ /** @deprecated **/
6880
+ static async usernameToUuidSkinProxy(username) {
6881
+ return Requests.genericRequest({
6882
+ baseURL: "https://minecraft-skin-proxy.inventive.workers.dev",
6883
+ url: "/uuid/" + username
6884
+ }).then((res) => {
6885
+ if (res.status === 200) {
6886
+ return res.data["id"];
6584
6887
  }
6585
- }
6586
- function onTouchEnd(event) {
6587
- handleTouchEnd(event);
6588
- scope.dispatchEvent(_endEvent);
6589
- state = STATE.NONE;
6590
- }
6591
- function onContextMenu(event) {
6592
- if (scope.enabled === false) return;
6593
- event.preventDefault();
6594
- }
6595
- function addPointer(event) {
6596
- pointers.push(event);
6597
- }
6598
- function removePointer(event) {
6599
- delete pointerPositions[event.pointerId];
6600
- for (let i = 0; i < pointers.length; i++) {
6601
- if (pointers[i].pointerId == event.pointerId) {
6602
- pointers.splice(i, 1);
6603
- return;
6604
- }
6888
+ return void 0;
6889
+ }).catch((err) => {
6890
+ console.warn(err);
6891
+ return void 0;
6892
+ });
6893
+ }
6894
+ static async usernameToUuidMineTools(username) {
6895
+ return Requests.genericRequest({
6896
+ baseURL: "https://api.minetools.eu",
6897
+ url: "/uuid/" + username
6898
+ }).then((res) => {
6899
+ if (res.status === 200) {
6900
+ return res.data["id"];
6605
6901
  }
6606
- }
6607
- function trackPointer(event) {
6608
- let position = pointerPositions[event.pointerId];
6609
- if (position === void 0) {
6610
- position = new import_three20.Vector2();
6611
- pointerPositions[event.pointerId] = position;
6902
+ return void 0;
6903
+ }).catch((err) => {
6904
+ console.warn(err);
6905
+ return void 0;
6906
+ });
6907
+ }
6908
+ static async getProfileFromMinetools(uuid) {
6909
+ return Requests.genericRequest({
6910
+ baseURL: "https://api.minetools.eu",
6911
+ url: "/profile/" + uuid
6912
+ }).then((res) => {
6913
+ if (res.status === 200) {
6914
+ return res.data;
6612
6915
  }
6613
- position.set(event.pageX, event.pageY);
6614
- }
6615
- function getSecondPointerPosition(event) {
6616
- const pointer = event.pointerId === pointers[0].pointerId ? pointers[1] : pointers[0];
6617
- return pointerPositions[pointer.pointerId];
6618
- }
6619
- scope.domElement.addEventListener("contextmenu", onContextMenu);
6620
- scope.domElement.addEventListener("pointerdown", onPointerDown);
6621
- scope.domElement.addEventListener("pointercancel", onPointerCancel);
6622
- scope.domElement.addEventListener("wheel", onMouseWheel, { passive: false });
6623
- this.update();
6916
+ });
6624
6917
  }
6625
- };
6626
- var MapControls = class extends OrbitControls {
6627
- constructor(object, domElement) {
6628
- super(object, domElement);
6629
- this.screenSpacePanning = false;
6630
- this.mouseButtons.LEFT = import_three20.MOUSE.PAN;
6631
- this.mouseButtons.RIGHT = import_three20.MOUSE.ROTATE;
6632
- this.touches.ONE = import_three20.TOUCH.PAN;
6633
- this.touches.TWO = import_three20.TOUCH.DOLLY_ROTATE;
6918
+ static async getMineSkin(mineskinId) {
6919
+ return Requests.genericRequest({
6920
+ baseURL: "https://api.mineskin.org",
6921
+ url: "/get/uuid/" + mineskinId
6922
+ }).then((res) => {
6923
+ if (res.status === 200) {
6924
+ return res.data;
6925
+ }
6926
+ return void 0;
6927
+ }).catch((err) => {
6928
+ console.warn(err);
6929
+ return void 0;
6930
+ });
6931
+ }
6932
+ static async getCapesDev(uuid, type = "all") {
6933
+ return Requests.genericRequest({
6934
+ baseURL: "https://api.capes.dev",
6935
+ url: "/load/" + uuid + "/" + type
6936
+ }).then((res) => {
6937
+ if (res.status === 200) {
6938
+ return res.data;
6939
+ }
6940
+ return void 0;
6941
+ }).catch((err) => {
6942
+ console.warn(err);
6943
+ return void 0;
6944
+ });
6945
+ }
6946
+ static getCrafatarSkinUrl(uuid) {
6947
+ return "https://crafatar.com/skins/" + uuid;
6948
+ }
6949
+ static getCrafatarCapeUrl(uuid) {
6950
+ return "https://crafatar.com/capes/" + uuid;
6951
+ }
6952
+ static getMcHeadsSkinUrl(uuid) {
6953
+ return "https://mc-heads.net/skin/" + uuid;
6954
+ }
6955
+ static getMineSkinPlayerSkinUrl(uuid) {
6956
+ return "https://mineskin.org/skin/player/" + uuid;
6957
+ }
6958
+ /** @deprecated **/
6959
+ static getSkinProxySkinUrl(uuid) {
6960
+ return "https://minecraft-skin-proxy.inventive.workers.dev/skin/" + uuid;
6961
+ }
6962
+ /** @deprecated **/
6963
+ static getSkinProxyCapeUrl(uuid) {
6964
+ return "https://minecraft-skin-proxy.inventive.workers.dev/cape/" + uuid;
6965
+ }
6966
+ static getMcProxySkinUrl(uuid) {
6967
+ return "https://mcproxy.dev/skin/" + uuid;
6634
6968
  }
6969
+ static getMcProxyCapeUrl(uuid) {
6970
+ return "https://mcproxy.dev/cape/" + uuid;
6971
+ }
6972
+ //</editor-fold>
6635
6973
  };
6636
6974
 
6637
6975
  // src/world/Chunk.ts
@@ -6748,7 +7086,7 @@ var MineRenderWorld = class {
6748
7086
  };
6749
7087
 
6750
7088
  // src/world/Chunk.ts
6751
- var p12 = prefix("Chunk");
7089
+ var p11 = prefix("Chunk");
6752
7090
  var Chunk = class _Chunk {
6753
7091
  constructor(scene, x, y, z) {
6754
7092
  this._blocks = [];
@@ -6800,7 +7138,7 @@ var Chunk = class _Chunk {
6800
7138
  const index = _Chunk.chunkPosToBlockIndex(pos);
6801
7139
  const current = this._blocks[index];
6802
7140
  if (typeof current !== "undefined") {
6803
- console.debug(p12, "deleting existing block at", pos, worldPos, index);
7141
+ console.debug(p11, "deleting existing block at", pos, worldPos, index);
6804
7142
  current.object.removeFromScene();
6805
7143
  delete this._blocks[index];
6806
7144
  }