minerender 2.1.0-alpha.1 → 2.1.0-alpha.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -28,14 +28,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
28
  mod
29
29
  ));
30
30
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
- var __decorateClass = (decorators, target, key, kind) => {
32
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
33
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
34
- if (decorator = decorators[i])
35
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
36
- if (kind && result) __defProp(target, key, result);
37
- return result;
38
- };
39
31
 
40
32
  // ../../node_modules/ts-deepmerge/dist/index.js
41
33
  var require_dist = __commonJS({
@@ -45,8 +37,8 @@ var require_dist = __commonJS({
45
37
  __assign = Object.assign || function(t) {
46
38
  for (var s, i = 1, n = arguments.length; i < n; i++) {
47
39
  s = arguments[i];
48
- for (var p13 in s) if (Object.prototype.hasOwnProperty.call(s, p13))
49
- t[p13] = s[p13];
40
+ for (var p12 in s) if (Object.prototype.hasOwnProperty.call(s, p12))
41
+ t[p12] = s[p12];
50
42
  }
51
43
  return t;
52
44
  };
@@ -90,7 +82,7 @@ var require_dist = __commonJS({
90
82
  return false;
91
83
  };
92
84
  var PROTECTED_KEYS = ["__proto__"];
93
- var merge11 = function() {
85
+ var merge10 = function() {
94
86
  var objects = [];
95
87
  for (var _i = 0; _i < arguments.length; _i++) {
96
88
  objects[_i] = arguments[_i];
@@ -101,9 +93,9 @@ var require_dist = __commonJS({
101
93
  return;
102
94
  }
103
95
  if (Array.isArray(result[key]) && Array.isArray(current[key])) {
104
- result[key] = merge11.options.mergeArrays ? Array.from(new Set(result[key].concat(current[key]))) : current[key];
96
+ result[key] = merge10.options.mergeArrays ? Array.from(new Set(result[key].concat(current[key]))) : current[key];
105
97
  } else if (isObject(result[key]) && isObject(current[key])) {
106
- result[key] = merge11(result[key], current[key]);
98
+ result[key] = merge10(result[key], current[key]);
107
99
  } else {
108
100
  result[key] = current[key];
109
101
  }
@@ -114,18 +106,18 @@ var require_dist = __commonJS({
114
106
  var defaultOptions = {
115
107
  mergeArrays: true
116
108
  };
117
- merge11.options = defaultOptions;
118
- merge11.withOptions = function(options) {
109
+ merge10.options = defaultOptions;
110
+ merge10.withOptions = function(options) {
119
111
  var objects = [];
120
112
  for (var _i = 1; _i < arguments.length; _i++) {
121
113
  objects[_i - 1] = arguments[_i];
122
114
  }
123
- merge11.options = __assign({ mergeArrays: true }, options);
124
- var result = merge11.apply(void 0, __spreadArray([], __read(objects), false));
125
- merge11.options = defaultOptions;
115
+ merge10.options = __assign({ mergeArrays: true }, options);
116
+ var result = merge10.apply(void 0, __spreadArray([], __read(objects), false));
117
+ merge10.options = defaultOptions;
126
118
  return result;
127
119
  };
128
- exports2.default = merge11;
120
+ exports2.default = merge10;
129
121
  }
130
122
  });
131
123
 
@@ -135,6 +127,7 @@ __export(index_node_exports, {
135
127
  AXES: () => AXES,
136
128
  ArchiveAssetSource: () => ArchiveAssetSource,
137
129
  AssetKey: () => AssetKey,
130
+ AssetLoadError: () => AssetLoadError,
138
131
  AssetLoader: () => AssetLoader,
139
132
  AssetParser: () => AssetParser,
140
133
  AssetSource: () => AssetSource,
@@ -192,6 +185,7 @@ __export(index_node_exports, {
192
185
  OrbitControls: () => OrbitControls,
193
186
  PersistentCache: () => PersistentCache,
194
187
  Renderer: () => Renderer,
188
+ RequestError: () => RequestError,
195
189
  Requests: () => Requests,
196
190
  SKIN_PARTS: () => SKIN_PARTS,
197
191
  SceneInspector: () => SceneInspector,
@@ -302,25 +296,29 @@ var Env = class {
302
296
  };
303
297
 
304
298
  // src/cache/PersistentCache.ts
305
- var _PersistentCache = class _PersistentCache {
299
+ var PersistentCache = class _PersistentCache {
306
300
  constructor(backing) {
307
301
  this.backing = backing;
308
302
  }
303
+ static {
304
+ /** Bump to invalidate every persisted entry. */
305
+ this.VERSION = 2;
306
+ }
309
307
  static open(name) {
310
308
  return Env.provider.openCache(name, _PersistentCache.VERSION);
311
309
  }
310
+ /** Loads a missing entry and stores only non-nullish results. */
312
311
  async getOrLoad(key, loader) {
313
312
  let v = await this.get(key);
314
313
  if (typeof v === "undefined" || v === null) {
315
314
  v = await loader(key);
316
- await this.put(key, v);
315
+ if (typeof v !== "undefined" && v !== null) {
316
+ await this.put(key, v);
317
+ }
317
318
  }
318
319
  return v;
319
320
  }
320
321
  };
321
- /** Bump to invalidate every persisted entry. */
322
- _PersistentCache.VERSION = 1;
323
- var PersistentCache = _PersistentCache;
324
322
 
325
323
  // src/env/node/NodeCache.ts
326
324
  var NodeCache = class extends PersistentCache {
@@ -494,8 +492,7 @@ function serializeImageKey(key) {
494
492
  return md5(key.src);
495
493
  }
496
494
  function serializeBoxGeometryKey(key) {
497
- var _a;
498
- return md5([key.width, key.height, key.depth, (_a = key.uv) == null ? void 0 : _a.join(":")].join("_"));
495
+ return md5([key.width, key.height, key.depth, key.uv?.join(":")].join("_"));
499
496
  }
500
497
  function serializeTextureKey(key) {
501
498
  return md5([key.src, key.format, key.rotation].join("$"));
@@ -510,7 +507,61 @@ function serializeMeshKey(key) {
510
507
  // src/cache/Caching.ts
511
508
  var import_loading_cache = require("@inventivetalent/loading-cache");
512
509
  var import_time = require("@inventivetalent/time");
513
- var Caching = class {
510
+ var Caching = class _Caching {
511
+ static {
512
+ this.rawImageCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(5)).buildAsync();
513
+ }
514
+ static {
515
+ this.imageDataCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
516
+ }
517
+ static {
518
+ this.canvasImageDataCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
519
+ }
520
+ static {
521
+ this.wrappedImageCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
522
+ }
523
+ static {
524
+ this.boxGeometryCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(20)).build();
525
+ }
526
+ static {
527
+ this.textureCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
528
+ }
529
+ static {
530
+ this.materialCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
531
+ }
532
+ static {
533
+ this.boxMeshCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
534
+ }
535
+ static {
536
+ this.textureAssetCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
537
+ }
538
+ static {
539
+ this.textureMetaCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
540
+ }
541
+ static {
542
+ this.rawModelCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
543
+ }
544
+ static {
545
+ this.mergedModelCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
546
+ }
547
+ static {
548
+ this.modelTextureAtlasCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
549
+ }
550
+ static {
551
+ this.blockStateCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
552
+ }
553
+ static {
554
+ this.listAssetCache = _Caching.createAssetCache();
555
+ }
556
+ static {
557
+ this.defaultBlockStatesCache = _Caching.createAssetCache();
558
+ }
559
+ static {
560
+ this.entityModelsCache = _Caching.createAssetCache();
561
+ }
562
+ static createAssetCache() {
563
+ 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();
564
+ }
514
565
  /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */
515
566
  static get all() {
516
567
  return [
@@ -527,7 +578,10 @@ var Caching = class {
527
578
  this.rawModelCache,
528
579
  this.mergedModelCache,
529
580
  this.modelTextureAtlasCache,
530
- this.blockStateCache
581
+ this.blockStateCache,
582
+ this.listAssetCache,
583
+ this.defaultBlockStatesCache,
584
+ this.entityModelsCache
531
585
  ];
532
586
  }
533
587
  static clear() {
@@ -538,8 +592,8 @@ var Caching = class {
538
592
  /**
539
593
  * Clears every cache and stops its expiry timer.
540
594
  *
541
- * loading-cache reschedules that timer indefinitely, so a Node process will not exit until
542
- * this is called - see {@link shutdown}.
595
+ * Expiry timers are unref'd in Node, so idle processes can exit without this cleanup.
596
+ * Use {@link shutdown} to also stop requests and the shared Ticker.
543
597
  */
544
598
  static end() {
545
599
  for (const cache of this.all) {
@@ -553,20 +607,6 @@ var Caching = class {
553
607
  };
554
608
  }
555
609
  };
556
- Caching.rawImageCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(5)).buildAsync();
557
- Caching.imageDataCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
558
- Caching.canvasImageDataCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
559
- Caching.wrappedImageCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(10)).buildAsync();
560
- Caching.boxGeometryCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(20)).build();
561
- Caching.textureCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
562
- Caching.materialCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
563
- Caching.boxMeshCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).build();
564
- Caching.textureAssetCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
565
- Caching.textureMetaCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
566
- Caching.rawModelCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
567
- Caching.mergedModelCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
568
- Caching.modelTextureAtlasCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
569
- Caching.blockStateCache = import_loading_cache.Caches.builder().expireAfterWrite(import_time.Time.minutes(10)).expireAfterAccess(import_time.Time.minutes(5)).expirationInterval(import_time.Time.seconds(30)).buildAsync();
570
610
 
571
611
  // src/Geometries.ts
572
612
  var Geometries = class _Geometries {
@@ -587,13 +627,14 @@ var Geometries = class _Geometries {
587
627
  };
588
628
 
589
629
  // src/Materials.ts
590
- var import_three6 = require("three");
630
+ var import_three5 = require("three");
591
631
 
592
632
  // src/texture/Textures.ts
593
- var import_three5 = require("three");
633
+ var import_three4 = require("three");
594
634
 
595
635
  // src/texture/TextureLoader.ts
596
- var import_three4 = require("three");
636
+ var import_three3 = require("three");
637
+ var THREE = __toESM(require("three"));
597
638
 
598
639
  // src/canvas/CanvasCompat.ts
599
640
  function createImage(width, height) {
@@ -604,9 +645,7 @@ function createCanvas2(width, height) {
604
645
  }
605
646
 
606
647
  // src/request/Requests.ts
607
- var import_axios = __toESM(require("axios"));
608
648
  var import_jobqu = require("jobqu");
609
- var import_time2 = require("@inventivetalent/time");
610
649
 
611
650
  // src/util/log.ts
612
651
  var Reset = "\x1B[0m";
@@ -616,198 +655,174 @@ function prefix(prefix2) {
616
655
  return `${FgGreen}MR${BgBlack}${prefix2 ?? ""}${Reset}`;
617
656
  }
618
657
 
619
- // src/util/BatchedExecutor.ts
620
- var BatchedExecutor = class {
621
- constructor(interval = 1, batch = 30) {
622
- this.interval = interval;
623
- this.batch = batch;
624
- this.queue = [];
625
- this.task = setInterval(() => this.run());
626
- }
627
- submit(task) {
628
- this.queue.push(task);
629
- }
630
- run() {
631
- for (let i = 0; i < this.batch; i++) {
632
- this.runNext();
633
- }
634
- }
635
- runNext() {
636
- let next = this.queue.shift();
637
- if (next) next();
658
+ // src/request/Requests.ts
659
+ var p = prefix("Requests");
660
+ var RequestError = class extends Error {
661
+ constructor(message, response, cause) {
662
+ super(message);
663
+ this.response = response;
664
+ this.cause = cause;
665
+ this.name = "RequestError";
638
666
  }
639
667
  };
640
-
641
- // src/util/model.ts
642
- var import_three3 = require("three");
643
- function applyElementRotation(rotation, geometry) {
644
- const origin = new import_three3.Vector3(rotation.origin[0], rotation.origin[1], rotation.origin[2]);
645
- geometry.translate(-origin.x, -origin.y, -origin.z);
646
- switch (rotation.axis) {
647
- case "X" /* X */:
648
- geometry.rotateX(toRadians(rotation.angle));
649
- break;
650
- case "y" /* Y */:
651
- geometry.rotateY(toRadians(rotation.angle));
652
- break;
653
- case "z" /* Z */:
654
- geometry.rotateZ(toRadians(rotation.angle));
655
- break;
656
- }
657
- if (rotation.rescale) {
658
- if (Math.abs(rotation.angle) === 22.5) {
659
- const s = 1 / Math.cos(0.39269909262657166);
660
- geometry.scale(s, 1, s);
661
- } else {
662
- const s = 1 / Math.cos(0.7853981852531433);
663
- geometry.scale(s, 1, s);
668
+ async function fetchRequest(config, defaultBaseURL) {
669
+ const { url, baseURL = defaultBaseURL, timeout = 5e3, responseType = "json", signal, ...options } = config;
670
+ const target = baseURL && !/^([a-z][a-z\d+.-]*:|\/\/)/i.test(url) ? `${baseURL.replace(/\/+$/, "")}/${url.replace(/^\/+/, "")}` : url;
671
+ const headers = new Headers(options.headers);
672
+ if (typeof window === "undefined" && !headers.has("User-Agent")) {
673
+ headers.set("User-Agent", "MineRender");
674
+ }
675
+ const attemptSignal = AbortSignal.any([
676
+ ...signal ? [signal] : [],
677
+ ...timeout === 0 ? [] : [AbortSignal.timeout(timeout)]
678
+ ]);
679
+ const request = new Request(target, { ...options, headers, signal: attemptSignal });
680
+ attemptSignal.throwIfAborted();
681
+ try {
682
+ const response = await fetch(request);
683
+ const result = {
684
+ data: void 0,
685
+ status: response.status,
686
+ statusText: response.statusText,
687
+ headers: response.headers,
688
+ url: response.url
689
+ };
690
+ if (!response.ok) {
691
+ await response.body?.cancel().catch(() => {
692
+ });
693
+ throw new RequestError(`Request failed with status ${response.status}`, result);
694
+ }
695
+ const emptyBody = request.method === "HEAD" || response.status === 204 || response.status === 205;
696
+ const data = responseType === "arraybuffer" ? await response.arrayBuffer() : emptyBody || response.body === null ? void 0 : await response.json();
697
+ return { ...result, data };
698
+ } catch (error) {
699
+ attemptSignal.throwIfAborted();
700
+ if (/^https?:/.test(request.url) && request.redirect !== "error" && error instanceof TypeError) {
701
+ throw new RequestError("Network request failed", void 0, error);
664
702
  }
703
+ throw error;
665
704
  }
666
- geometry.translate(origin.x, origin.y, origin.z);
667
- }
668
- function applyModelPartRotation(modelPart, geometry) {
669
- const origin = new import_three3.Vector3(modelPart.pivotX, modelPart.pivotY, modelPart.pivotZ);
670
- geometry.translate(-origin.x, -origin.y, -origin.z);
671
- geometry.rotateX(toRadians(modelPart.pitch));
672
- geometry.rotateY(toRadians(modelPart.yaw));
673
- geometry.rotateZ(toRadians(modelPart.roll));
674
- geometry.translate(origin.x, origin.y, origin.z);
675
705
  }
676
- function applyGenericRotation(axis, rotation, obj) {
677
- switch (axis) {
678
- case "X" /* X */:
679
- obj.rotateOnAxis(new import_three3.Vector3(1, 0, 0), toRadians(rotation));
680
- break;
681
- case "y" /* Y */:
682
- obj.rotateOnAxis(new import_three3.Vector3(0, 1, 0), toRadians(rotation));
683
- break;
684
- case "z" /* Z */:
685
- obj.rotateOnAxis(new import_three3.Vector3(0, 0, 1), toRadians(rotation));
686
- break;
706
+ async function abortable(promise, signal) {
707
+ if (!signal) return promise;
708
+ let abort;
709
+ const cancelled = new Promise((_, reject) => {
710
+ abort = () => reject(signal.reason);
711
+ signal.addEventListener("abort", abort, { once: true });
712
+ if (signal.aborted) abort();
713
+ });
714
+ try {
715
+ return await Promise.race([promise, cancelled]);
716
+ } finally {
717
+ signal.removeEventListener("abort", abort);
687
718
  }
688
719
  }
689
- function addBox3WireframeToObject(box, obj, color = 16777215, w = 2) {
690
- let size = new import_three3.Vector3();
691
- box.getSize(size);
692
- let boxGeo = new import_three3.BoxGeometry(size.x, size.y, size.z, 1, 1, 1);
693
- let wireGeo = new import_three3.EdgesGeometry(boxGeo);
694
- let wireMat = new import_three3.LineBasicMaterial({ color, linewidth: w });
695
- let wireframe = new import_three3.LineSegments(wireGeo, wireMat);
696
- obj.add(wireframe);
697
- let axes = new import_three3.AxesHelper(1);
698
- obj.add(axes);
699
- }
700
- function addWireframeToObject(obj, color = 16777215, w = 2) {
701
- let boxGeo = new import_three3.BoxGeometry(16, 16, 16, 1, 1, 1);
702
- let wireGeo = new import_three3.EdgesGeometry(boxGeo);
703
- let wireMat = new import_three3.LineBasicMaterial({ color, linewidth: w });
704
- let wireframe = new import_three3.LineSegments(wireGeo, wireMat);
705
- obj.add(wireframe);
706
- let axes = new import_three3.AxesHelper(1);
707
- obj.add(axes);
708
- }
709
- function addWireframeToMesh(geo, mesh, color = 16777215, w = 2) {
710
- let wireGeo = new import_three3.EdgesGeometry(geo);
711
- let wireMat = new import_three3.LineBasicMaterial({ color, linewidth: w });
712
- let wireframe = new import_three3.LineSegments(wireGeo, wireMat);
713
- mesh.add(wireframe);
714
- let axes = new import_three3.AxesHelper(1);
715
- mesh.add(axes);
716
- }
717
-
718
- // src/util/performance.ts
719
- function captureException(e, ...extra) {
720
- console.error(e, extra);
721
- }
722
- function timingStart(marker) {
723
- console.time(marker);
724
- }
725
- function timingEnd(marker) {
726
- console.timeEnd(marker);
727
- }
728
-
729
- // src/util/three.ts
730
- function isObject3D(obj) {
731
- return obj.isObject3D;
732
- }
733
- function isMesh(obj) {
734
- return obj.isMesh;
735
- }
736
- function isInstancedMesh(obj) {
737
- return obj.isInstancedMesh;
738
- }
739
- function isPerspectiveCamera(obj) {
740
- return obj.isPerspectiveCamera;
741
- }
742
- function isOrthographicCamera(obj) {
743
- return obj.isOrthographicCamera;
744
- }
745
-
746
- // src/request/Requests.ts
747
- var p = prefix("Requests");
748
- if (typeof window === "undefined") {
749
- import_axios.default.defaults.headers["User-Agent"] = "MineRender";
750
- }
751
- var _Requests = class _Requests {
752
- static genericRequest(request) {
753
- return this.genericQueue.add(request).catch(async (e) => {
754
- console.debug(p, "generic catch", e.code, e);
755
- if (this.shouldRetry(e, request)) {
756
- await sleep(100);
757
- return this.genericRequest(request);
758
- }
759
- throw e;
760
- });
761
- }
762
- static mcAssetRequest(request) {
763
- return this.mcAssetRequestQueue.add(request).catch((e) => {
764
- console.debug(p, "mcAssetRequest catch", e.code, e);
765
- throw e;
766
- });
720
+ var RequestQueue = class {
721
+ constructor() {
722
+ this.pendingRequests = 0;
723
+ this.stopped = new AbortController();
724
+ this.queue = new import_jobqu.JobQueue(
725
+ (request) => fetchRequest(request, this.baseURL),
726
+ { interval: 10, maxPerRun: 1, maxActive: 8 }
727
+ );
767
728
  }
768
- static shouldRetry(e, request) {
769
- if ("code" in e) {
770
- if ("ECONNABORTED" === e.code) {
771
- if ("minerenderRetry" in request) {
772
- if (request["minerenderRetry"] > 0) {
773
- request["minerenderRetry"]--;
774
- return true;
729
+ async request(request) {
730
+ this.pendingRequests++;
731
+ const signal = request.signal;
732
+ try {
733
+ for (let retries = 0; ; retries++) {
734
+ signal?.throwIfAborted();
735
+ try {
736
+ return await abortable(this.queue.add(request), signal);
737
+ } catch (error) {
738
+ console.debug(p, "Request failed", error);
739
+ const delay = this.retryDelay(error, request, retries);
740
+ if (delay === void 0) {
741
+ throw error;
775
742
  }
776
- } else {
777
- request["minerenderRetry"] = 3;
778
- return true;
743
+ await this.waitForRetry(delay, signal);
779
744
  }
780
745
  }
746
+ } finally {
747
+ if (signal?.aborted) {
748
+ this.queue.remove(request);
749
+ }
750
+ this.pendingRequests--;
781
751
  }
782
- return false;
752
+ }
753
+ retryDelay(error, request, retries) {
754
+ if (this.stopped.signal.aborted || retries >= 3 || (request.method ?? "get").toLowerCase() !== "get" || request.signal?.aborted) {
755
+ return void 0;
756
+ }
757
+ if (error instanceof RequestError) {
758
+ const status = error.response?.status;
759
+ if (status !== void 0 && status !== 408 && status !== 429 && !(status >= 500 && status < 600)) return void 0;
760
+ } else if (!(error instanceof DOMException && error.name === "TimeoutError")) {
761
+ return void 0;
762
+ }
763
+ let delay = 100 * 2 ** retries;
764
+ const retryAfter = error instanceof RequestError ? error.response?.headers.get("Retry-After") : void 0;
765
+ if (retryAfter !== void 0 && retryAfter !== null) {
766
+ const seconds = Number(retryAfter);
767
+ if (!retryAfter.trim() || !Number.isFinite(seconds) || seconds < 0) {
768
+ return void 0;
769
+ }
770
+ delay = Math.max(delay, seconds * 1e3);
771
+ }
772
+ return delay;
773
+ }
774
+ async waitForRetry(delay, signal) {
775
+ let timer;
776
+ const waiting = new Promise((resolve) => {
777
+ timer = setTimeout(resolve, delay);
778
+ });
779
+ try {
780
+ await abortable(waiting, AbortSignal.any([this.stopped.signal, ...signal ? [signal] : []]));
781
+ } finally {
782
+ clearTimeout(timer);
783
+ }
784
+ }
785
+ get pendingSize() {
786
+ return this.pendingRequests;
787
+ }
788
+ end() {
789
+ this.queue.end();
790
+ this.stopped.abort(new import_jobqu.JobCancelledError("ended"));
791
+ }
792
+ };
793
+ var Requests = class {
794
+ static {
795
+ this.genericQueue = new RequestQueue();
796
+ }
797
+ static {
798
+ this.mcAssetRequestQueue = new RequestQueue();
799
+ }
800
+ static genericRequest(request) {
801
+ return this.genericQueue.request(request);
802
+ }
803
+ static mcAssetRequest(request) {
804
+ return this.mcAssetRequestQueue.request(request);
783
805
  }
784
806
  static setMcAssetRoot(root) {
785
- this.mcAssetInstance.defaults.baseURL = root;
807
+ this.mcAssetRequestQueue.baseURL = root;
786
808
  }
809
+ /** Counts unsettled calls, including retry delays and requests still running after shutdown. */
787
810
  static get queueSizes() {
788
811
  return {
789
- generic: this.genericQueue.size,
790
- mcAsset: this.mcAssetRequestQueue.size
812
+ generic: this.genericQueue.pendingSize,
813
+ mcAsset: this.mcAssetRequestQueue.pendingSize
791
814
  };
792
815
  }
793
816
  /**
794
- * Stops both queue timers. jobqu reschedules itself indefinitely, so a Node process will not
795
- * exit until this is called - see {@link shutdown}.
817
+ * Permanently stops both queues and rejects waiting, retrying, and future requests.
818
+ * Requests already running can finish. Idle queues hold no timer, so Node can exit without
819
+ * this cleanup. See {@link shutdown}.
796
820
  */
797
821
  static end() {
798
822
  this.genericQueue.end();
799
823
  this.mcAssetRequestQueue.end();
800
824
  }
801
825
  };
802
- _Requests.axiosInstance = import_axios.default.create({
803
- timeout: 5e3
804
- });
805
- _Requests.mcAssetInstance = import_axios.default.create({
806
- timeout: 5e3
807
- });
808
- _Requests.genericQueue = new import_jobqu.JobQueue((request) => _Requests.axiosInstance.request(request), import_time2.Time.millis(10), 1);
809
- _Requests.mcAssetRequestQueue = new import_jobqu.JobQueue((request) => _Requests.mcAssetInstance.request(request), import_time2.Time.millis(10), 1);
810
- var Requests = _Requests;
811
826
 
812
827
  // src/WrappedImage.ts
813
828
  var WrappedImage = class {
@@ -872,29 +887,41 @@ var ImageLoader = class _ImageLoader {
872
887
  static async loadAsync(src) {
873
888
  return new Promise((resolve, reject) => {
874
889
  const image = this._createImage();
875
- image.src = src;
876
890
  image.onload = () => resolve(image);
877
- image.onerror = (err) => reject(err);
891
+ image.onerror = (err) => reject(err instanceof Error ? err : new Error("Failed to decode image"));
892
+ image.src = src;
878
893
  });
879
894
  }
880
895
  static loadElement(src, onload, onerr) {
881
896
  const image = this._createImage();
882
- image.src = src;
883
897
  if (onload)
884
898
  image.onload = onload;
885
899
  if (onerr)
886
900
  image.onerror = onerr;
901
+ image.src = src;
887
902
  return image;
888
903
  }
889
904
  static async loadData(src) {
890
905
  console.debug(p2, "loadData", src);
891
- return await this.infoToData(await this.getInfo(src));
906
+ const image = await this.loadCanvasData(src);
907
+ return image.data.getImageData(0, 0, image.width, image.height);
892
908
  }
893
909
  static async loadCanvasData(src) {
894
- return await this.infoToCanvasData(await this.getInfo(src));
910
+ const keyStr = serializeImageKey({ src });
911
+ const info = this.getInfo(src);
912
+ const cached = Caching.rawImageCache.getIfPresent(keyStr);
913
+ try {
914
+ return await this.infoToCanvasData(await info);
915
+ } catch (err) {
916
+ if (cached && Caching.rawImageCache.getIfPresent(keyStr) === cached) {
917
+ Caching.rawImageCache.invalidate(keyStr);
918
+ }
919
+ throw err;
920
+ }
895
921
  }
896
922
  static async infoToCanvasData(info) {
897
- const image = await _ImageLoader.loadAsync(info.src);
923
+ const type = info.type === "jpg" ? "jpeg" : info.type ?? "png";
924
+ const image = await _ImageLoader.loadAsync(`data:image/${type};base64,${info.data.toString("base64")}`);
898
925
  const canvas = createCanvas2(info.width, info.height);
899
926
  const context = canvas.getContext("2d");
900
927
  context.drawImage(image, 0, 0);
@@ -905,11 +932,8 @@ var ImageLoader = class _ImageLoader {
905
932
  };
906
933
  }
907
934
  static async infoToData(info) {
908
- const image = await _ImageLoader.loadAsync(info.src);
909
- const canvas = createCanvas2(info.width, info.height);
910
- const context = canvas.getContext("2d");
911
- context.drawImage(image, 0, 0);
912
- return context.getImageData(0, 0, canvas.width, canvas.height);
935
+ const image = await this.infoToCanvasData(info);
936
+ return image.data.getImageData(0, 0, image.width, image.height);
913
937
  }
914
938
  static async getData(src) {
915
939
  const keyStr = serializeImageKey({ src });
@@ -924,38 +948,25 @@ var ImageLoader = class _ImageLoader {
924
948
  });
925
949
  }
926
950
  static async processResponse(response) {
927
- const src = response.config.url;
951
+ const src = response.url;
928
952
  const data = import_buffer.Buffer.from(response.data);
929
953
  const { width, height, type } = Env.provider.imageSize(data);
954
+ if (!width || !height) {
955
+ throw new Error("Invalid or unsupported image dimensions");
956
+ }
930
957
  return {
931
958
  src,
932
- width: width || 0,
933
- height: height || 0,
959
+ width,
960
+ height,
934
961
  type,
935
962
  data
936
963
  };
937
964
  }
938
965
  static async loadInfo(src) {
939
- if (src.startsWith("data:image/png;base64")) {
940
- return this.processResponse({
941
- config: {
942
- url: src
943
- },
944
- data: import_buffer.Buffer.from(src.substr("data:image/png;base64,".length), "base64")
945
- });
946
- }
947
966
  return Requests.genericRequest({
948
967
  url: src,
949
968
  responseType: "arraybuffer"
950
- }).then(this.processResponse).catch((err) => {
951
- return {
952
- src,
953
- width: 0,
954
- height: 0,
955
- type: void 0,
956
- data: import_buffer.Buffer.from([0])
957
- };
958
- });
969
+ }).then(this.processResponse);
959
970
  }
960
971
  static async getInfo(src) {
961
972
  const keyStr = serializeImageKey({ src });
@@ -977,25 +988,39 @@ var ImageLoader = class _ImageLoader {
977
988
 
978
989
  // src/texture/TextureLoader.ts
979
990
  var TextureLoader = class {
991
+ static {
992
+ this.failedTextures = /* @__PURE__ */ new WeakSet();
993
+ }
994
+ /** Reports whether image loading failed, so cached textures can be retried. */
995
+ static hasFailed(texture) {
996
+ return this.failedTextures.has(texture);
997
+ }
980
998
  static createTexture() {
981
- return new import_three4.Texture();
999
+ return new import_three3.Texture();
982
1000
  }
983
- static loadInBackground(src, format = import_three4.RGBAFormat, rotation = 0) {
1001
+ static loadInBackground(src, format = import_three3.RGBAFormat, rotation = 0) {
984
1002
  const texture = this.createTexture();
985
- const image = ImageLoader.loadElement(src);
986
- image.onload = function() {
1003
+ texture.colorSpace = THREE.SRGBColorSpace;
1004
+ const image = ImageLoader.loadElement(src, () => {
987
1005
  texture.needsUpdate = true;
988
- };
1006
+ }, (error) => {
1007
+ this.failedTextures.add(texture);
1008
+ console.warn("Failed to load texture", src, error);
1009
+ });
989
1010
  texture.image = image;
990
1011
  texture.format = format;
991
1012
  texture.rotation = rotation;
992
1013
  return Textures.initTextureProps(texture);
993
1014
  }
994
- static load(src, format = import_three4.RGBAFormat, rotation = 0) {
995
- const texture = new import_three4.Texture();
1015
+ static load(src, format = import_three3.RGBAFormat, rotation = 0) {
1016
+ const texture = new import_three3.Texture();
1017
+ texture.colorSpace = THREE.SRGBColorSpace;
996
1018
  ImageLoader.getData(src).then((image) => {
997
- texture.needsUpdate = true;
998
1019
  texture.image = image;
1020
+ texture.needsUpdate = true;
1021
+ }).catch((error) => {
1022
+ this.failedTextures.add(texture);
1023
+ console.warn("Failed to load texture", src, error);
999
1024
  });
1000
1025
  texture.format = format;
1001
1026
  texture.rotation = rotation;
@@ -1004,11 +1029,11 @@ var TextureLoader = class {
1004
1029
  };
1005
1030
 
1006
1031
  // src/texture/Textures.ts
1007
- var THREE = __toESM(require("three"));
1032
+ var THREE2 = __toESM(require("three"));
1008
1033
  var Textures = class _Textures {
1009
1034
  static initTextureProps(texture) {
1010
- texture.magFilter = THREE.NearestFilter;
1011
- texture.minFilter = THREE.NearestFilter;
1035
+ texture.magFilter = THREE2.NearestFilter;
1036
+ texture.minFilter = THREE2.NearestFilter;
1012
1037
  texture.anisotropy = 0;
1013
1038
  return texture;
1014
1039
  }
@@ -1016,13 +1041,19 @@ var Textures = class _Textures {
1016
1041
  return TextureLoader.load(key.src, key.format, key.rotation);
1017
1042
  }
1018
1043
  static createAsset(key) {
1019
- return new import_three5.Texture();
1044
+ return new import_three4.Texture();
1020
1045
  }
1021
1046
  static createCanvasTexture(canvas) {
1022
- return this.initTextureProps(new import_three5.CanvasTexture(canvas));
1047
+ const texture = new import_three4.CanvasTexture(canvas);
1048
+ texture.colorSpace = THREE2.SRGBColorSpace;
1049
+ return this.initTextureProps(texture);
1023
1050
  }
1024
1051
  static getImage(key) {
1025
1052
  const keyStr = serializeTextureKey(key);
1053
+ const cached = Caching.textureCache.peek(keyStr);
1054
+ if (cached && TextureLoader.hasFailed(cached)) {
1055
+ Caching.textureCache.invalidate(keyStr);
1056
+ }
1026
1057
  return Caching.textureCache.get(keyStr, (k) => {
1027
1058
  return _Textures.createImage(key);
1028
1059
  });
@@ -1030,7 +1061,10 @@ var Textures = class _Textures {
1030
1061
  };
1031
1062
 
1032
1063
  // src/Materials.ts
1033
- var _Materials = class _Materials {
1064
+ var Materials = class _Materials {
1065
+ static {
1066
+ this.MISSING_TEXTURE_SRC = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX/AP8AAACfphTyAAAAFUlEQVQoz2MIhQKGVVAwKjIqQrwIAHRz/wFI17TEAAAAAElFTkSuQmCC";
1067
+ }
1034
1068
  // resolved lazily: as a static field this decoded an image the moment the library was
1035
1069
  // imported, which needs both a DOM and an EnvProvider to already be in place
1036
1070
  static get MISSING_TEXTURE() {
@@ -1038,26 +1072,26 @@ var _Materials = class _Materials {
1038
1072
  }
1039
1073
  static createImage(key) {
1040
1074
  const transparent = key.transparent || false;
1041
- return new import_three6.MeshBasicMaterial({
1075
+ return new import_three5.MeshBasicMaterial({
1042
1076
  map: Textures.getImage(key.texture),
1043
1077
  transparent,
1044
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1078
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1045
1079
  alphaTest: 0.5
1046
1080
  });
1047
1081
  }
1048
1082
  static createBasicCanvasMaterial(canvas, transparent = false, shade = false) {
1049
1083
  if (shade) {
1050
- return new import_three6.MeshStandardMaterial({
1084
+ return new import_three5.MeshStandardMaterial({
1051
1085
  map: Textures.createCanvasTexture(canvas),
1052
1086
  transparent,
1053
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1087
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1054
1088
  alphaTest: 0.5
1055
1089
  });
1056
1090
  }
1057
- return new import_three6.MeshBasicMaterial({
1091
+ return new import_three5.MeshBasicMaterial({
1058
1092
  map: Textures.createCanvasTexture(canvas),
1059
1093
  transparent,
1060
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1094
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1061
1095
  alphaTest: 0.5
1062
1096
  });
1063
1097
  }
@@ -1136,16 +1170,19 @@ var _Materials = class _Materials {
1136
1170
  gl_FragColor = vec4(lift + color.rgb * light2, 1.0);
1137
1171
 
1138
1172
  }
1173
+
1174
+ #include <tonemapping_fragment>
1175
+ #include <colorspace_fragment>
1139
1176
  }
1140
1177
  `;
1141
1178
  try {
1142
- return new import_three6.ShaderMaterial({
1179
+ return new import_three5.ShaderMaterial({
1143
1180
  uniforms: {
1144
1181
  SHADE: { value: true },
1145
1182
  BRIGHTNESS: { value: 1 },
1146
1183
  EMISSIVE: { value: false },
1147
1184
  base: {
1148
- value: new import_three6.Color(12698049)
1185
+ value: new import_three5.Color(12698049)
1149
1186
  /*TODO*/
1150
1187
  },
1151
1188
  map: { value: Textures.createCanvasTexture(canvas) }
@@ -1154,7 +1191,7 @@ var _Materials = class _Materials {
1154
1191
  fragmentShader: fragShader,
1155
1192
  vertexColors: true,
1156
1193
  transparent,
1157
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1194
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1158
1195
  alphaTest: 0.5
1159
1196
  });
1160
1197
  } catch (e) {
@@ -1164,6 +1201,10 @@ var _Materials = class _Materials {
1164
1201
  }
1165
1202
  static getImage(key) {
1166
1203
  const keyStr = serializeMaterialKey(key);
1204
+ const map = Caching.materialCache.peek(keyStr)?.map;
1205
+ if (map && TextureLoader.hasFailed(map)) {
1206
+ Caching.materialCache.invalidate(keyStr);
1207
+ }
1167
1208
  return Caching.materialCache.get(keyStr, (k) => {
1168
1209
  return _Materials.createImage(key);
1169
1210
  });
@@ -1184,14 +1225,12 @@ var _Materials = class _Materials {
1184
1225
  }
1185
1226
  }
1186
1227
  };
1187
- _Materials.MISSING_TEXTURE_SRC = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX/AP8AAACfphTyAAAAFUlEQVQoz2MIhQKGVVAwKjIqQrwIAHRz/wFI17TEAAAAAElFTkSuQmCC";
1188
- var Materials = _Materials;
1189
1228
 
1190
1229
  // src/Meshes.ts
1191
- var import_three7 = require("three");
1230
+ var import_three6 = require("three");
1192
1231
  var Meshes = class _Meshes {
1193
1232
  static createBox(key) {
1194
- return new import_three7.Mesh(Geometries.getBox(key.geometry), Materials.getImage(key.material));
1233
+ return new import_three6.Mesh(Geometries.getBox(key.geometry), Materials.getImage(key.material));
1195
1234
  }
1196
1235
  static getBox(key) {
1197
1236
  const keyStr = serializeMeshKey(key);
@@ -1240,7 +1279,7 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1240
1279
  this.root = root;
1241
1280
  }
1242
1281
  static parse(assetType, str, origin) {
1243
- let namespace = (origin == null ? void 0 : origin.namespace) || DEFAULT_NAMESPACE;
1282
+ let namespace = origin?.namespace || DEFAULT_NAMESPACE;
1244
1283
  if (str.includes(":")) {
1245
1284
  let split2 = str.split(":");
1246
1285
  namespace = split2[0];
@@ -1253,8 +1292,8 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1253
1292
  split.shift();
1254
1293
  }
1255
1294
  let path = split.join("/");
1256
- let extension = assetType === "textures" ? ".png" : (origin == null ? void 0 : origin.assetType) || ".json";
1257
- return new _AssetKey(namespace, path, assetType, type, "assets", extension, origin == null ? void 0 : origin.root);
1295
+ let extension = assetType === "textures" ? ".png" : origin?.assetType || ".json";
1296
+ return new _AssetKey(namespace, path, assetType, type, "assets", extension, origin?.root);
1258
1297
  }
1259
1298
  toString() {
1260
1299
  let a = [
@@ -1268,12 +1307,12 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1268
1307
  return a.join("/");
1269
1308
  }
1270
1309
  getFullPath() {
1271
- let p13 = [];
1310
+ let p12 = [];
1272
1311
  if (this.type) {
1273
- p13.push(this.type);
1312
+ p12.push(this.type);
1274
1313
  }
1275
- p13.push(this.path);
1276
- return p13.join("/");
1314
+ p12.push(this.path);
1315
+ return p12.join("/");
1277
1316
  }
1278
1317
  toNamespacedString() {
1279
1318
  return this.namespace + ":" + this.getFullPath();
@@ -1298,7 +1337,7 @@ var ModelMerger = class {
1298
1337
  merged = (0, import_ts_deepmerge.default)(merged, parentModel);
1299
1338
  }
1300
1339
  merged = (0, import_ts_deepmerge.default)(merged, model);
1301
- merged.hierarchy = models.map((m) => m.parent).filter((p13) => `${p13}`);
1340
+ merged.hierarchy = models.map((m) => m.parent).filter((p12) => `${p12}`);
1302
1341
  merged.hierarchy.push(`${merged.parent}`);
1303
1342
  return merged;
1304
1343
  }
@@ -1317,9 +1356,6 @@ var ModelMerger = class {
1317
1356
  }
1318
1357
  };
1319
1358
 
1320
- // src/assets/Models.ts
1321
- var import_typescript_memoize = require("typescript-memoize");
1322
-
1323
1359
  // src/assets/source/parser/AssetParsers.ts
1324
1360
  var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1325
1361
  AssetParser2["MODEL"] = "model";
@@ -1333,14 +1369,14 @@ var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1333
1369
  })(AssetParser || {});
1334
1370
 
1335
1371
  // src/assets/Models.ts
1336
- var _Models = class _Models {
1372
+ var Models = class _Models {
1337
1373
  // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading
1338
1374
  // the library, and would require an EnvProvider before any entry has had a chance to register
1339
1375
  static get PERSISTENT_CACHE() {
1340
1376
  return this._persistentCache ??= PersistentCache.open("minerender-models");
1341
1377
  }
1342
1378
  static async getItemList() {
1343
- return AssetLoader.get(new AssetKey(
1379
+ const key = new AssetKey(
1344
1380
  DEFAULT_NAMESPACE,
1345
1381
  "_list",
1346
1382
  "models",
@@ -1348,7 +1384,10 @@ var _Models = class _Models {
1348
1384
  "assets",
1349
1385
  ".json",
1350
1386
  DEFAULT_ROOT
1351
- ), "list" /* LIST */).then((r) => (r == null ? void 0 : r.files) ?? []);
1387
+ );
1388
+ return Caching.listAssetCache.get(key.serialize(), () => {
1389
+ return AssetLoader.get(key, "list" /* LIST */);
1390
+ }).then((r) => r?.files ?? []);
1352
1391
  }
1353
1392
  static async loadAndMerge(key) {
1354
1393
  const model = await this.getRaw(key);
@@ -1395,19 +1434,15 @@ var _Models = class _Models {
1395
1434
  return this.PERSISTENT_CACHE.clear();
1396
1435
  }
1397
1436
  };
1398
- __decorateClass([
1399
- (0, import_typescript_memoize.Memoize)()
1400
- ], _Models, "getItemList", 1);
1401
- var Models = _Models;
1402
1437
 
1403
1438
  // src/assets/BlockStates.ts
1404
- var import_typescript_memoize2 = require("typescript-memoize");
1405
1439
  var BlockStates = class {
1406
1440
  static get PERSISTENT_CACHE() {
1407
1441
  return this._persistentCache ??= PersistentCache.open("minerender-blockstates");
1408
1442
  }
1443
+ // BlockState names are hardcoded
1409
1444
  static async getList() {
1410
- return AssetLoader.get(new AssetKey(
1445
+ const key = new AssetKey(
1411
1446
  DEFAULT_NAMESPACE,
1412
1447
  "_list",
1413
1448
  "blockstates",
@@ -1415,11 +1450,16 @@ var BlockStates = class {
1415
1450
  "assets",
1416
1451
  ".json",
1417
1452
  DEFAULT_ROOT
1418
- ), "list" /* LIST */).then((r) => (r == null ? void 0 : r.files) ?? []);
1453
+ );
1454
+ return Caching.listAssetCache.get(key.serialize(), () => {
1455
+ return AssetLoader.get(key, "list" /* LIST */);
1456
+ }).then((r) => r?.files ?? []);
1419
1457
  }
1420
1458
  static async getDefaultStates() {
1421
1459
  const key = AssetKey.parse("blockstates", "minerender:defaultBlockStates");
1422
- return AssetLoader.get(key, "json" /* JSON */);
1460
+ return Caching.defaultBlockStatesCache.get(key.serialize(), () => {
1461
+ return AssetLoader.get(key, "json" /* JSON */);
1462
+ });
1423
1463
  }
1424
1464
  static async getDefaultState(key) {
1425
1465
  const defaultStates = await this.getDefaultStates();
@@ -1458,12 +1498,6 @@ var BlockStates = class {
1458
1498
  await this.PERSISTENT_CACHE.clear();
1459
1499
  }
1460
1500
  };
1461
- __decorateClass([
1462
- (0, import_typescript_memoize2.Memoize)()
1463
- ], BlockStates, "getList", 1);
1464
- __decorateClass([
1465
- (0, import_typescript_memoize2.Memoize)()
1466
- ], BlockStates, "getDefaultStates", 1);
1467
1501
  var DefaultBlockStates = class {
1468
1502
  };
1469
1503
 
@@ -1490,37 +1524,250 @@ var AssetSource = class {
1490
1524
  constructor() {
1491
1525
  }
1492
1526
  };
1493
-
1494
- // src/nbt/NBTHelper.ts
1495
- var NBTHelper = class {
1496
- static async fromBuffer(buffer) {
1497
- const prismarineNbt = await import("prismarine-nbt");
1498
- const { parsed, type, metadata } = await prismarineNbt.parse(buffer);
1499
- return parsed;
1527
+ var AssetLoadError = class extends Error {
1528
+ constructor(source, key, path, cause) {
1529
+ super(`Failed to load ${key.toNamespacedString()} from ${path}${cause instanceof Error ? `: ${cause.message}` : ""}`);
1530
+ this.source = source;
1531
+ this.key = key;
1532
+ this.path = path;
1533
+ this.cause = cause;
1534
+ this.name = "AssetLoadError";
1500
1535
  }
1501
1536
  };
1502
1537
 
1503
- // src/assets/source/HostedAssetSource.ts
1504
- var import_ts_deepmerge2 = __toESM(require_dist());
1505
- var p3 = prefix("HostedAssetSource");
1506
- var DEFAULT_OPTIONS = {
1507
- retryDefaults: true
1508
- };
1509
- var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1510
- async loadOrRetryWithDefaults(key, parser) {
1511
- const direct = await this.load(key, parser);
1512
- if (typeof direct !== "undefined") {
1513
- return direct;
1538
+ // src/util/BatchedExecutor.ts
1539
+ var BatchedExecutor = class {
1540
+ constructor(interval = 1, batch = 30) {
1541
+ this.interval = interval;
1542
+ this.batch = batch;
1543
+ this.queue = [];
1544
+ this.task = setInterval(() => this.run());
1545
+ }
1546
+ submit(task) {
1547
+ this.queue.push(task);
1548
+ }
1549
+ run() {
1550
+ for (let i = 0; i < this.batch; i++) {
1551
+ this.runNext();
1514
1552
  }
1515
- if (key.namespace !== DEFAULT_NAMESPACE) {
1516
- console.info(p3, "Retrying", key, "with default namespace");
1517
- const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);
1518
- const namespaced = await this.load(namespaceKey, parser);
1519
- if (typeof namespaced !== "undefined") {
1520
- return namespaced;
1521
- }
1522
- if (typeof key.root !== "undefined" && key.root !== DEFAULT_ROOT || typeof this.root !== "undefined" && this.root !== DEFAULT_ROOT) {
1523
- console.info(p3, "Retrying", key, "with default root+namespace");
1553
+ }
1554
+ runNext() {
1555
+ let next = this.queue.shift();
1556
+ if (next) next();
1557
+ }
1558
+ };
1559
+
1560
+ // src/util/model.ts
1561
+ var import_three7 = require("three");
1562
+ function applyElementRotation(rotation, geometry) {
1563
+ const origin = new import_three7.Vector3(rotation.origin[0], rotation.origin[1], rotation.origin[2]);
1564
+ geometry.translate(-origin.x, -origin.y, -origin.z);
1565
+ switch (rotation.axis) {
1566
+ case "X" /* X */:
1567
+ geometry.rotateX(toRadians(rotation.angle));
1568
+ break;
1569
+ case "y" /* Y */:
1570
+ geometry.rotateY(toRadians(rotation.angle));
1571
+ break;
1572
+ case "z" /* Z */:
1573
+ geometry.rotateZ(toRadians(rotation.angle));
1574
+ break;
1575
+ }
1576
+ if (rotation.rescale) {
1577
+ if (Math.abs(rotation.angle) === 22.5) {
1578
+ const s = 1 / Math.cos(0.39269909262657166);
1579
+ geometry.scale(s, 1, s);
1580
+ } else {
1581
+ const s = 1 / Math.cos(0.7853981852531433);
1582
+ geometry.scale(s, 1, s);
1583
+ }
1584
+ }
1585
+ geometry.translate(origin.x, origin.y, origin.z);
1586
+ }
1587
+ function applyModelPartRotation(modelPart, geometry) {
1588
+ const origin = new import_three7.Vector3(modelPart.pivotX, modelPart.pivotY, modelPart.pivotZ);
1589
+ geometry.translate(-origin.x, -origin.y, -origin.z);
1590
+ geometry.rotateX(toRadians(modelPart.pitch));
1591
+ geometry.rotateY(toRadians(modelPart.yaw));
1592
+ geometry.rotateZ(toRadians(modelPart.roll));
1593
+ geometry.translate(origin.x, origin.y, origin.z);
1594
+ }
1595
+ function applyGenericRotation(axis, rotation, obj) {
1596
+ switch (axis) {
1597
+ case "X" /* X */:
1598
+ obj.rotateOnAxis(new import_three7.Vector3(1, 0, 0), toRadians(rotation));
1599
+ break;
1600
+ case "y" /* Y */:
1601
+ obj.rotateOnAxis(new import_three7.Vector3(0, 1, 0), toRadians(rotation));
1602
+ break;
1603
+ case "z" /* Z */:
1604
+ obj.rotateOnAxis(new import_three7.Vector3(0, 0, 1), toRadians(rotation));
1605
+ break;
1606
+ }
1607
+ }
1608
+ function addBox3WireframeToObject(box, obj, color = 16777215, w = 2) {
1609
+ let size = new import_three7.Vector3();
1610
+ box.getSize(size);
1611
+ let boxGeo = new import_three7.BoxGeometry(size.x, size.y, size.z, 1, 1, 1);
1612
+ let wireGeo = new import_three7.EdgesGeometry(boxGeo);
1613
+ let wireMat = new import_three7.LineBasicMaterial({ color, linewidth: w });
1614
+ let wireframe = new import_three7.LineSegments(wireGeo, wireMat);
1615
+ obj.add(wireframe);
1616
+ let axes = new import_three7.AxesHelper(1);
1617
+ obj.add(axes);
1618
+ }
1619
+ function addWireframeToObject(obj, color = 16777215, w = 2) {
1620
+ let boxGeo = new import_three7.BoxGeometry(16, 16, 16, 1, 1, 1);
1621
+ let wireGeo = new import_three7.EdgesGeometry(boxGeo);
1622
+ let wireMat = new import_three7.LineBasicMaterial({ color, linewidth: w });
1623
+ let wireframe = new import_three7.LineSegments(wireGeo, wireMat);
1624
+ obj.add(wireframe);
1625
+ let axes = new import_three7.AxesHelper(1);
1626
+ obj.add(axes);
1627
+ }
1628
+ function addWireframeToMesh(geo, mesh, color = 16777215, w = 2) {
1629
+ let wireGeo = new import_three7.EdgesGeometry(geo);
1630
+ let wireMat = new import_three7.LineBasicMaterial({ color, linewidth: w });
1631
+ let wireframe = new import_three7.LineSegments(wireGeo, wireMat);
1632
+ mesh.add(wireframe);
1633
+ let axes = new import_three7.AxesHelper(1);
1634
+ mesh.add(axes);
1635
+ }
1636
+
1637
+ // src/util/performance.ts
1638
+ function captureException(e, ...extra) {
1639
+ console.error(e, extra);
1640
+ }
1641
+ function timingStart(marker) {
1642
+ console.time(marker);
1643
+ }
1644
+ function timingEnd(marker) {
1645
+ console.timeEnd(marker);
1646
+ }
1647
+
1648
+ // src/util/three.ts
1649
+ function isObject3D(obj) {
1650
+ return obj.isObject3D;
1651
+ }
1652
+ function isMesh(obj) {
1653
+ return obj.isMesh;
1654
+ }
1655
+ function isInstancedMesh(obj) {
1656
+ return obj.isInstancedMesh;
1657
+ }
1658
+ function isPerspectiveCamera(obj) {
1659
+ return obj.isPerspectiveCamera;
1660
+ }
1661
+ function isOrthographicCamera(obj) {
1662
+ return obj.isOrthographicCamera;
1663
+ }
1664
+
1665
+ // src/nbt/NBTHelper.ts
1666
+ var NBTHelper = class {
1667
+ static async fromBuffer(buffer) {
1668
+ const prismarineNbt = await import("prismarine-nbt");
1669
+ const { parsed, type, metadata } = await prismarineNbt.parse(buffer);
1670
+ return parsed;
1671
+ }
1672
+ };
1673
+
1674
+ // src/assets/source/HostedAssetSource.ts
1675
+ var import_ts_deepmerge2 = __toESM(require_dist());
1676
+ var p3 = prefix("HostedAssetSource");
1677
+ var DEFAULT_OPTIONS = {
1678
+ retryDefaults: true
1679
+ };
1680
+ var HostedAssetSource = class _HostedAssetSource extends AssetSource {
1681
+ static {
1682
+ this.MODEL = {
1683
+ config(request) {
1684
+ },
1685
+ parse(response) {
1686
+ return response.data;
1687
+ }
1688
+ };
1689
+ }
1690
+ static {
1691
+ this.BLOCKSTATE = {
1692
+ config(request) {
1693
+ },
1694
+ parse(response) {
1695
+ return response.data;
1696
+ }
1697
+ };
1698
+ }
1699
+ static {
1700
+ this.META = {
1701
+ config(request) {
1702
+ },
1703
+ parse(response) {
1704
+ return response.data;
1705
+ }
1706
+ };
1707
+ }
1708
+ static {
1709
+ this.NBT = {
1710
+ config(request) {
1711
+ request.responseType = "arraybuffer";
1712
+ },
1713
+ parse(response) {
1714
+ return NBTHelper.fromBuffer(Buffer.from(response.data));
1715
+ }
1716
+ };
1717
+ }
1718
+ static {
1719
+ this.IMAGE = {
1720
+ config(request) {
1721
+ request.responseType = "arraybuffer";
1722
+ },
1723
+ async parse(response) {
1724
+ return await ImageLoader.processResponse(response);
1725
+ }
1726
+ };
1727
+ }
1728
+ static {
1729
+ this.LIST = {
1730
+ config(request) {
1731
+ },
1732
+ parse(response) {
1733
+ return response.data;
1734
+ }
1735
+ };
1736
+ }
1737
+ static {
1738
+ this.JSON = {
1739
+ config(request) {
1740
+ },
1741
+ parse(response) {
1742
+ return response.data;
1743
+ }
1744
+ };
1745
+ }
1746
+ static {
1747
+ this.PARSER_MAP = /* @__PURE__ */ new Map([
1748
+ ["model" /* MODEL */, _HostedAssetSource.MODEL],
1749
+ ["blockstate" /* BLOCKSTATE */, _HostedAssetSource.BLOCKSTATE],
1750
+ ["meta" /* META */, _HostedAssetSource.META],
1751
+ ["nbt" /* NBT */, _HostedAssetSource.NBT],
1752
+ ["image" /* IMAGE */, _HostedAssetSource.IMAGE],
1753
+ ["list" /* LIST */, _HostedAssetSource.LIST],
1754
+ ["json" /* JSON */, _HostedAssetSource.JSON]
1755
+ ]);
1756
+ }
1757
+ async loadOrRetryWithDefaults(key, parser) {
1758
+ const direct = await this.load(key, parser);
1759
+ if (typeof direct !== "undefined") {
1760
+ return direct;
1761
+ }
1762
+ if (key.namespace !== DEFAULT_NAMESPACE) {
1763
+ console.info(p3, "Retrying", key, "with default namespace");
1764
+ const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);
1765
+ const namespaced = await this.load(namespaceKey, parser);
1766
+ if (typeof namespaced !== "undefined") {
1767
+ return namespaced;
1768
+ }
1769
+ if (typeof key.root !== "undefined" && key.root !== DEFAULT_ROOT || typeof this.root !== "undefined" && this.root !== DEFAULT_ROOT) {
1770
+ console.info(p3, "Retrying", key, "with default root+namespace");
1524
1771
  const namespacedRootedKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, DEFAULT_ROOT);
1525
1772
  const namespacedRooted = await this.load(namespacedRootedKey, parser);
1526
1773
  if (typeof namespacedRooted !== "undefined") {
@@ -1541,31 +1788,25 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1541
1788
  console.info(p3, "Loading", key);
1542
1789
  const url = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1543
1790
  console.debug(p3, url);
1544
- let req = {
1545
- url
1546
- };
1547
- parser.config(req);
1548
- return await Requests.mcAssetRequest(req).then((response) => {
1549
- if (response && response.data) {
1550
- try {
1551
- return parser.parse(response);
1552
- } catch (e) {
1553
- console.warn("Parser failed to process response", response, e);
1554
- throw e;
1555
- }
1556
- }
1557
- return void 0;
1558
- }).catch((err) => {
1559
- if (err.response) {
1560
- let response = err.response;
1561
- if (response.status === 404) {
1562
- console.debug(p3, key, "not found");
1791
+ const request = { url };
1792
+ try {
1793
+ parser.config(request);
1794
+ let response;
1795
+ try {
1796
+ response = await Requests.mcAssetRequest(request);
1797
+ } catch (cause) {
1798
+ if (cause instanceof RequestError && cause.response?.status === 404) {
1563
1799
  return void 0;
1564
1800
  }
1801
+ throw cause;
1565
1802
  }
1566
- console.debug(p3, "Failed to load", key, err == null ? void 0 : err.message);
1567
- return void 0;
1568
- });
1803
+ if (response.data === void 0) {
1804
+ throw new Error("Asset response has no data");
1805
+ }
1806
+ return await parser.parse(response);
1807
+ } catch (cause) {
1808
+ throw new AssetLoadError(this, key, request.url, cause);
1809
+ }
1569
1810
  }
1570
1811
  assetBasePath(key) {
1571
1812
  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 + "/" : ""}`;
@@ -1589,67 +1830,6 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1589
1830
  return this.load(key, responseParser);
1590
1831
  }
1591
1832
  };
1592
- _HostedAssetSource.MODEL = {
1593
- config(request) {
1594
- },
1595
- parse(response) {
1596
- return response.data;
1597
- }
1598
- };
1599
- _HostedAssetSource.BLOCKSTATE = {
1600
- config(request) {
1601
- },
1602
- parse(response) {
1603
- return response.data;
1604
- }
1605
- };
1606
- _HostedAssetSource.META = {
1607
- config(request) {
1608
- },
1609
- parse(response) {
1610
- return response.data;
1611
- }
1612
- };
1613
- _HostedAssetSource.NBT = {
1614
- config(request) {
1615
- request.responseType = "arraybuffer";
1616
- },
1617
- parse(response) {
1618
- return NBTHelper.fromBuffer(Buffer.from(response.data));
1619
- }
1620
- };
1621
- _HostedAssetSource.IMAGE = {
1622
- config(request) {
1623
- request.responseType = "arraybuffer";
1624
- },
1625
- async parse(response) {
1626
- return await ImageLoader.processResponse(response);
1627
- }
1628
- };
1629
- _HostedAssetSource.LIST = {
1630
- config(request) {
1631
- },
1632
- parse(response) {
1633
- return response.data;
1634
- }
1635
- };
1636
- _HostedAssetSource.JSON = {
1637
- config(request) {
1638
- },
1639
- parse(response) {
1640
- return response.data;
1641
- }
1642
- };
1643
- _HostedAssetSource.PARSER_MAP = /* @__PURE__ */ new Map([
1644
- ["model" /* MODEL */, _HostedAssetSource.MODEL],
1645
- ["blockstate" /* BLOCKSTATE */, _HostedAssetSource.BLOCKSTATE],
1646
- ["meta" /* META */, _HostedAssetSource.META],
1647
- ["nbt" /* NBT */, _HostedAssetSource.NBT],
1648
- ["image" /* IMAGE */, _HostedAssetSource.IMAGE],
1649
- ["list" /* LIST */, _HostedAssetSource.LIST],
1650
- ["json" /* JSON */, _HostedAssetSource.JSON]
1651
- ]);
1652
- var HostedAssetSource = _HostedAssetSource;
1653
1833
 
1654
1834
  // src/assets/source/archive/BrowserArchiveProxy.ts
1655
1835
  var import_zip = require("@zip.js/zip.js");
@@ -1672,7 +1852,6 @@ var BrowserArchiveProxy = class {
1672
1852
  };
1673
1853
 
1674
1854
  // src/assets/source/archive/ArchiveAssetSource.ts
1675
- var p4 = prefix("ArchiveAssetSource");
1676
1855
  var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1677
1856
  constructor(archiveProxy) {
1678
1857
  super();
@@ -1691,74 +1870,31 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1691
1870
  }
1692
1871
  async get(key, parser) {
1693
1872
  const responseParser = HostedAssetSource.PARSER_MAP.get(parser);
1694
- console.log("ArchiveAssetSource.get", key, parser);
1695
- let entries = await this.getEntries();
1696
- const path = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1697
- console.log(path);
1698
- const entry = await this.getEntry(path);
1699
- console.log(entry);
1700
- if (!entry) {
1701
- return void 0;
1702
- }
1703
- let blob = await entry.getData();
1704
- const url = URL.createObjectURL(blob);
1705
- console.log(url);
1706
- let req = {
1707
- url
1708
- };
1709
- responseParser.config(req);
1710
- return Requests.genericRequest(req).then((response) => {
1711
- if (response && response.data) {
1712
- try {
1713
- return responseParser.parse(response);
1714
- } catch (e) {
1715
- console.warn("Parser failed to process response", response, e);
1716
- throw e;
1717
- }
1718
- }
1719
- return void 0;
1720
- }).catch((err) => {
1721
- if (err.response) {
1722
- let response = err.response;
1723
- if (response.status === 404) {
1724
- console.debug(p4, key, "not found");
1725
- return void 0;
1726
- }
1727
- }
1728
- console.debug(p4, "Failed to load", key, err == null ? void 0 : err.message);
1729
- return void 0;
1730
- });
1873
+ return this.load(key, responseParser);
1731
1874
  }
1732
- //TODO: abstract this
1733
1875
  async load(key, parser) {
1734
- console.info(p4, "Loading", key);
1735
- const url = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1736
- console.debug(p4, url);
1737
- let req = {
1738
- url
1739
- };
1740
- parser.config(req);
1741
- return await Requests.genericRequest(req).then((response) => {
1742
- if (response && response.data) {
1743
- try {
1744
- return parser.parse(response);
1745
- } catch (e) {
1746
- console.warn("Parser failed to process response", response, e);
1747
- throw e;
1748
- }
1876
+ const path = `${this.assetBasePath(key)}${key.type !== void 0 ? key.type + "/" : ""}${key.path}${key.extension}`;
1877
+ let url;
1878
+ try {
1879
+ const entry = await this.getEntry(path);
1880
+ if (!entry) {
1881
+ return void 0;
1749
1882
  }
1750
- return void 0;
1751
- }).catch((err) => {
1752
- if (err.response) {
1753
- let response = err.response;
1754
- if (response.status === 404) {
1755
- console.debug(p4, key, "not found");
1756
- return void 0;
1757
- }
1883
+ url = URL.createObjectURL(await entry.getData());
1884
+ const request = { url };
1885
+ parser.config(request);
1886
+ const response = await Requests.genericRequest(request);
1887
+ if (response.data === void 0) {
1888
+ throw new Error("Asset response has no data");
1758
1889
  }
1759
- console.debug(p4, "Failed to load", key, err == null ? void 0 : err.message);
1760
- return void 0;
1761
- });
1890
+ return await parser.parse(response);
1891
+ } catch (cause) {
1892
+ throw new AssetLoadError(this, key, path, cause);
1893
+ } finally {
1894
+ if (url !== void 0) {
1895
+ URL.revokeObjectURL(url);
1896
+ }
1897
+ }
1762
1898
  }
1763
1899
  assetBasePath(key) {
1764
1900
  return `${key.rootType !== void 0 ? key.rootType + "/" : ""}${key.namespace !== void 0 ? key.namespace + "/" : ""}${key.assetType !== void 0 ? key.assetType + "/" : ""}`;
@@ -1766,18 +1902,23 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1766
1902
  };
1767
1903
 
1768
1904
  // src/assets/AssetLoader.ts
1769
- var import_ts_deepmerge3 = __toESM(require_dist());
1770
- var p5 = prefix("AssetLoader");
1771
- var _AssetLoader = class _AssetLoader {
1905
+ var p4 = prefix("AssetLoader");
1906
+ var AssetLoader = class {
1907
+ static {
1908
+ this.ROOT = DEFAULT_ROOT;
1909
+ }
1910
+ static {
1911
+ this._SOURCES = [];
1912
+ }
1772
1913
  static addSource(key, source, override = true) {
1773
1914
  if (override) {
1774
1915
  const existing = this.removeSource(key);
1775
1916
  if (existing) {
1776
- console.log(p5, "Removed existing AssetSource", key);
1917
+ console.log(p4, "Removed existing AssetSource", key);
1777
1918
  }
1778
1919
  }
1779
1920
  this._SOURCES.unshift({ key, source });
1780
- console.log(p5, "Added AssetSource", key);
1921
+ console.log(p4, "Added AssetSource", key);
1781
1922
  }
1782
1923
  static removeSource(key) {
1783
1924
  const index = this._SOURCES.findIndex((s) => s.key === key);
@@ -1789,8 +1930,11 @@ var _AssetLoader = class _AssetLoader {
1789
1930
  }
1790
1931
  return void 0;
1791
1932
  }
1933
+ static {
1934
+ this.addSource("mcassets-fallback", new HostedAssetSource("https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master", { retryDefaults: false }));
1935
+ this.addSource("mcassets", new HostedAssetSource(DEFAULT_ROOT, { retryDefaults: false }));
1936
+ }
1792
1937
  static async getAll(key, parser) {
1793
- console.log(this._SOURCES);
1794
1938
  let promises = [];
1795
1939
  for (const source of this._SOURCES) {
1796
1940
  promises.push(source.source.get(key, parser));
@@ -1799,31 +1943,18 @@ var _AssetLoader = class _AssetLoader {
1799
1943
  return results.filter((r) => r != void 0);
1800
1944
  });
1801
1945
  }
1946
+ /** Returns the first defined result in source-priority order, without merging assets. */
1802
1947
  static async get(key, parser) {
1803
- console.log(this._SOURCES);
1804
- let promises = [];
1805
- for (const source of this._SOURCES) {
1806
- promises.push(source.source.get(key, parser));
1807
- }
1808
- return Promise.all(promises).then((results) => {
1809
- const fallback = results[results.length - 1];
1810
- for (const result of results) {
1811
- if (result) {
1812
- if (fallback) {
1813
- return (0, import_ts_deepmerge3.default)({}, fallback, result);
1814
- }
1815
- return result;
1816
- }
1948
+ const sources = [...this._SOURCES];
1949
+ for (const source of sources) {
1950
+ const result = await source.source.get(key, parser);
1951
+ if (result !== void 0) {
1952
+ return result;
1817
1953
  }
1818
- return void 0;
1819
- });
1954
+ }
1955
+ return void 0;
1820
1956
  }
1821
1957
  };
1822
- _AssetLoader.ROOT = DEFAULT_ROOT;
1823
- _AssetLoader._SOURCES = [];
1824
- _AssetLoader.addSource("mcassets-fallback", new HostedAssetSource("https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master", { retryDefaults: false }));
1825
- _AssetLoader.addSource("mcassets", new HostedAssetSource(DEFAULT_ROOT, { retryDefaults: false }));
1826
- var AssetLoader = _AssetLoader;
1827
1958
 
1828
1959
  // src/assets/ModelTextures.ts
1829
1960
  var ModelTextures = class {
@@ -1831,11 +1962,21 @@ var ModelTextures = class {
1831
1962
  return this._persistentMetaCache ??= PersistentCache.open("minerender-texturemeta");
1832
1963
  }
1833
1964
  static async get(key) {
1834
- const asset = await this.preload(key);
1835
- if (asset) {
1836
- return ImageLoader.infoToCanvasData(asset);
1965
+ const keyStr = key.serialize();
1966
+ const pending = this.preload(key);
1967
+ const cached = Caching.textureAssetCache.getIfPresent(keyStr);
1968
+ try {
1969
+ const asset = await pending;
1970
+ if (asset) {
1971
+ return await ImageLoader.infoToCanvasData(asset);
1972
+ }
1973
+ return void 0;
1974
+ } catch (err) {
1975
+ if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {
1976
+ Caching.textureAssetCache.invalidate(keyStr);
1977
+ }
1978
+ throw err;
1837
1979
  }
1838
- return void 0;
1839
1980
  }
1840
1981
  static async preload(key) {
1841
1982
  const keyStr = key.serialize();
@@ -1909,7 +2050,28 @@ var CanvasImage = class {
1909
2050
  };
1910
2051
 
1911
2052
  // src/Ticker.ts
1912
- var _Ticker = class _Ticker {
2053
+ var Ticker = class _Ticker {
2054
+ static {
2055
+ this.TPS = 20;
2056
+ }
2057
+ static {
2058
+ this.counter = 0;
2059
+ }
2060
+ static {
2061
+ this._tickers = /* @__PURE__ */ new Map();
2062
+ }
2063
+ static {
2064
+ this.oneSecondTps = 0;
2065
+ }
2066
+ static {
2067
+ this.oneSecondTicks = 0;
2068
+ }
2069
+ static {
2070
+ this.fiveSecondTps = 0;
2071
+ }
2072
+ static {
2073
+ this.fiveSecondTicks = 0;
2074
+ }
1913
2075
  static schedule(fn, ms) {
1914
2076
  const handle = setInterval(fn, ms);
1915
2077
  const unref = handle.unref;
@@ -1971,14 +2133,6 @@ var _Ticker = class _Ticker {
1971
2133
  this._tickers.clear();
1972
2134
  }
1973
2135
  };
1974
- _Ticker.TPS = 20;
1975
- _Ticker.counter = 0;
1976
- _Ticker._tickers = /* @__PURE__ */ new Map();
1977
- _Ticker.oneSecondTps = 0;
1978
- _Ticker.oneSecondTicks = 0;
1979
- _Ticker.fiveSecondTps = 0;
1980
- _Ticker.fiveSecondTicks = 0;
1981
- var Ticker = _Ticker;
1982
2136
 
1983
2137
  // src/texture/TextureAtlas.ts
1984
2138
  var TextureAtlas = class {
@@ -2004,6 +2158,9 @@ var TextureAtlas = class {
2004
2158
 
2005
2159
  // src/model/ModelGenerator.ts
2006
2160
  var ModelGenerator = class {
2161
+ static {
2162
+ this.ITEM_LAYERS = ["layer0", "layer1", "layer2", "layer3", "layer4"];
2163
+ }
2007
2164
  static generateItemModel(imageData, layer) {
2008
2165
  const mainElement = {
2009
2166
  from: [0, 0, 7.5],
@@ -2023,10 +2180,9 @@ var ModelGenerator = class {
2023
2180
  return [mainElement];
2024
2181
  }
2025
2182
  };
2026
- ModelGenerator.ITEM_LAYERS = ["layer0", "layer1", "layer2", "layer3", "layer4"];
2027
2183
 
2028
2184
  // src/UVMapper.ts
2029
- var p6 = prefix("UVMapper");
2185
+ var p5 = prefix("UVMapper");
2030
2186
  var DEFAULT_UV = [0, 0, 16, 16];
2031
2187
  var X = 0;
2032
2188
  var Y = 1;
@@ -2199,12 +2355,11 @@ var UVMapper = class {
2199
2355
  return [tl, tr, bl, br];
2200
2356
  }
2201
2357
  static async createAtlas(originalModel) {
2202
- var _a;
2203
2358
  const textureMap = {};
2204
2359
  const metaMap = {};
2205
2360
  const model = { ...originalModel };
2206
2361
  const isItemModel = !("elements" in model);
2207
- console.debug(p6, "Creating Atlas for", model.key);
2362
+ console.debug(p5, "Creating Atlas for", model.key);
2208
2363
  if (model.textures) {
2209
2364
  const promises = [];
2210
2365
  const uniqueTextureNames = [];
@@ -2218,7 +2373,7 @@ var UVMapper = class {
2218
2373
  const assetKey = AssetKey.parse("textures", textureValue, model.key);
2219
2374
  promises.push(ModelTextures.get(assetKey).then((asset) => {
2220
2375
  if (!asset) {
2221
- console.warn(p6, "Missing texture", assetKey);
2376
+ console.warn(p5, "Missing texture", assetKey);
2222
2377
  return;
2223
2378
  }
2224
2379
  textureMap[textureKey] = new WrappedImage(asset);
@@ -2230,7 +2385,7 @@ var UVMapper = class {
2230
2385
  }
2231
2386
  await Promise.all(promises);
2232
2387
  const textureCount = uniqueTextureNames.length;
2233
- console.debug(p6, "Creating Atlas for", textureCount, "textures");
2388
+ console.debug(p5, "Creating Atlas for", textureCount, "textures");
2234
2389
  this.fillMissingTextureKeys(model.textures, textureMap);
2235
2390
  this.fillMissingTextureKeys(model.textures, metaMap);
2236
2391
  const sizes = {};
@@ -2250,7 +2405,7 @@ var UVMapper = class {
2250
2405
  this.fillMissingTextureKeys(model.textures, sizes);
2251
2406
  const s = Math.ceil(Math.sqrt(textureCount + 1));
2252
2407
  const size = Math.ceil(s * maxWidth);
2253
- console.debug(p6, "Atlas size:", size);
2408
+ console.debug(p5, "Atlas size:", size);
2254
2409
  const squaredSize = size * size;
2255
2410
  const missing = await ImageLoader.getData("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX/AP8AAACfphTyAAAAFUlEQVQoz2MIhQKGVVAwKjIqQrwIAHRz/wFI17TEAAAAAElFTkSuQmCC");
2256
2411
  const empty = await ImageLoader.getData("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAAA1BMVEUAAACnej3aAAAAAXRSTlMAQObYZgAAAA5JREFUKM9jGAWjgAIAAAJAAAFSSwuTAAAAAElFTkSuQmCC");
@@ -2279,16 +2434,15 @@ var UVMapper = class {
2279
2434
  if (texture.animated) {
2280
2435
  hasAnimation = true;
2281
2436
  const meta = metaMap[textureKey];
2282
- const frameTime = ((_a = meta == null ? void 0 : meta.animation) == null ? void 0 : _a.frametime) ?? 1;
2437
+ const frameTime = meta?.animation?.frametime ?? 1;
2283
2438
  console.log(meta);
2284
2439
  console.log(frameTime);
2285
2440
  let t = 0;
2286
2441
  let f = 0;
2287
2442
  animatorFunctions[textureKey] = () => {
2288
- var _a2;
2289
2443
  if (t++ >= frameTime) {
2290
2444
  t = 0;
2291
- const frames = (_a2 = meta == null ? void 0 : meta.animation) == null ? void 0 : _a2.frames;
2445
+ const frames = meta?.animation?.frames;
2292
2446
  const frame = frames ? frames[f] : f;
2293
2447
  image.putData(texture.getFrameSectionData(frame), x, y, 0, 0, maxWidth, maxWidth);
2294
2448
  f++;
@@ -2306,10 +2460,10 @@ var UVMapper = class {
2306
2460
  }
2307
2461
  }
2308
2462
  const atlasImageData = image.toDataURL();
2309
- console.log(p6, "Atlas Image for", model.key, atlasImageData);
2463
+ console.log(p5, "Atlas Image for", model.key, atlasImageData);
2310
2464
  this.fillMissingTextureKeys(model.textures, positions);
2311
2465
  if (isItemModel) {
2312
- console.debug(p6, "Generating item model for", model);
2466
+ console.debug(p5, "Generating item model for", model);
2313
2467
  model.elements = [];
2314
2468
  for (let layerName of ModelGenerator.ITEM_LAYERS) {
2315
2469
  const textureImage = textureMap[layerName];
@@ -2317,7 +2471,7 @@ var UVMapper = class {
2317
2471
  model.elements.push(...ModelGenerator.generateItemModel(textureImage.data, layerName));
2318
2472
  }
2319
2473
  }
2320
- console.debug(p6, "Item model elements", model.elements);
2474
+ console.debug(p5, "Item model elements", model.elements);
2321
2475
  }
2322
2476
  if (!model.elements) {
2323
2477
  }
@@ -2377,7 +2531,7 @@ var UVMapper = class {
2377
2531
  hasTransparency
2378
2532
  );
2379
2533
  } else {
2380
- console.warn(p6, "Model does not have any textures", model);
2534
+ console.warn(p5, "Model does not have any textures", model);
2381
2535
  }
2382
2536
  return void 0;
2383
2537
  }
@@ -2515,17 +2669,20 @@ function shutdown() {
2515
2669
  }
2516
2670
 
2517
2671
  // src/assets/Entities.ts
2518
- var import_typescript_memoize3 = require("typescript-memoize");
2519
2672
  var Entities = class {
2520
2673
  static async getBlockEntityModels() {
2521
2674
  const key = AssetKey.parse("models", "minerender:blockEntityModels");
2522
2675
  console.log(key);
2523
- return AssetLoader.get(key, "json" /* JSON */);
2676
+ return Caching.entityModelsCache.get(key.serialize(), () => {
2677
+ return AssetLoader.get(key, "json" /* JSON */);
2678
+ });
2524
2679
  }
2525
2680
  static async getEntityModels() {
2526
2681
  const key = AssetKey.parse("models", "minerender:entityModels");
2527
2682
  console.log(key);
2528
- return AssetLoader.get(key, "json" /* JSON */);
2683
+ return Caching.entityModelsCache.get(key.serialize(), () => {
2684
+ return AssetLoader.get(key, "json" /* JSON */);
2685
+ });
2529
2686
  }
2530
2687
  // BlockEntity names are hardcoded
2531
2688
  static async getBlockList() {
@@ -2571,12 +2728,6 @@ var Entities = class {
2571
2728
  };
2572
2729
  }
2573
2730
  };
2574
- __decorateClass([
2575
- (0, import_typescript_memoize3.Memoize)()
2576
- ], Entities, "getBlockEntityModels", 1);
2577
- __decorateClass([
2578
- (0, import_typescript_memoize3.Memoize)()
2579
- ], Entities, "getEntityModels", 1);
2580
2731
  var EntityModels = class {
2581
2732
  };
2582
2733
  var BlockEntityModels = class {
@@ -2640,18 +2791,26 @@ var MineRenderError = class _MineRenderError extends Error {
2640
2791
  };
2641
2792
 
2642
2793
  // src/renderer/SceneObject.ts
2643
- var import_ts_deepmerge4 = __toESM(require_dist());
2644
- var p7 = prefix("SceneObject");
2645
- var _SceneObject = class _SceneObject extends import_three9.Object3D {
2794
+ var import_ts_deepmerge3 = __toESM(require_dist());
2795
+ var p6 = prefix("SceneObject");
2796
+ var SceneObject = class _SceneObject extends import_three9.Object3D {
2646
2797
  constructor(options) {
2647
2798
  super();
2648
2799
  this.isSceneObject = true;
2649
2800
  this.materialCallbacks = {};
2650
2801
  this._isInstanced = false;
2651
2802
  this._instanceCounter = 0;
2652
- this.options = (0, import_ts_deepmerge4.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
2803
+ this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
2653
2804
  console.log("SceneObject options", this.options);
2654
2805
  }
2806
+ static {
2807
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge3.default)({}, {
2808
+ instanceMeshes: true,
2809
+ maxInstanceCount: 50,
2810
+ mergeMeshes: true,
2811
+ wireframe: false
2812
+ });
2813
+ }
2655
2814
  set scene(scene) {
2656
2815
  if (!!this._scene) throw new MineRenderError("Scene already set");
2657
2816
  this._scene = scene;
@@ -2820,9 +2979,9 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2820
2979
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
2821
2980
  const i = this._instanceCounter++;
2822
2981
  this.setMatrixAt(i, new import_three9.Matrix4());
2823
- console.debug(p7, "nextInstance " + i);
2982
+ console.debug(p6, "nextInstance " + i);
2824
2983
  if (i === this.options.maxInstanceCount) {
2825
- console.warn(p7, "Max instance count reached for " + this);
2984
+ console.warn(p6, "Max instance count reached for " + this);
2826
2985
  }
2827
2986
  if (this.scene) {
2828
2987
  this.scene.stats.instanceCount++;
@@ -2993,34 +3152,29 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2993
3152
  this.notifyDirty();
2994
3153
  }
2995
3154
  removeFromScene() {
2996
- var _a;
2997
- (_a = this._scene) == null ? void 0 : _a.remove(this);
3155
+ this._scene?.remove(this);
2998
3156
  this.notifyDirty();
2999
3157
  }
3000
3158
  //</editor-fold>
3001
3159
  };
3002
- _SceneObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, {
3003
- instanceMeshes: true,
3004
- maxInstanceCount: 50,
3005
- mergeMeshes: true,
3006
- wireframe: false
3007
- });
3008
- var SceneObject = _SceneObject;
3009
3160
  function isSceneObject(obj) {
3010
3161
  return obj.isSceneObject;
3011
3162
  }
3012
3163
 
3013
3164
  // src/entity/scene/EntityObject.ts
3014
- var import_ts_deepmerge5 = __toESM(require_dist());
3165
+ var import_ts_deepmerge4 = __toESM(require_dist());
3015
3166
  var import_three11 = require("three");
3016
- var THREE2 = __toESM(require("three"));
3167
+ var THREE3 = __toESM(require("three"));
3017
3168
  var EntityObject = class extends SceneObject {
3018
3169
  constructor(entity, options) {
3019
3170
  super();
3020
3171
  this.entity = entity;
3021
3172
  this.isEntityObject = true;
3022
3173
  this.meshesCreated = false;
3023
- this.options = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
3174
+ this.options = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
3175
+ }
3176
+ static {
3177
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, {});
3024
3178
  }
3025
3179
  async init() {
3026
3180
  this.createMeshes();
@@ -3029,17 +3183,19 @@ var EntityObject = class extends SceneObject {
3029
3183
  dispose() {
3030
3184
  super.dispose();
3031
3185
  }
3032
- async loadTextures() {
3033
- var _a;
3034
- this.imageData = await ModelTextures.get(new AssetKey(
3035
- ((_a = this.entity.key) == null ? void 0 : _a.namespace) ?? DEFAULT_NAMESPACE,
3186
+ get textureKey() {
3187
+ return new AssetKey(
3188
+ this.entity.key?.namespace ?? DEFAULT_NAMESPACE,
3036
3189
  this.entity.key.path,
3037
3190
  //TODO: texture may differ from entity name; most of them are in subdirectories for multiple variants etc.
3038
3191
  "textures",
3039
3192
  "entity",
3040
3193
  "assets",
3041
3194
  ".png"
3042
- ));
3195
+ );
3196
+ }
3197
+ async loadTextures() {
3198
+ this.imageData = await ModelTextures.get(this.textureKey);
3043
3199
  }
3044
3200
  //TODO: abstract this, since extracted model data can be used for entities, blocks, players
3045
3201
  createMeshes(force = false) {
@@ -3058,8 +3214,8 @@ var EntityObject = class extends SceneObject {
3058
3214
  const l = cube.maxZ - cube.minZ;
3059
3215
  const uv = texture.toUvArray(w, h, l);
3060
3216
  const cubeGeo = this._getBoxGeometryForDimensionsAndUv(w, h, l, uv).clone();
3061
- cubeGeo.applyMatrix4(new THREE2.Matrix4().makeTranslation(w / 2, h / 2, l / 2));
3062
- cubeGeo.applyMatrix4(new THREE2.Matrix4().makeTranslation(cube.minX, cube.minY, cube.minZ));
3217
+ cubeGeo.applyMatrix4(new THREE3.Matrix4().makeTranslation(w / 2, h / 2, l / 2));
3218
+ cubeGeo.applyMatrix4(new THREE3.Matrix4().makeTranslation(cube.minX, cube.minY, cube.minZ));
3063
3219
  applyModelPartRotation(part, cubeGeo);
3064
3220
  const mesh = this.createMesh(partName, cubeGeo, mat);
3065
3221
  partAnchor.add(mesh);
@@ -3072,24 +3228,25 @@ var EntityObject = class extends SceneObject {
3072
3228
  this.meshesCreated = true;
3073
3229
  }
3074
3230
  async applyTextures() {
3075
- var _a;
3076
- const textureAsset = await ModelTextures.preload(new AssetKey(
3077
- ((_a = this.entity.key) == null ? void 0 : _a.namespace) ?? DEFAULT_NAMESPACE,
3078
- this.entity.key.path,
3079
- "textures",
3080
- "entity",
3081
- "assets",
3082
- ".png"
3083
- ));
3084
- if (textureAsset) {
3085
- let mat = Materials.getImage({ texture: { src: textureAsset.src } });
3086
- this.iterateAllMeshes((mesh) => {
3087
- mesh.material = mat;
3088
- });
3089
- }
3231
+ const assetKeyStr = this.textureKey.serialize();
3232
+ const keyStr = `entity:${assetKeyStr}`;
3233
+ let mat = Caching.materialCache.getIfPresent(keyStr);
3234
+ if (!mat) {
3235
+ const pending = this.loadTextures();
3236
+ const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
3237
+ await pending;
3238
+ if (!this.imageData) return;
3239
+ const canvas = this.imageData.data.canvas;
3240
+ const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
3241
+ mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
3242
+ this.imageData = void 0;
3243
+ }
3244
+ this.iterateAllMeshes((mesh) => {
3245
+ mesh.material = mat;
3246
+ });
3247
+ this.notifyDirty();
3090
3248
  }
3091
3249
  };
3092
- EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, {});
3093
3250
  function isEntityObject(obj) {
3094
3251
  return obj.isEntityObject;
3095
3252
  }
@@ -3101,7 +3258,7 @@ var GuiObject = class extends SceneObject {
3101
3258
 
3102
3259
  // src/inspector/SceneInspector.ts
3103
3260
  var import_three12 = require("three");
3104
- var p8 = prefix("SceneInspector");
3261
+ var p7 = prefix("SceneInspector");
3105
3262
  var help = "<span>Ctrl+Click to Select<br/></span><br/>";
3106
3263
  var SceneInspector = class {
3107
3264
  constructor(renderer) {
@@ -3130,8 +3287,7 @@ var SceneInspector = class {
3130
3287
  return out;
3131
3288
  }
3132
3289
  onClick(event) {
3133
- var _a;
3134
- if (((_a = event.target) == null ? void 0 : _a.nodeName) !== "CANVAS") return;
3290
+ if (event.target?.nodeName !== "CANVAS") return;
3135
3291
  if (!event.ctrlKey) return;
3136
3292
  setTimeout(() => {
3137
3293
  this.mouse.x = event.clientX / window.innerWidth * 2 - 1;
@@ -3171,7 +3327,7 @@ var SceneInspector = class {
3171
3327
  }
3172
3328
  selectObject(targetObject, targetIntersection) {
3173
3329
  this.selectedObject = targetObject;
3174
- console.log(p8, "selected", targetObject);
3330
+ console.log(p7, "selected", targetObject);
3175
3331
  this.redraw(targetObject, targetIntersection);
3176
3332
  }
3177
3333
  redraw(targetObject, targetIntersection) {
@@ -3469,7 +3625,7 @@ var SceneStatsDisplay = class {
3469
3625
  };
3470
3626
 
3471
3627
  // src/instance/InstanceManager.ts
3472
- var p9 = prefix("InstanceManager");
3628
+ var p8 = prefix("InstanceManager");
3473
3629
  var InstanceManager = class {
3474
3630
  constructor() {
3475
3631
  this.isInstanceManager = true;
@@ -3477,7 +3633,7 @@ var InstanceManager = class {
3477
3633
  }
3478
3634
  async get(key) {
3479
3635
  if (key in this.instanceCache) {
3480
- console.debug(p9, "key in cache", key);
3636
+ console.debug(p8, "key in cache", key);
3481
3637
  return (await this.instanceCache[key]).nextInstance();
3482
3638
  }
3483
3639
  return void 0;
@@ -3486,13 +3642,17 @@ var InstanceManager = class {
3486
3642
  if (key in this.instanceCache) {
3487
3643
  return await this.get(key);
3488
3644
  }
3489
- console.debug(p9, "key not in cache", key);
3490
- this.instanceCache[key] = new Promise(async (resolve) => {
3491
- const obj = await supplier();
3492
- const instance = obj.nextInstance();
3493
- resolve(instance);
3494
- });
3495
- return await this.instanceCache[key];
3645
+ console.debug(p8, "key not in cache", key);
3646
+ const pending = Promise.resolve().then(supplier).then((obj) => obj.nextInstance());
3647
+ this.instanceCache[key] = pending;
3648
+ try {
3649
+ return await pending;
3650
+ } catch (error) {
3651
+ if (this.instanceCache[key] === pending) {
3652
+ delete this.instanceCache[key];
3653
+ }
3654
+ throw error;
3655
+ }
3496
3656
  }
3497
3657
  reset() {
3498
3658
  for (let instanceCacheKey in this.instanceCache) {
@@ -4081,26 +4241,28 @@ function computeMorphedAttributes(object) {
4081
4241
  }
4082
4242
 
4083
4243
  // src/model/scene/ModelObject.ts
4084
- var import_ts_deepmerge6 = __toESM(require_dist());
4085
- var p10 = prefix("ModelObject");
4086
- var _ModelObject = class _ModelObject extends SceneObject {
4244
+ var import_ts_deepmerge5 = __toESM(require_dist());
4245
+ var p9 = prefix("ModelObject");
4246
+ var ModelObject = class _ModelObject extends SceneObject {
4087
4247
  constructor(originalModel, options) {
4088
4248
  super(options);
4089
4249
  this.originalModel = originalModel;
4090
4250
  this.isModelObject = true;
4091
4251
  this.meshesCreated = false;
4092
- this.options = (0, import_ts_deepmerge6.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
4252
+ this.options = (0, import_ts_deepmerge5.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
4093
4253
  console.log("ModelObject options", this.options);
4094
4254
  }
4255
+ static {
4256
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, {});
4257
+ }
4095
4258
  async init() {
4096
4259
  await this.loadTextures();
4097
4260
  this.createMeshes();
4098
4261
  this.applyTextures();
4099
4262
  }
4100
4263
  dispose() {
4101
- var _a;
4102
4264
  super.dispose();
4103
- (_a = this.atlas) == null ? void 0 : _a.dispose();
4265
+ this.atlas?.dispose();
4104
4266
  }
4105
4267
  get textureAtlas() {
4106
4268
  return this.atlas;
@@ -4110,13 +4272,12 @@ var _ModelObject = class _ModelObject extends SceneObject {
4110
4272
  this.atlas = await UVMapper.getAtlas(this.originalModel);
4111
4273
  }
4112
4274
  createMeshes(force = false) {
4113
- var _a;
4114
4275
  if (this.meshesCreated && !force) return;
4115
4276
  const mat = Materials.MISSING_TEXTURE;
4116
4277
  let allGeos = [];
4117
4278
  if (this.atlas) {
4118
4279
  if (this.atlas.model.elements) {
4119
- (_a = this.atlas.model.elements) == null ? void 0 : _a.forEach((el) => {
4280
+ this.atlas.model.elements?.forEach((el) => {
4120
4281
  const elGeo = this._getBoxGeometryFromElement(el).clone();
4121
4282
  elGeo.applyMatrix4(new import_three15.Matrix4().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4122
4283
  elGeo.applyMatrix4(new import_three15.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
@@ -4134,10 +4295,10 @@ var _ModelObject = class _ModelObject extends SceneObject {
4134
4295
  }
4135
4296
  });
4136
4297
  } else {
4137
- console.debug(p10, this.atlas.model, "has no elements");
4298
+ console.debug(p9, this.atlas.model, "has no elements");
4138
4299
  }
4139
4300
  } else {
4140
- console.debug(p10, "Missing atlas for", this);
4301
+ console.debug(p9, "Missing atlas for", this);
4141
4302
  }
4142
4303
  if (this.options.mergeMeshes) {
4143
4304
  let combinedGeo;
@@ -4189,17 +4350,15 @@ var _ModelObject = class _ModelObject extends SceneObject {
4189
4350
  }
4190
4351
  }
4191
4352
  };
4192
- _ModelObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge6.default)({}, SceneObject.DEFAULT_OPTIONS, {});
4193
- var ModelObject = _ModelObject;
4194
4353
  function isModelObject(obj) {
4195
4354
  return obj.isModelObject;
4196
4355
  }
4197
4356
 
4198
4357
  // src/model/block/scene/BlockObject.ts
4199
- var import_ts_deepmerge7 = __toESM(require_dist());
4358
+ var import_ts_deepmerge6 = __toESM(require_dist());
4200
4359
  var import_three16 = require("three");
4201
- var p11 = prefix("BlockObject");
4202
- var _BlockObject = class _BlockObject extends SceneObject {
4360
+ var p10 = prefix("BlockObject");
4361
+ var BlockObject = class _BlockObject extends SceneObject {
4203
4362
  constructor(blockState, options) {
4204
4363
  super(options);
4205
4364
  this.blockState = blockState;
@@ -4212,11 +4371,16 @@ var _BlockObject = class _BlockObject extends SceneObject {
4212
4371
  this._instanceModel = [];
4213
4372
  this._variants = [];
4214
4373
  this._models = [];
4215
- this.options = (0, import_ts_deepmerge7.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
4374
+ this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
4375
+ }
4376
+ static {
4377
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge6.default)({}, ModelObject.DEFAULT_OPTIONS, {
4378
+ applyDefaultState: true
4379
+ });
4216
4380
  }
4217
4381
  async init() {
4218
4382
  if (this.options.applyDefaultState) {
4219
- const defaultState = this.blockState.key ? BlockStates.getDefaultState(this.blockState.key) : void 0;
4383
+ const defaultState = this.blockState.key ? await BlockStates.getDefaultState(this.blockState.key) : void 0;
4220
4384
  if (defaultState && Object.keys(defaultState).length > 0) {
4221
4385
  const state = {};
4222
4386
  for (let k in defaultState) {
@@ -4292,7 +4456,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
4292
4456
  } else if (this.blockState.multipart) {
4293
4457
  for (let part of this.blockState.multipart) {
4294
4458
  if (!part.apply) {
4295
- console.debug(p11, "Missing apply for blockState part", part);
4459
+ console.debug(p10, "Missing apply for blockState part", part);
4296
4460
  continue;
4297
4461
  }
4298
4462
  if (!part.when) {
@@ -4501,10 +4665,6 @@ var _BlockObject = class _BlockObject extends SceneObject {
4501
4665
  //TODO: should override rotation + scale methods
4502
4666
  //TODO
4503
4667
  };
4504
- _BlockObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge7.default)({}, ModelObject.DEFAULT_OPTIONS, {
4505
- applyDefaultState: true
4506
- });
4507
- var BlockObject = _BlockObject;
4508
4668
  function isBlockObject(obj) {
4509
4669
  return obj.isBlockObject;
4510
4670
  }
@@ -4529,11 +4689,10 @@ var StructureParser = class {
4529
4689
  throw new MineRenderError("Structure does not have palette(s)");
4530
4690
  }
4531
4691
  const blocks = nbt.blocks.value.value.map((block) => {
4532
- var _a;
4533
4692
  const state = palette.value.value[block.state.value];
4534
4693
  if (state.Name.value === "minecraft:air") return void 0;
4535
4694
  const props = {};
4536
- for (let k in (_a = state.Properties) == null ? void 0 : _a.value) {
4695
+ for (let k in state.Properties?.value) {
4537
4696
  props[k] = state.Properties.value[k].value;
4538
4697
  }
4539
4698
  return {
@@ -4552,7 +4711,7 @@ var StructureParser = class {
4552
4711
 
4553
4712
  // src/renderer/MineRenderScene.ts
4554
4713
  var import_three17 = require("three");
4555
- var import_ts_deepmerge9 = __toESM(require_dist());
4714
+ var import_ts_deepmerge8 = __toESM(require_dist());
4556
4715
 
4557
4716
  // src/skin/SkinPart.ts
4558
4717
  var SkinPart = /* @__PURE__ */ ((SkinPart2) => {
@@ -5283,7 +5442,7 @@ var slimSkinGeometries = {
5283
5442
  };
5284
5443
 
5285
5444
  // src/skin/scene/SkinObject.ts
5286
- var import_ts_deepmerge8 = __toESM(require_dist());
5445
+ var import_ts_deepmerge7 = __toESM(require_dist());
5287
5446
  var SkinObject = class extends SceneObject {
5288
5447
  constructor(options) {
5289
5448
  super();
@@ -5291,7 +5450,7 @@ var SkinObject = class extends SceneObject {
5291
5450
  this.legacy = false;
5292
5451
  this.skinTextureWidth = 64;
5293
5452
  this.skinTextureHeight = 64;
5294
- this.options = (0, import_ts_deepmerge8.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
5453
+ this.options = (0, import_ts_deepmerge7.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
5295
5454
  }
5296
5455
  async init() {
5297
5456
  this.createMeshes();
@@ -5395,31 +5554,64 @@ var SkinObject = class extends SceneObject {
5395
5554
  };
5396
5555
 
5397
5556
  // src/renderer/MineRenderScene.ts
5398
- var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5557
+ var MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5399
5558
  constructor(options) {
5400
5559
  super();
5401
5560
  this.isMineRenderScene = true;
5402
5561
  this.stats = new SceneStats();
5403
5562
  this.instanceManager = new InstanceManager();
5404
5563
  this.dirty = true;
5405
- this.options = (0, import_ts_deepmerge9.default)({}, _MineRenderScene.DEFAULT_OPTIONS, options ?? {});
5564
+ this.observedObjects = /* @__PURE__ */ new Set();
5565
+ this.onObjectChange = (event) => {
5566
+ if (event.target?.parent === this) {
5567
+ this.dirty = true;
5568
+ }
5569
+ };
5570
+ this.options = (0, import_ts_deepmerge8.default)({}, _MineRenderScene.DEFAULT_OPTIONS, options ?? {});
5406
5571
  }
5407
- add(...object) {
5408
- this.dirty = true;
5409
- this.stats.objectCount += object.length;
5410
- for (let obj of object) {
5411
- if (isSceneObject(obj)) {
5412
- this.stats.sceneObjectCount++;
5572
+ static {
5573
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge8.default)({}, {});
5574
+ }
5575
+ add(...objects) {
5576
+ for (const object of objects) {
5577
+ this.dirty = true;
5578
+ try {
5579
+ super.add(object);
5580
+ } finally {
5581
+ if (object?.isObject3D && object !== this) {
5582
+ this.updateObjectRegistration(object, object.parent === this);
5583
+ }
5413
5584
  }
5414
- obj.addEventListener("change", (event) => {
5415
- this.dirty = true;
5416
- });
5417
5585
  }
5418
- return super.add(...object);
5586
+ return this;
5419
5587
  }
5420
- remove(...object) {
5421
- this.dirty = true;
5422
- return super.remove(...object);
5588
+ remove(...objects) {
5589
+ for (const object of objects) {
5590
+ if (!this.children.includes(object)) continue;
5591
+ this.dirty = true;
5592
+ this.updateObjectRegistration(object, false);
5593
+ try {
5594
+ super.remove(object);
5595
+ } finally {
5596
+ this.updateObjectRegistration(object, object.parent === this);
5597
+ }
5598
+ }
5599
+ return this;
5600
+ }
5601
+ updateObjectRegistration(object, attached) {
5602
+ if (this.observedObjects.has(object) === attached) return;
5603
+ if (attached) {
5604
+ this.observedObjects.add(object);
5605
+ object.addEventListener("change", this.onObjectChange);
5606
+ } else {
5607
+ this.observedObjects.delete(object);
5608
+ object.removeEventListener("change", this.onObjectChange);
5609
+ }
5610
+ const change = attached ? 1 : -1;
5611
+ this.stats.objectCount += change;
5612
+ if (isSceneObject(object)) {
5613
+ this.stats.sceneObjectCount += change;
5614
+ }
5423
5615
  }
5424
5616
  async initAndAdd(...object) {
5425
5617
  this.dirty = true;
@@ -5429,13 +5621,12 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5429
5621
  return this.add(...object);
5430
5622
  }
5431
5623
  async addSceneObject(asset, objectSupplier, _options, parent = this) {
5432
- var _a, _b;
5433
5624
  console.log("addSceneObject", asset);
5434
5625
  console.log("parent", parent);
5435
5626
  console.log(_options);
5436
5627
  this.dirty = true;
5437
5628
  const obj = await objectSupplier();
5438
- if (((_a = obj == null ? void 0 : obj.options) == null ? void 0 : _a.instanceMeshes) && asset.key && ((_b = asset.key) == null ? void 0 : _b.assetType) === "models") {
5629
+ if (obj?.options?.instanceMeshes && asset.key && asset.key?.assetType === "models") {
5439
5630
  console.log("instanceMeshes + key");
5440
5631
  const key = asset.key.serialize();
5441
5632
  return this.instanceManager.getOrCreate(key, async () => {
@@ -5475,1048 +5666,1139 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5475
5666
  return this.addSceneObject(entity, () => new EntityObject(entity, options), options, parent);
5476
5667
  }
5477
5668
  };
5478
- _MineRenderScene.DEFAULT_OPTIONS = (0, import_ts_deepmerge9.default)({}, {});
5479
- var MineRenderScene = _MineRenderScene;
5480
5669
  function isMineRenderScene(obj) {
5481
5670
  return obj.isMineRenderScene;
5482
5671
  }
5483
5672
 
5484
5673
  // src/renderer/Renderer.ts
5485
- var import_three18 = require("three");
5486
- var import_ts_deepmerge10 = __toESM(require_dist());
5674
+ var import_three19 = require("three");
5675
+ var import_ts_deepmerge9 = __toESM(require_dist());
5487
5676
  var import_stats = __toESM(require("stats.js"));
5488
5677
  var import_postprocessing = require("postprocessing");
5489
- var _Renderer = class _Renderer {
5490
- constructor(options) {
5491
- this._dirty = true;
5492
- this._animationTimer = void 0;
5493
- this._animationFrame = void 0;
5494
- this._resizeListener = void 0;
5495
- this.options = (0, import_ts_deepmerge10.default)({}, _Renderer.DEFAULT_OPTIONS, options ?? {});
5496
- this._animationLoop = this.animate.bind(this);
5497
- this._fpsTimer = this.options.render.fpsLimit > 0 ? 1e3 / this.options.render.fpsLimit : void 0;
5498
- this._scene = this.createScene();
5499
- this._camera = this.createCamera();
5500
- this._renderer = this.createRenderer();
5501
- this._composer = this.createComposer();
5502
- if (this.options.render.stats) {
5503
- this._stats = new import_stats.default();
5504
- document.body.appendChild(this._stats.dom);
5678
+
5679
+ // src/three/OrbitControls.js
5680
+ var import_three18 = require("three");
5681
+ var _changeEvent = { type: "change" };
5682
+ var _startEvent = { type: "start" };
5683
+ var _endEvent = { type: "end" };
5684
+ var OrbitControls = class extends import_three18.EventDispatcher {
5685
+ constructor(object, domElement) {
5686
+ super();
5687
+ if (domElement === void 0) console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.');
5688
+ if (domElement === document) console.error('THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.');
5689
+ this.object = object;
5690
+ this.domElement = domElement;
5691
+ this.domElement.style.touchAction = "none";
5692
+ this.enabled = true;
5693
+ this.target = new import_three18.Vector3();
5694
+ this.minDistance = 0;
5695
+ this.maxDistance = Infinity;
5696
+ this.minZoom = 0;
5697
+ this.maxZoom = Infinity;
5698
+ this.minPolarAngle = 0;
5699
+ this.maxPolarAngle = Math.PI;
5700
+ this.minAzimuthAngle = -Infinity;
5701
+ this.maxAzimuthAngle = Infinity;
5702
+ this.enableDamping = false;
5703
+ this.dampingFactor = 0.05;
5704
+ this.enableZoom = true;
5705
+ this.zoomSpeed = 1;
5706
+ this.enableRotate = true;
5707
+ this.rotateSpeed = 1;
5708
+ this.enablePan = true;
5709
+ this.panSpeed = 1;
5710
+ this.screenSpacePanning = true;
5711
+ this.keyPanSpeed = 7;
5712
+ this.autoRotate = false;
5713
+ this.autoRotateSpeed = 2;
5714
+ this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" };
5715
+ this.mouseButtons = { LEFT: import_three18.MOUSE.ROTATE, MIDDLE: import_three18.MOUSE.DOLLY, RIGHT: import_three18.MOUSE.PAN };
5716
+ this.touches = { ONE: import_three18.TOUCH.ROTATE, TWO: import_three18.TOUCH.DOLLY_PAN };
5717
+ this.target0 = this.target.clone();
5718
+ this.position0 = this.object.position.clone();
5719
+ this.zoom0 = this.object.zoom;
5720
+ this._domElementKeyEvents = null;
5721
+ this.getPolarAngle = function() {
5722
+ return spherical.phi;
5723
+ };
5724
+ this.getAzimuthalAngle = function() {
5725
+ return spherical.theta;
5726
+ };
5727
+ this.getDistance = function() {
5728
+ return this.object.position.distanceTo(this.target);
5729
+ };
5730
+ this.saveState = function() {
5731
+ scope.target0.copy(scope.target);
5732
+ scope.position0.copy(scope.object.position);
5733
+ scope.zoom0 = scope.object.zoom;
5734
+ };
5735
+ this.reset = function() {
5736
+ scope.target.copy(scope.target0);
5737
+ scope.object.position.copy(scope.position0);
5738
+ scope.object.zoom = scope.zoom0;
5739
+ scope.object.updateProjectionMatrix();
5740
+ scope.dispatchEvent(_changeEvent);
5741
+ scope.update();
5742
+ state = STATE.NONE;
5743
+ };
5744
+ this.update = function() {
5745
+ const offset = new import_three18.Vector3();
5746
+ const quat = new import_three18.Quaternion().setFromUnitVectors(object.up, new import_three18.Vector3(0, 1, 0));
5747
+ const quatInverse = quat.clone().invert();
5748
+ const lastPosition = new import_three18.Vector3();
5749
+ const lastQuaternion = new import_three18.Quaternion();
5750
+ const twoPI = 2 * Math.PI;
5751
+ return function update() {
5752
+ const position = scope.object.position;
5753
+ offset.copy(position).sub(scope.target);
5754
+ offset.applyQuaternion(quat);
5755
+ spherical.setFromVector3(offset);
5756
+ if (scope.autoRotate && state === STATE.NONE) {
5757
+ rotateLeft(getAutoRotationAngle());
5758
+ }
5759
+ if (scope.enableDamping) {
5760
+ spherical.theta += sphericalDelta.theta * scope.dampingFactor;
5761
+ spherical.phi += sphericalDelta.phi * scope.dampingFactor;
5762
+ } else {
5763
+ spherical.theta += sphericalDelta.theta;
5764
+ spherical.phi += sphericalDelta.phi;
5765
+ }
5766
+ let min = scope.minAzimuthAngle;
5767
+ let max = scope.maxAzimuthAngle;
5768
+ if (isFinite(min) && isFinite(max)) {
5769
+ if (min < -Math.PI) min += twoPI;
5770
+ else if (min > Math.PI) min -= twoPI;
5771
+ if (max < -Math.PI) max += twoPI;
5772
+ else if (max > Math.PI) max -= twoPI;
5773
+ if (min <= max) {
5774
+ spherical.theta = Math.max(min, Math.min(max, spherical.theta));
5775
+ } else {
5776
+ spherical.theta = spherical.theta > (min + max) / 2 ? Math.max(min, spherical.theta) : Math.min(max, spherical.theta);
5777
+ }
5778
+ }
5779
+ spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
5780
+ spherical.makeSafe();
5781
+ spherical.radius *= scale;
5782
+ spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));
5783
+ if (scope.enableDamping === true) {
5784
+ scope.target.addScaledVector(panOffset, scope.dampingFactor);
5785
+ } else {
5786
+ scope.target.add(panOffset);
5787
+ }
5788
+ offset.setFromSpherical(spherical);
5789
+ offset.applyQuaternion(quatInverse);
5790
+ position.copy(scope.target).add(offset);
5791
+ scope.object.lookAt(scope.target);
5792
+ if (scope.enableDamping === true) {
5793
+ sphericalDelta.theta *= 1 - scope.dampingFactor;
5794
+ sphericalDelta.phi *= 1 - scope.dampingFactor;
5795
+ panOffset.multiplyScalar(1 - scope.dampingFactor);
5796
+ } else {
5797
+ sphericalDelta.set(0, 0, 0);
5798
+ panOffset.set(0, 0, 0);
5799
+ }
5800
+ scale = 1;
5801
+ if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
5802
+ scope.dispatchEvent(_changeEvent);
5803
+ lastPosition.copy(scope.object.position);
5804
+ lastQuaternion.copy(scope.object.quaternion);
5805
+ zoomChanged = false;
5806
+ return true;
5807
+ }
5808
+ return false;
5809
+ };
5810
+ }();
5811
+ this.dispose = function() {
5812
+ scope.domElement.removeEventListener("contextmenu", onContextMenu);
5813
+ scope.domElement.removeEventListener("pointerdown", onPointerDown);
5814
+ scope.domElement.removeEventListener("pointercancel", onPointerCancel);
5815
+ scope.domElement.removeEventListener("wheel", onMouseWheel);
5816
+ scope.domElement.removeEventListener("pointermove", onPointerMove);
5817
+ scope.domElement.removeEventListener("pointerup", onPointerUp);
5818
+ if (scope._domElementKeyEvents !== null) {
5819
+ scope._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
5820
+ }
5821
+ };
5822
+ const scope = this;
5823
+ const STATE = {
5824
+ NONE: -1,
5825
+ ROTATE: 0,
5826
+ DOLLY: 1,
5827
+ PAN: 2,
5828
+ TOUCH_ROTATE: 3,
5829
+ TOUCH_PAN: 4,
5830
+ TOUCH_DOLLY_PAN: 5,
5831
+ TOUCH_DOLLY_ROTATE: 6
5832
+ };
5833
+ let state = STATE.NONE;
5834
+ const EPS = 1e-6;
5835
+ const spherical = new import_three18.Spherical();
5836
+ const sphericalDelta = new import_three18.Spherical();
5837
+ let scale = 1;
5838
+ const panOffset = new import_three18.Vector3();
5839
+ let zoomChanged = false;
5840
+ const rotateStart = new import_three18.Vector2();
5841
+ const rotateEnd = new import_three18.Vector2();
5842
+ const rotateDelta = new import_three18.Vector2();
5843
+ const panStart = new import_three18.Vector2();
5844
+ const panEnd = new import_three18.Vector2();
5845
+ const panDelta = new import_three18.Vector2();
5846
+ const dollyStart = new import_three18.Vector2();
5847
+ const dollyEnd = new import_three18.Vector2();
5848
+ const dollyDelta = new import_three18.Vector2();
5849
+ const pointers = [];
5850
+ const pointerPositions = {};
5851
+ function getAutoRotationAngle() {
5852
+ return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
5505
5853
  }
5506
- this.init();
5507
- }
5508
- //<editor-fold desc="INIT">
5509
- createScene() {
5510
- return new MineRenderScene();
5511
- }
5512
- createCamera() {
5513
- switch (this.options.camera.type) {
5514
- case "perspective":
5515
- default:
5516
- return new import_three18.PerspectiveCamera(
5517
- this.options.camera.perspective.fov,
5518
- this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
5519
- this.options.camera.near,
5520
- this.options.camera.far
5521
- );
5522
- case "orthographic":
5523
- return new import_three18.OrthographicCamera(
5524
- this.options.camera.orthographic.left ?? this.viewWidth / -2,
5525
- this.options.camera.orthographic.right ?? this.viewWidth / 2,
5526
- this.options.camera.orthographic.top ?? this.viewHeight / 2,
5527
- this.options.camera.orthographic.bottom ?? this.viewHeight / -2,
5528
- this.options.camera.near,
5529
- this.options.camera.far
5530
- );
5854
+ function getZoomScale() {
5855
+ return Math.pow(0.95, scope.zoomSpeed);
5531
5856
  }
5532
- }
5533
- createRenderer() {
5534
- const renderer = new import_three18.WebGLRenderer({
5535
- antialias: this.options.render.antialias,
5536
- alpha: true,
5537
- powerPreference: "high-performance",
5538
- depth: true
5539
- });
5540
- renderer.setClearColor(0, 0);
5541
- renderer.shadowMap.enabled = true;
5542
- renderer.shadowMap.type = import_three18.PCFSoftShadowMap;
5543
- renderer.outputEncoding = import_three18.LinearEncoding;
5544
- renderer.setSize(this.viewWidth, this.viewHeight);
5545
- return renderer;
5546
- }
5547
- createComposer() {
5548
- const composer = new import_postprocessing.EffectComposer(this.renderer);
5549
- if (!this.options.composer.enabled) return composer;
5550
- composer.setSize(this.viewWidth, this.viewHeight);
5551
- composer.addPass(new import_postprocessing.RenderPass(this.scene, this.camera));
5552
- return composer;
5553
- }
5554
- //</editor-fold>
5555
- init() {
5556
- if (typeof window["__THREE_DEVTOOLS__"] !== "undefined") {
5557
- window["__THREE_DEVTOOLS__"].dispatchEvent(new CustomEvent("observe", { detail: this.scene }));
5558
- }
5559
- if (this.options.debug.grid) {
5560
- const gridHelper = new import_three18.GridHelper(128, 16);
5561
- this.scene.add(gridHelper);
5562
- const gridHelper2 = new import_three18.GridHelper(128, 16);
5563
- gridHelper2.rotation.x = 90 * (Math.PI / 180);
5564
- this.scene.add(gridHelper2);
5565
- const gridHelper3 = new import_three18.GridHelper(128, 16);
5566
- gridHelper3.rotation.z = 90 * (Math.PI / 180);
5567
- this.scene.add(gridHelper3);
5857
+ function rotateLeft(angle) {
5858
+ sphericalDelta.theta -= angle;
5568
5859
  }
5569
- if (this.options.debug.axes) {
5570
- const axesHelper = new import_three18.AxesHelper(64);
5571
- this.scene.add(axesHelper);
5860
+ function rotateUp(angle) {
5861
+ sphericalDelta.phi -= angle;
5572
5862
  }
5573
- if (this.options.camera.position) {
5574
- if (isVector3(this.options.camera.position)) {
5575
- this.camera.position.set(this.options.camera.position.x, this.options.camera.position.y, this.options.camera.position.z);
5576
- } else if (isTripleArray(this.options.camera.position)) {
5577
- this.camera.position.set(this.options.camera.position[0], this.options.camera.position[1], this.options.camera.position[2]);
5863
+ const panLeft = function() {
5864
+ const v = new import_three18.Vector3();
5865
+ return function panLeft2(distance, objectMatrix) {
5866
+ v.setFromMatrixColumn(objectMatrix, 0);
5867
+ v.multiplyScalar(-distance);
5868
+ panOffset.add(v);
5869
+ };
5870
+ }();
5871
+ const panUp = function() {
5872
+ const v = new import_three18.Vector3();
5873
+ return function panUp2(distance, objectMatrix) {
5874
+ if (scope.screenSpacePanning === true) {
5875
+ v.setFromMatrixColumn(objectMatrix, 1);
5876
+ } else {
5877
+ v.setFromMatrixColumn(objectMatrix, 0);
5878
+ v.crossVectors(scope.object.up, v);
5879
+ }
5880
+ v.multiplyScalar(distance);
5881
+ panOffset.add(v);
5882
+ };
5883
+ }();
5884
+ const pan = function() {
5885
+ const offset = new import_three18.Vector3();
5886
+ return function pan2(deltaX, deltaY) {
5887
+ const element = scope.domElement;
5888
+ if (scope.object.isPerspectiveCamera) {
5889
+ const position = scope.object.position;
5890
+ offset.copy(position).sub(scope.target);
5891
+ let targetDistance = offset.length();
5892
+ targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180);
5893
+ panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
5894
+ panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);
5895
+ } else if (scope.object.isOrthographicCamera) {
5896
+ panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);
5897
+ panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);
5898
+ } else {
5899
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.");
5900
+ scope.enablePan = false;
5901
+ }
5902
+ };
5903
+ }();
5904
+ function dollyOut(dollyScale) {
5905
+ if (scope.object.isPerspectiveCamera) {
5906
+ scale /= dollyScale;
5907
+ } else if (scope.object.isOrthographicCamera) {
5908
+ scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
5909
+ scope.object.updateProjectionMatrix();
5910
+ zoomChanged = true;
5911
+ } else {
5912
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
5913
+ scope.enableZoom = false;
5578
5914
  }
5579
5915
  }
5580
- if (this.options.camera.lookingAt) {
5581
- if (isVector3(this.options.camera.lookingAt)) {
5582
- this.camera.lookAt(this.options.camera.lookingAt);
5583
- } else if (isTripleArray(this.options.camera.lookingAt)) {
5584
- this.camera.lookAt(this.options.camera.lookingAt[0], this.options.camera.lookingAt[1], this.options.camera.lookingAt[2]);
5916
+ function dollyIn(dollyScale) {
5917
+ if (scope.object.isPerspectiveCamera) {
5918
+ scale *= dollyScale;
5919
+ } else if (scope.object.isOrthographicCamera) {
5920
+ scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
5921
+ scope.object.updateProjectionMatrix();
5922
+ zoomChanged = true;
5923
+ } else {
5924
+ console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
5925
+ scope.enableZoom = false;
5585
5926
  }
5586
5927
  }
5587
- if (this.options.render.autoResize) {
5588
- this._resizeListener = () => {
5589
- this.resize(this.viewWidth, this.viewHeight);
5590
- };
5591
- window.addEventListener("resize", this._resizeListener);
5592
- }
5593
- }
5594
- get element() {
5595
- return this._element;
5596
- }
5597
- appendTo(element) {
5598
- this._element = element;
5599
- this._element.appendChild(this.renderer.domElement);
5600
- if (this.viewWidth == 0) {
5601
- console.warn("0 element width");
5928
+ function handleMouseDownRotate(event) {
5929
+ rotateStart.set(event.clientX, event.clientY);
5602
5930
  }
5603
- if (this.viewHeight == 0) {
5604
- console.warn("0 element height");
5931
+ function handleMouseDownDolly(event) {
5932
+ dollyStart.set(event.clientX, event.clientY);
5605
5933
  }
5606
- this.resize(this.viewWidth, this.viewHeight);
5607
- }
5608
- /**
5609
- * Register an EventDispatcher which may update the scene or renderer in order to redraw the scene
5610
- */
5611
- registerEventDispatcher(dispatcher, changeEvent2 = "change") {
5612
- dispatcher.addEventListener(changeEvent2, (event) => {
5613
- this._dirty = true;
5614
- });
5615
- }
5616
- resize(width, height) {
5617
- if (isPerspectiveCamera(this.camera)) {
5618
- this.camera.aspect = width / height;
5619
- this.camera.updateProjectionMatrix();
5620
- } else if (isOrthographicCamera(this.camera)) {
5621
- this.camera.left = width / -2;
5622
- this.camera.right = width / 2;
5623
- this.camera.top = height / 2;
5624
- this.camera.bottom = height / -2;
5625
- this.camera.updateProjectionMatrix();
5934
+ function handleMouseDownPan(event) {
5935
+ panStart.set(event.clientX, event.clientY);
5626
5936
  }
5627
- this.renderer.setSize(width, height);
5628
- this.composer.setSize(width, height);
5629
- }
5630
- //<editor-fold desc="RENDER">
5631
- get dirty() {
5632
- return this._dirty || this.scene.dirty;
5633
- }
5634
- set dirty(dirty) {
5635
- this._dirty = dirty;
5636
- this.scene.dirty = dirty;
5637
- }
5638
- start() {
5639
- stop();
5640
- this.renderer.setAnimationLoop(this._animationLoop);
5641
- }
5642
- stop() {
5643
- this.renderer.setAnimationLoop(null);
5644
- if (this._animationTimer)
5645
- clearTimeout(this._animationTimer);
5646
- this._animationTimer = void 0;
5647
- if (this._animationFrame)
5648
- cancelAnimationFrame(this._animationFrame);
5649
- this._animationFrame = void 0;
5650
- }
5651
- animate(t) {
5652
- if (this._stats) {
5653
- this._stats.begin();
5937
+ function handleMouseMoveRotate(event) {
5938
+ rotateEnd.set(event.clientX, event.clientY);
5939
+ rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
5940
+ const element = scope.domElement;
5941
+ rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
5942
+ rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
5943
+ rotateStart.copy(rotateEnd);
5944
+ scope.update();
5654
5945
  }
5655
- if (this.dirty || this.options.render.renderAlways) {
5656
- if (this.options.composer.enabled) {
5657
- this.composer.render();
5658
- } else {
5659
- this.renderer.render(this.scene, this.camera);
5946
+ function handleMouseMoveDolly(event) {
5947
+ dollyEnd.set(event.clientX, event.clientY);
5948
+ dollyDelta.subVectors(dollyEnd, dollyStart);
5949
+ if (dollyDelta.y > 0) {
5950
+ dollyOut(getZoomScale());
5951
+ } else if (dollyDelta.y < 0) {
5952
+ dollyIn(getZoomScale());
5660
5953
  }
5954
+ dollyStart.copy(dollyEnd);
5955
+ scope.update();
5661
5956
  }
5662
- this.dirty = false;
5663
- if (this._stats) {
5664
- this._stats.end();
5957
+ function handleMouseMovePan(event) {
5958
+ panEnd.set(event.clientX, event.clientY);
5959
+ panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
5960
+ pan(panDelta.x, panDelta.y);
5961
+ panStart.copy(panEnd);
5962
+ scope.update();
5665
5963
  }
5666
- }
5667
- //</editor-fold>
5668
- toImage() {
5669
- return this.renderer.domElement.toDataURL();
5670
- }
5671
- ///
5672
- get attachedToBody() {
5673
- return this.element === document.body;
5674
- }
5675
- get viewWidth() {
5676
- var _a;
5677
- return this.attachedToBody ? window.innerWidth : ((_a = this.element) == null ? void 0 : _a.offsetWidth) || 0;
5678
- }
5679
- get viewHeight() {
5680
- var _a;
5681
- return this.attachedToBody ? window.innerHeight : ((_a = this.element) == null ? void 0 : _a.offsetHeight) || 0;
5682
- }
5683
- get scene() {
5684
- return this._scene;
5685
- }
5686
- get camera() {
5687
- return this._camera;
5688
- }
5689
- get renderer() {
5690
- return this._renderer;
5691
- }
5692
- get composer() {
5693
- return this._composer;
5694
- }
5695
- ///
5696
- };
5697
- _Renderer.DEFAULT_OPTIONS = (0, import_ts_deepmerge10.default)({}, {
5698
- camera: {
5699
- type: "perspective",
5700
- near: 1,
5701
- far: 5e3,
5702
- perspective: {
5703
- aspect: void 0,
5704
- fov: 50
5705
- },
5706
- orthographic: {
5707
- left: void 0,
5708
- right: void 0,
5709
- top: void 0,
5710
- bottom: void 0
5711
- },
5712
- position: new import_three18.Vector3(50, 50, 50),
5713
- lookingAt: new import_three18.Vector3(0, 0, 0)
5714
- },
5715
- render: {
5716
- fpsLimit: 60,
5717
- stats: false,
5718
- antialias: true,
5719
- shade: true,
5720
- autoResize: true,
5721
- renderAlways: false
5722
- },
5723
- composer: {
5724
- enabled: true
5725
- },
5726
- debug: {
5727
- grid: false,
5728
- axes: false
5729
- }
5730
- });
5731
- var Renderer = _Renderer;
5732
-
5733
- // src/skin/Skins.ts
5734
- var Skins = class {
5735
- //<editor-fold desc="Skins">
5736
- static async fromUuidOrUsername(uuidOrUsername) {
5737
- if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
5738
- return this.fromUuid(uuidOrUsername);
5964
+ function handleMouseUp() {
5739
5965
  }
5740
- return this.fromUsername(uuidOrUsername);
5741
- }
5742
- static async fromUuid(uuid) {
5743
- return this.getSkinProxySkinUrl(uuid);
5744
- }
5745
- static async fromUsername(username) {
5746
- return this.usernameToUuid(username).then((uuid) => {
5747
- if (uuid) {
5748
- return this.fromUuid(uuid);
5749
- }
5750
- return void 0;
5751
- });
5752
- }
5753
- static async fromMineSkin(mineskinId) {
5754
- return this.getMineSkin(mineskinId).then((mineskin) => {
5755
- if (mineskin) {
5756
- return mineskin["data"]["texture"]["value"]["urls"]["skins"];
5966
+ function handleMouseWheel(event) {
5967
+ if (event.deltaY < 0) {
5968
+ dollyIn(getZoomScale());
5969
+ } else if (event.deltaY > 0) {
5970
+ dollyOut(getZoomScale());
5757
5971
  }
5758
- return void 0;
5759
- });
5760
- }
5761
- //</editor-fold>
5762
- //<editor-fold desc="Capes">
5763
- static async capeFromUuidOrUsername(uuidOrUsername) {
5764
- if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
5765
- return this.capeFromUuid(uuidOrUsername);
5972
+ scope.update();
5766
5973
  }
5767
- return this.capeFromUsername(uuidOrUsername);
5768
- }
5769
- static async capeFromUuid(uuid) {
5770
- return this.getSkinProxyCapeUrl(uuid);
5771
- }
5772
- static async capeFromUsername(username) {
5773
- return this.usernameToUuid(username).then((uuid) => {
5774
- if (uuid) {
5775
- return this.capeFromUuid(uuid);
5776
- }
5777
- return void 0;
5778
- });
5779
- }
5780
- static async capeFromCapesDev(uuid, capeType = "minecraft") {
5781
- return this.getCapesDev(uuid, capeType).then((cape) => {
5782
- if (cape) {
5783
- return cape == null ? void 0 : cape.stillImageUrl;
5784
- }
5785
- return void 0;
5786
- });
5787
- }
5788
- //</editor-fold>
5789
- //<editor-fold desc="Helpers">
5790
- static async usernameToUuid(username) {
5791
- return this.usernameToUuidSkinProxy(username);
5792
- }
5793
- static async usernameToUuidSkinProxy(username) {
5794
- return Requests.genericRequest({
5795
- baseURL: "https://minecraft-skin-proxy.inventive.workers.dev",
5796
- url: "/uuid/" + username
5797
- }).then((res) => {
5798
- if (res.status === 200) {
5799
- return res.data["id"];
5974
+ function handleKeyDown(event) {
5975
+ let needsUpdate = false;
5976
+ switch (event.code) {
5977
+ case scope.keys.UP:
5978
+ pan(0, scope.keyPanSpeed);
5979
+ needsUpdate = true;
5980
+ break;
5981
+ case scope.keys.BOTTOM:
5982
+ pan(0, -scope.keyPanSpeed);
5983
+ needsUpdate = true;
5984
+ break;
5985
+ case scope.keys.LEFT:
5986
+ pan(scope.keyPanSpeed, 0);
5987
+ needsUpdate = true;
5988
+ break;
5989
+ case scope.keys.RIGHT:
5990
+ pan(-scope.keyPanSpeed, 0);
5991
+ needsUpdate = true;
5992
+ break;
5800
5993
  }
5801
- return void 0;
5802
- }).catch((err) => {
5803
- console.warn(err);
5804
- return void 0;
5805
- });
5806
- }
5807
- static async usernameToUuidMineTools(username) {
5808
- return Requests.genericRequest({
5809
- baseURL: "https://api.minetools.eu",
5810
- url: "/uuid/" + username
5811
- }).then((res) => {
5812
- if (res.status === 200) {
5813
- return res.data["id"];
5994
+ if (needsUpdate) {
5995
+ event.preventDefault();
5996
+ scope.update();
5814
5997
  }
5815
- return void 0;
5816
- }).catch((err) => {
5817
- console.warn(err);
5818
- return void 0;
5819
- });
5820
- }
5821
- static async getProfileFromMinetools(uuid) {
5822
- return Requests.genericRequest({
5823
- baseURL: "https://api.minetools.eu",
5824
- url: "/profile/" + uuid
5825
- }).then((res) => {
5826
- if (res.status === 200) {
5827
- return res.data;
5998
+ }
5999
+ function handleTouchStartRotate() {
6000
+ if (pointers.length === 1) {
6001
+ rotateStart.set(pointers[0].pageX, pointers[0].pageY);
6002
+ } else {
6003
+ const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
6004
+ const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
6005
+ rotateStart.set(x, y);
5828
6006
  }
5829
- });
5830
- }
5831
- static async getMineSkin(mineskinId) {
5832
- return Requests.genericRequest({
5833
- baseURL: "https://api.mineskin.org",
5834
- url: "/get/uuid/" + mineskinId
5835
- }).then((res) => {
5836
- if (res.status === 200) {
5837
- return res.data;
6007
+ }
6008
+ function handleTouchStartPan() {
6009
+ if (pointers.length === 1) {
6010
+ panStart.set(pointers[0].pageX, pointers[0].pageY);
6011
+ } else {
6012
+ const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
6013
+ const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
6014
+ panStart.set(x, y);
5838
6015
  }
5839
- return void 0;
5840
- }).catch((err) => {
5841
- console.warn(err);
5842
- return void 0;
5843
- });
5844
- }
5845
- static async getCapesDev(uuid, type = "all") {
5846
- return Requests.genericRequest({
5847
- baseURL: "https://api.capes.dev",
5848
- url: "/load/" + uuid + "/" + type
5849
- }).then((res) => {
5850
- if (res.status === 200) {
5851
- return res.data;
6016
+ }
6017
+ function handleTouchStartDolly() {
6018
+ const dx = pointers[0].pageX - pointers[1].pageX;
6019
+ const dy = pointers[0].pageY - pointers[1].pageY;
6020
+ const distance = Math.sqrt(dx * dx + dy * dy);
6021
+ dollyStart.set(0, distance);
6022
+ }
6023
+ function handleTouchStartDollyPan() {
6024
+ if (scope.enableZoom) handleTouchStartDolly();
6025
+ if (scope.enablePan) handleTouchStartPan();
6026
+ }
6027
+ function handleTouchStartDollyRotate() {
6028
+ if (scope.enableZoom) handleTouchStartDolly();
6029
+ if (scope.enableRotate) handleTouchStartRotate();
6030
+ }
6031
+ function handleTouchMoveRotate(event) {
6032
+ if (pointers.length == 1) {
6033
+ rotateEnd.set(event.pageX, event.pageY);
6034
+ } else {
6035
+ const position = getSecondPointerPosition(event);
6036
+ const x = 0.5 * (event.pageX + position.x);
6037
+ const y = 0.5 * (event.pageY + position.y);
6038
+ rotateEnd.set(x, y);
5852
6039
  }
5853
- return void 0;
5854
- }).catch((err) => {
5855
- console.warn(err);
5856
- return void 0;
5857
- });
5858
- }
5859
- static getCrafatarSkinUrl(uuid) {
5860
- return "https://crafatar.com/skins/" + uuid;
5861
- }
5862
- static getCrafatarCapeUrl(uuid) {
5863
- return "https://crafatar.com/capes/" + uuid;
5864
- }
5865
- static getMcHeadsSkinUrl(uuid) {
5866
- return "https://mc-heads.net/skin/" + uuid;
5867
- }
5868
- static getMineSkinPlayerSkinUrl(uuid) {
5869
- return "https://mineskin.org/skin/player/" + uuid;
5870
- }
5871
- static getSkinProxySkinUrl(uuid) {
5872
- return "https://minecraft-skin-proxy.inventive.workers.dev/skin/" + uuid;
5873
- }
5874
- static getSkinProxyCapeUrl(uuid) {
5875
- return "https://minecraft-skin-proxy.inventive.workers.dev/cape/" + uuid;
5876
- }
5877
- //</editor-fold>
5878
- };
5879
-
5880
- // src/three/OrbitControls.js
5881
- var import_three20 = require("three");
5882
- var _changeEvent = { type: "change" };
5883
- var _startEvent = { type: "start" };
5884
- var _endEvent = { type: "end" };
5885
- var OrbitControls = class extends import_three20.EventDispatcher {
5886
- constructor(object, domElement) {
5887
- super();
5888
- if (domElement === void 0) console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.');
5889
- if (domElement === document) console.error('THREE.OrbitControls: "document" should not be used as the target "domElement". Please use "renderer.domElement" instead.');
5890
- this.object = object;
5891
- this.domElement = domElement;
5892
- this.domElement.style.touchAction = "none";
5893
- this.enabled = true;
5894
- this.target = new import_three20.Vector3();
5895
- this.minDistance = 0;
5896
- this.maxDistance = Infinity;
5897
- this.minZoom = 0;
5898
- this.maxZoom = Infinity;
5899
- this.minPolarAngle = 0;
5900
- this.maxPolarAngle = Math.PI;
5901
- this.minAzimuthAngle = -Infinity;
5902
- this.maxAzimuthAngle = Infinity;
5903
- this.enableDamping = false;
5904
- this.dampingFactor = 0.05;
5905
- this.enableZoom = true;
5906
- this.zoomSpeed = 1;
5907
- this.enableRotate = true;
5908
- this.rotateSpeed = 1;
5909
- this.enablePan = true;
5910
- this.panSpeed = 1;
5911
- this.screenSpacePanning = true;
5912
- this.keyPanSpeed = 7;
5913
- this.autoRotate = false;
5914
- this.autoRotateSpeed = 2;
5915
- this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" };
5916
- this.mouseButtons = { LEFT: import_three20.MOUSE.ROTATE, MIDDLE: import_three20.MOUSE.DOLLY, RIGHT: import_three20.MOUSE.PAN };
5917
- this.touches = { ONE: import_three20.TOUCH.ROTATE, TWO: import_three20.TOUCH.DOLLY_PAN };
5918
- this.target0 = this.target.clone();
5919
- this.position0 = this.object.position.clone();
5920
- this.zoom0 = this.object.zoom;
5921
- this._domElementKeyEvents = null;
5922
- this.getPolarAngle = function() {
5923
- return spherical.phi;
5924
- };
5925
- this.getAzimuthalAngle = function() {
5926
- return spherical.theta;
5927
- };
5928
- this.getDistance = function() {
5929
- return this.object.position.distanceTo(this.target);
5930
- };
5931
- this.saveState = function() {
5932
- scope.target0.copy(scope.target);
5933
- scope.position0.copy(scope.object.position);
5934
- scope.zoom0 = scope.object.zoom;
5935
- };
5936
- this.reset = function() {
5937
- scope.target.copy(scope.target0);
5938
- scope.object.position.copy(scope.position0);
5939
- scope.object.zoom = scope.zoom0;
5940
- scope.object.updateProjectionMatrix();
5941
- scope.dispatchEvent(_changeEvent);
5942
- scope.update();
5943
- state = STATE.NONE;
5944
- };
5945
- this.update = function() {
5946
- const offset = new import_three20.Vector3();
5947
- const quat = new import_three20.Quaternion().setFromUnitVectors(object.up, new import_three20.Vector3(0, 1, 0));
5948
- const quatInverse = quat.clone().invert();
5949
- const lastPosition = new import_three20.Vector3();
5950
- const lastQuaternion = new import_three20.Quaternion();
5951
- const twoPI = 2 * Math.PI;
5952
- return function update() {
5953
- const position = scope.object.position;
5954
- offset.copy(position).sub(scope.target);
5955
- offset.applyQuaternion(quat);
5956
- spherical.setFromVector3(offset);
5957
- if (scope.autoRotate && state === STATE.NONE) {
5958
- rotateLeft(getAutoRotationAngle());
5959
- }
5960
- if (scope.enableDamping) {
5961
- spherical.theta += sphericalDelta.theta * scope.dampingFactor;
5962
- spherical.phi += sphericalDelta.phi * scope.dampingFactor;
5963
- } else {
5964
- spherical.theta += sphericalDelta.theta;
5965
- spherical.phi += sphericalDelta.phi;
5966
- }
5967
- let min = scope.minAzimuthAngle;
5968
- let max = scope.maxAzimuthAngle;
5969
- if (isFinite(min) && isFinite(max)) {
5970
- if (min < -Math.PI) min += twoPI;
5971
- else if (min > Math.PI) min -= twoPI;
5972
- if (max < -Math.PI) max += twoPI;
5973
- else if (max > Math.PI) max -= twoPI;
5974
- if (min <= max) {
5975
- spherical.theta = Math.max(min, Math.min(max, spherical.theta));
5976
- } else {
5977
- spherical.theta = spherical.theta > (min + max) / 2 ? Math.max(min, spherical.theta) : Math.min(max, spherical.theta);
5978
- }
5979
- }
5980
- spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));
5981
- spherical.makeSafe();
5982
- spherical.radius *= scale;
5983
- spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));
5984
- if (scope.enableDamping === true) {
5985
- scope.target.addScaledVector(panOffset, scope.dampingFactor);
5986
- } else {
5987
- scope.target.add(panOffset);
5988
- }
5989
- offset.setFromSpherical(spherical);
5990
- offset.applyQuaternion(quatInverse);
5991
- position.copy(scope.target).add(offset);
5992
- scope.object.lookAt(scope.target);
5993
- if (scope.enableDamping === true) {
5994
- sphericalDelta.theta *= 1 - scope.dampingFactor;
5995
- sphericalDelta.phi *= 1 - scope.dampingFactor;
5996
- panOffset.multiplyScalar(1 - scope.dampingFactor);
5997
- } else {
5998
- sphericalDelta.set(0, 0, 0);
5999
- panOffset.set(0, 0, 0);
6000
- }
6001
- scale = 1;
6002
- if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {
6003
- scope.dispatchEvent(_changeEvent);
6004
- lastPosition.copy(scope.object.position);
6005
- lastQuaternion.copy(scope.object.quaternion);
6006
- zoomChanged = false;
6007
- return true;
6008
- }
6009
- return false;
6010
- };
6011
- }();
6012
- this.dispose = function() {
6013
- scope.domElement.removeEventListener("contextmenu", onContextMenu);
6014
- scope.domElement.removeEventListener("pointerdown", onPointerDown);
6015
- scope.domElement.removeEventListener("pointercancel", onPointerCancel);
6016
- scope.domElement.removeEventListener("wheel", onMouseWheel);
6017
- scope.domElement.removeEventListener("pointermove", onPointerMove);
6018
- scope.domElement.removeEventListener("pointerup", onPointerUp);
6019
- if (scope._domElementKeyEvents !== null) {
6020
- scope._domElementKeyEvents.removeEventListener("keydown", onKeyDown);
6040
+ rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
6041
+ const element = scope.domElement;
6042
+ rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
6043
+ rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
6044
+ rotateStart.copy(rotateEnd);
6045
+ }
6046
+ function handleTouchMovePan(event) {
6047
+ if (pointers.length === 1) {
6048
+ panEnd.set(event.pageX, event.pageY);
6049
+ } else {
6050
+ const position = getSecondPointerPosition(event);
6051
+ const x = 0.5 * (event.pageX + position.x);
6052
+ const y = 0.5 * (event.pageY + position.y);
6053
+ panEnd.set(x, y);
6021
6054
  }
6022
- };
6023
- const scope = this;
6024
- const STATE = {
6025
- NONE: -1,
6026
- ROTATE: 0,
6027
- DOLLY: 1,
6028
- PAN: 2,
6029
- TOUCH_ROTATE: 3,
6030
- TOUCH_PAN: 4,
6031
- TOUCH_DOLLY_PAN: 5,
6032
- TOUCH_DOLLY_ROTATE: 6
6033
- };
6034
- let state = STATE.NONE;
6035
- const EPS = 1e-6;
6036
- const spherical = new import_three20.Spherical();
6037
- const sphericalDelta = new import_three20.Spherical();
6038
- let scale = 1;
6039
- const panOffset = new import_three20.Vector3();
6040
- let zoomChanged = false;
6041
- const rotateStart = new import_three20.Vector2();
6042
- const rotateEnd = new import_three20.Vector2();
6043
- const rotateDelta = new import_three20.Vector2();
6044
- const panStart = new import_three20.Vector2();
6045
- const panEnd = new import_three20.Vector2();
6046
- const panDelta = new import_three20.Vector2();
6047
- const dollyStart = new import_three20.Vector2();
6048
- const dollyEnd = new import_three20.Vector2();
6049
- const dollyDelta = new import_three20.Vector2();
6050
- const pointers = [];
6051
- const pointerPositions = {};
6052
- function getAutoRotationAngle() {
6053
- return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
6055
+ panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
6056
+ pan(panDelta.x, panDelta.y);
6057
+ panStart.copy(panEnd);
6054
6058
  }
6055
- function getZoomScale() {
6056
- return Math.pow(0.95, scope.zoomSpeed);
6059
+ function handleTouchMoveDolly(event) {
6060
+ const position = getSecondPointerPosition(event);
6061
+ const dx = event.pageX - position.x;
6062
+ const dy = event.pageY - position.y;
6063
+ const distance = Math.sqrt(dx * dx + dy * dy);
6064
+ dollyEnd.set(0, distance);
6065
+ dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed));
6066
+ dollyOut(dollyDelta.y);
6067
+ dollyStart.copy(dollyEnd);
6057
6068
  }
6058
- function rotateLeft(angle) {
6059
- sphericalDelta.theta -= angle;
6069
+ function handleTouchMoveDollyPan(event) {
6070
+ if (scope.enableZoom) handleTouchMoveDolly(event);
6071
+ if (scope.enablePan) handleTouchMovePan(event);
6060
6072
  }
6061
- function rotateUp(angle) {
6062
- sphericalDelta.phi -= angle;
6073
+ function handleTouchMoveDollyRotate(event) {
6074
+ if (scope.enableZoom) handleTouchMoveDolly(event);
6075
+ if (scope.enableRotate) handleTouchMoveRotate(event);
6063
6076
  }
6064
- const panLeft = function() {
6065
- const v = new import_three20.Vector3();
6066
- return function panLeft2(distance, objectMatrix) {
6067
- v.setFromMatrixColumn(objectMatrix, 0);
6068
- v.multiplyScalar(-distance);
6069
- panOffset.add(v);
6070
- };
6071
- }();
6072
- const panUp = function() {
6073
- const v = new import_three20.Vector3();
6074
- return function panUp2(distance, objectMatrix) {
6075
- if (scope.screenSpacePanning === true) {
6076
- v.setFromMatrixColumn(objectMatrix, 1);
6077
- } else {
6078
- v.setFromMatrixColumn(objectMatrix, 0);
6079
- v.crossVectors(scope.object.up, v);
6080
- }
6081
- v.multiplyScalar(distance);
6082
- panOffset.add(v);
6083
- };
6084
- }();
6085
- const pan = function() {
6086
- const offset = new import_three20.Vector3();
6087
- return function pan2(deltaX, deltaY) {
6088
- const element = scope.domElement;
6089
- if (scope.object.isPerspectiveCamera) {
6090
- const position = scope.object.position;
6091
- offset.copy(position).sub(scope.target);
6092
- let targetDistance = offset.length();
6093
- targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180);
6094
- panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);
6095
- panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);
6096
- } else if (scope.object.isOrthographicCamera) {
6097
- panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);
6098
- panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);
6099
- } else {
6100
- console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.");
6101
- scope.enablePan = false;
6102
- }
6103
- };
6104
- }();
6105
- function dollyOut(dollyScale) {
6106
- if (scope.object.isPerspectiveCamera) {
6107
- scale /= dollyScale;
6108
- } else if (scope.object.isOrthographicCamera) {
6109
- scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));
6110
- scope.object.updateProjectionMatrix();
6111
- zoomChanged = true;
6077
+ function handleTouchEnd() {
6078
+ }
6079
+ function onPointerDown(event) {
6080
+ if (scope.enabled === false) return;
6081
+ if (pointers.length === 0) {
6082
+ scope.domElement.setPointerCapture(event.pointerId);
6083
+ scope.domElement.addEventListener("pointermove", onPointerMove);
6084
+ scope.domElement.addEventListener("pointerup", onPointerUp);
6085
+ }
6086
+ addPointer(event);
6087
+ if (event.pointerType === "touch") {
6088
+ onTouchStart(event);
6112
6089
  } else {
6113
- console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
6114
- scope.enableZoom = false;
6090
+ onMouseDown(event);
6115
6091
  }
6116
6092
  }
6117
- function dollyIn(dollyScale) {
6118
- if (scope.object.isPerspectiveCamera) {
6119
- scale *= dollyScale;
6120
- } else if (scope.object.isOrthographicCamera) {
6121
- scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));
6122
- scope.object.updateProjectionMatrix();
6123
- zoomChanged = true;
6093
+ function onPointerMove(event) {
6094
+ if (scope.enabled === false) return;
6095
+ if (event.pointerType === "touch") {
6096
+ onTouchMove(event);
6124
6097
  } else {
6125
- console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.");
6126
- scope.enableZoom = false;
6098
+ onMouseMove(event);
6099
+ }
6100
+ }
6101
+ function onPointerUp(event) {
6102
+ if (scope.enabled === false) return;
6103
+ if (event.pointerType === "touch") {
6104
+ onTouchEnd();
6105
+ } else {
6106
+ onMouseUp(event);
6107
+ }
6108
+ removePointer(event);
6109
+ if (pointers.length === 0) {
6110
+ scope.domElement.releasePointerCapture(event.pointerId);
6111
+ scope.domElement.removeEventListener("pointermove", onPointerMove);
6112
+ scope.domElement.removeEventListener("pointerup", onPointerUp);
6113
+ }
6114
+ }
6115
+ function onPointerCancel(event) {
6116
+ removePointer(event);
6117
+ }
6118
+ function onMouseDown(event) {
6119
+ let mouseAction;
6120
+ switch (event.button) {
6121
+ case 0:
6122
+ mouseAction = scope.mouseButtons.LEFT;
6123
+ break;
6124
+ case 1:
6125
+ mouseAction = scope.mouseButtons.MIDDLE;
6126
+ break;
6127
+ case 2:
6128
+ mouseAction = scope.mouseButtons.RIGHT;
6129
+ break;
6130
+ default:
6131
+ mouseAction = -1;
6132
+ }
6133
+ switch (mouseAction) {
6134
+ case import_three18.MOUSE.DOLLY:
6135
+ if (scope.enableZoom === false) return;
6136
+ handleMouseDownDolly(event);
6137
+ state = STATE.DOLLY;
6138
+ break;
6139
+ case import_three18.MOUSE.ROTATE:
6140
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
6141
+ if (scope.enablePan === false) return;
6142
+ handleMouseDownPan(event);
6143
+ state = STATE.PAN;
6144
+ } else {
6145
+ if (scope.enableRotate === false) return;
6146
+ handleMouseDownRotate(event);
6147
+ state = STATE.ROTATE;
6148
+ }
6149
+ break;
6150
+ case import_three18.MOUSE.PAN:
6151
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
6152
+ if (scope.enableRotate === false) return;
6153
+ handleMouseDownRotate(event);
6154
+ state = STATE.ROTATE;
6155
+ } else {
6156
+ if (scope.enablePan === false) return;
6157
+ handleMouseDownPan(event);
6158
+ state = STATE.PAN;
6159
+ }
6160
+ break;
6161
+ default:
6162
+ state = STATE.NONE;
6163
+ }
6164
+ if (state !== STATE.NONE) {
6165
+ scope.dispatchEvent(_startEvent);
6166
+ }
6167
+ }
6168
+ function onMouseMove(event) {
6169
+ if (scope.enabled === false) return;
6170
+ switch (state) {
6171
+ case STATE.ROTATE:
6172
+ if (scope.enableRotate === false) return;
6173
+ handleMouseMoveRotate(event);
6174
+ break;
6175
+ case STATE.DOLLY:
6176
+ if (scope.enableZoom === false) return;
6177
+ handleMouseMoveDolly(event);
6178
+ break;
6179
+ case STATE.PAN:
6180
+ if (scope.enablePan === false) return;
6181
+ handleMouseMovePan(event);
6182
+ break;
6127
6183
  }
6128
6184
  }
6129
- function handleMouseDownRotate(event) {
6130
- rotateStart.set(event.clientX, event.clientY);
6131
- }
6132
- function handleMouseDownDolly(event) {
6133
- dollyStart.set(event.clientX, event.clientY);
6185
+ function onMouseUp(event) {
6186
+ handleMouseUp(event);
6187
+ scope.dispatchEvent(_endEvent);
6188
+ state = STATE.NONE;
6134
6189
  }
6135
- function handleMouseDownPan(event) {
6136
- panStart.set(event.clientX, event.clientY);
6190
+ function onMouseWheel(event) {
6191
+ if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE) return;
6192
+ event.preventDefault();
6193
+ scope.dispatchEvent(_startEvent);
6194
+ handleMouseWheel(event);
6195
+ scope.dispatchEvent(_endEvent);
6137
6196
  }
6138
- function handleMouseMoveRotate(event) {
6139
- rotateEnd.set(event.clientX, event.clientY);
6140
- rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
6141
- const element = scope.domElement;
6142
- rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
6143
- rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
6144
- rotateStart.copy(rotateEnd);
6145
- scope.update();
6197
+ function onKeyDown(event) {
6198
+ if (scope.enabled === false || scope.enablePan === false) return;
6199
+ handleKeyDown(event);
6146
6200
  }
6147
- function handleMouseMoveDolly(event) {
6148
- dollyEnd.set(event.clientX, event.clientY);
6149
- dollyDelta.subVectors(dollyEnd, dollyStart);
6150
- if (dollyDelta.y > 0) {
6151
- dollyOut(getZoomScale());
6152
- } else if (dollyDelta.y < 0) {
6153
- dollyIn(getZoomScale());
6201
+ function onTouchStart(event) {
6202
+ trackPointer(event);
6203
+ switch (pointers.length) {
6204
+ case 1:
6205
+ switch (scope.touches.ONE) {
6206
+ case import_three18.TOUCH.ROTATE:
6207
+ if (scope.enableRotate === false) return;
6208
+ handleTouchStartRotate();
6209
+ state = STATE.TOUCH_ROTATE;
6210
+ break;
6211
+ case import_three18.TOUCH.PAN:
6212
+ if (scope.enablePan === false) return;
6213
+ handleTouchStartPan();
6214
+ state = STATE.TOUCH_PAN;
6215
+ break;
6216
+ default:
6217
+ state = STATE.NONE;
6218
+ }
6219
+ break;
6220
+ case 2:
6221
+ switch (scope.touches.TWO) {
6222
+ case import_three18.TOUCH.DOLLY_PAN:
6223
+ if (scope.enableZoom === false && scope.enablePan === false) return;
6224
+ handleTouchStartDollyPan();
6225
+ state = STATE.TOUCH_DOLLY_PAN;
6226
+ break;
6227
+ case import_three18.TOUCH.DOLLY_ROTATE:
6228
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
6229
+ handleTouchStartDollyRotate();
6230
+ state = STATE.TOUCH_DOLLY_ROTATE;
6231
+ break;
6232
+ default:
6233
+ state = STATE.NONE;
6234
+ }
6235
+ break;
6236
+ default:
6237
+ state = STATE.NONE;
6154
6238
  }
6155
- dollyStart.copy(dollyEnd);
6156
- scope.update();
6157
- }
6158
- function handleMouseMovePan(event) {
6159
- panEnd.set(event.clientX, event.clientY);
6160
- panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
6161
- pan(panDelta.x, panDelta.y);
6162
- panStart.copy(panEnd);
6163
- scope.update();
6164
- }
6165
- function handleMouseUp() {
6166
- }
6167
- function handleMouseWheel(event) {
6168
- if (event.deltaY < 0) {
6169
- dollyIn(getZoomScale());
6170
- } else if (event.deltaY > 0) {
6171
- dollyOut(getZoomScale());
6239
+ if (state !== STATE.NONE) {
6240
+ scope.dispatchEvent(_startEvent);
6172
6241
  }
6173
- scope.update();
6174
6242
  }
6175
- function handleKeyDown(event) {
6176
- let needsUpdate = false;
6177
- switch (event.code) {
6178
- case scope.keys.UP:
6179
- pan(0, scope.keyPanSpeed);
6180
- needsUpdate = true;
6243
+ function onTouchMove(event) {
6244
+ trackPointer(event);
6245
+ switch (state) {
6246
+ case STATE.TOUCH_ROTATE:
6247
+ if (scope.enableRotate === false) return;
6248
+ handleTouchMoveRotate(event);
6249
+ scope.update();
6181
6250
  break;
6182
- case scope.keys.BOTTOM:
6183
- pan(0, -scope.keyPanSpeed);
6184
- needsUpdate = true;
6251
+ case STATE.TOUCH_PAN:
6252
+ if (scope.enablePan === false) return;
6253
+ handleTouchMovePan(event);
6254
+ scope.update();
6185
6255
  break;
6186
- case scope.keys.LEFT:
6187
- pan(scope.keyPanSpeed, 0);
6188
- needsUpdate = true;
6256
+ case STATE.TOUCH_DOLLY_PAN:
6257
+ if (scope.enableZoom === false && scope.enablePan === false) return;
6258
+ handleTouchMoveDollyPan(event);
6259
+ scope.update();
6189
6260
  break;
6190
- case scope.keys.RIGHT:
6191
- pan(-scope.keyPanSpeed, 0);
6192
- needsUpdate = true;
6261
+ case STATE.TOUCH_DOLLY_ROTATE:
6262
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
6263
+ handleTouchMoveDollyRotate(event);
6264
+ scope.update();
6193
6265
  break;
6266
+ default:
6267
+ state = STATE.NONE;
6194
6268
  }
6195
- if (needsUpdate) {
6196
- event.preventDefault();
6197
- scope.update();
6269
+ }
6270
+ function onTouchEnd(event) {
6271
+ handleTouchEnd(event);
6272
+ scope.dispatchEvent(_endEvent);
6273
+ state = STATE.NONE;
6274
+ }
6275
+ function onContextMenu(event) {
6276
+ if (scope.enabled === false) return;
6277
+ event.preventDefault();
6278
+ }
6279
+ function addPointer(event) {
6280
+ pointers.push(event);
6281
+ }
6282
+ function removePointer(event) {
6283
+ delete pointerPositions[event.pointerId];
6284
+ for (let i = 0; i < pointers.length; i++) {
6285
+ if (pointers[i].pointerId == event.pointerId) {
6286
+ pointers.splice(i, 1);
6287
+ return;
6288
+ }
6198
6289
  }
6199
6290
  }
6200
- function handleTouchStartRotate() {
6201
- if (pointers.length === 1) {
6202
- rotateStart.set(pointers[0].pageX, pointers[0].pageY);
6203
- } else {
6204
- const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
6205
- const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
6206
- rotateStart.set(x, y);
6291
+ function trackPointer(event) {
6292
+ let position = pointerPositions[event.pointerId];
6293
+ if (position === void 0) {
6294
+ position = new import_three18.Vector2();
6295
+ pointerPositions[event.pointerId] = position;
6207
6296
  }
6297
+ position.set(event.pageX, event.pageY);
6208
6298
  }
6209
- function handleTouchStartPan() {
6210
- if (pointers.length === 1) {
6211
- panStart.set(pointers[0].pageX, pointers[0].pageY);
6212
- } else {
6213
- const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
6214
- const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
6215
- panStart.set(x, y);
6299
+ function getSecondPointerPosition(event) {
6300
+ const pointer = event.pointerId === pointers[0].pointerId ? pointers[1] : pointers[0];
6301
+ return pointerPositions[pointer.pointerId];
6302
+ }
6303
+ scope.domElement.addEventListener("contextmenu", onContextMenu);
6304
+ scope.domElement.addEventListener("pointerdown", onPointerDown);
6305
+ scope.domElement.addEventListener("pointercancel", onPointerCancel);
6306
+ scope.domElement.addEventListener("wheel", onMouseWheel, { passive: false });
6307
+ this.update();
6308
+ }
6309
+ };
6310
+ var MapControls = class extends OrbitControls {
6311
+ constructor(object, domElement) {
6312
+ super(object, domElement);
6313
+ this.screenSpacePanning = false;
6314
+ this.mouseButtons.LEFT = import_three18.MOUSE.PAN;
6315
+ this.mouseButtons.RIGHT = import_three18.MOUSE.ROTATE;
6316
+ this.touches.ONE = import_three18.TOUCH.PAN;
6317
+ this.touches.TWO = import_three18.TOUCH.DOLLY_ROTATE;
6318
+ }
6319
+ };
6320
+
6321
+ // src/renderer/Renderer.ts
6322
+ var Renderer = class _Renderer {
6323
+ constructor(options) {
6324
+ this._dirty = true;
6325
+ this._resizeListener = void 0;
6326
+ this._disposed = false;
6327
+ this._debugHelpers = [];
6328
+ this._eventDispatchers = /* @__PURE__ */ new Map();
6329
+ this._changeListener = () => {
6330
+ this._dirty = true;
6331
+ };
6332
+ this.options = (0, import_ts_deepmerge9.default)({}, _Renderer.DEFAULT_OPTIONS, options ?? {});
6333
+ this._animationLoop = this.animate.bind(this);
6334
+ this._frameInterval = this.options.render.fpsLimit > 0 ? 1e3 / this.options.render.fpsLimit : void 0;
6335
+ this._scene = this.createScene();
6336
+ this._camera = this.createCamera();
6337
+ this._renderer = this.createRenderer();
6338
+ this._composer = this.createComposer();
6339
+ if (this.options.render.stats) {
6340
+ this._stats = new import_stats.default();
6341
+ document.body.appendChild(this._stats.dom);
6342
+ }
6343
+ this.init();
6344
+ this._controls = this.createControls();
6345
+ }
6346
+ static {
6347
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge9.default)({}, {
6348
+ camera: {
6349
+ type: "perspective",
6350
+ near: 1,
6351
+ far: 5e3,
6352
+ perspective: {
6353
+ aspect: void 0,
6354
+ fov: 50
6355
+ },
6356
+ orthographic: {
6357
+ left: void 0,
6358
+ right: void 0,
6359
+ top: void 0,
6360
+ bottom: void 0
6361
+ },
6362
+ position: new import_three19.Vector3(50, 50, 50),
6363
+ lookingAt: new import_three19.Vector3(0, 0, 0)
6364
+ },
6365
+ render: {
6366
+ fpsLimit: 60,
6367
+ stats: false,
6368
+ antialias: true,
6369
+ shade: true,
6370
+ autoResize: true,
6371
+ renderAlways: false
6372
+ },
6373
+ composer: {
6374
+ enabled: true
6375
+ },
6376
+ controls: {
6377
+ enabled: false
6378
+ },
6379
+ debug: {
6380
+ grid: false,
6381
+ axes: false
6216
6382
  }
6383
+ });
6384
+ }
6385
+ //<editor-fold desc="INIT">
6386
+ createScene() {
6387
+ return new MineRenderScene();
6388
+ }
6389
+ createCamera() {
6390
+ switch (this.options.camera.type) {
6391
+ case "perspective":
6392
+ default:
6393
+ return new import_three19.PerspectiveCamera(
6394
+ this.options.camera.perspective.fov,
6395
+ this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
6396
+ this.options.camera.near,
6397
+ this.options.camera.far
6398
+ );
6399
+ case "orthographic":
6400
+ return new import_three19.OrthographicCamera(
6401
+ this.options.camera.orthographic.left ?? this.viewWidth / -2,
6402
+ this.options.camera.orthographic.right ?? this.viewWidth / 2,
6403
+ this.options.camera.orthographic.top ?? this.viewHeight / 2,
6404
+ this.options.camera.orthographic.bottom ?? this.viewHeight / -2,
6405
+ this.options.camera.near,
6406
+ this.options.camera.far
6407
+ );
6217
6408
  }
6218
- function handleTouchStartDolly() {
6219
- const dx = pointers[0].pageX - pointers[1].pageX;
6220
- const dy = pointers[0].pageY - pointers[1].pageY;
6221
- const distance = Math.sqrt(dx * dx + dy * dy);
6222
- dollyStart.set(0, distance);
6409
+ }
6410
+ createRenderer() {
6411
+ const renderer = new import_three19.WebGLRenderer({
6412
+ antialias: this.options.render.antialias,
6413
+ alpha: true,
6414
+ powerPreference: "high-performance",
6415
+ depth: true
6416
+ });
6417
+ renderer.setClearColor(0, 0);
6418
+ renderer.shadowMap.enabled = true;
6419
+ renderer.shadowMap.type = import_three19.PCFSoftShadowMap;
6420
+ renderer.outputColorSpace = import_three19.SRGBColorSpace;
6421
+ renderer.setSize(this.viewWidth, this.viewHeight);
6422
+ return renderer;
6423
+ }
6424
+ createComposer() {
6425
+ if (!this.options.composer.enabled) return void 0;
6426
+ const composer = new import_postprocessing.EffectComposer(this.renderer);
6427
+ composer.setSize(this.viewWidth, this.viewHeight);
6428
+ composer.addPass(new import_postprocessing.RenderPass(this.scene, this.camera));
6429
+ return composer;
6430
+ }
6431
+ createControls() {
6432
+ if (!this.options.controls?.enabled) return void 0;
6433
+ const position = this.camera.position.clone();
6434
+ const controls = new OrbitControls(this.camera, this.renderer.domElement);
6435
+ this.camera.position.copy(position);
6436
+ const target = this.options.camera.lookingAt;
6437
+ if (isVector3(target)) {
6438
+ controls.target.copy(target);
6439
+ } else if (isTripleArray(target)) {
6440
+ controls.target.set(target[0], target[1], target[2]);
6441
+ }
6442
+ controls.update();
6443
+ controls.saveState();
6444
+ this.registerEventDispatcher(controls);
6445
+ return controls;
6446
+ }
6447
+ //</editor-fold>
6448
+ init() {
6449
+ if (this._disposed) return;
6450
+ if (typeof window["__THREE_DEVTOOLS__"] !== "undefined") {
6451
+ window["__THREE_DEVTOOLS__"].dispatchEvent(new CustomEvent("observe", { detail: this.scene }));
6223
6452
  }
6224
- function handleTouchStartDollyPan() {
6225
- if (scope.enableZoom) handleTouchStartDolly();
6226
- if (scope.enablePan) handleTouchStartPan();
6453
+ if (this.options.debug.grid) {
6454
+ const gridHelper = new import_three19.GridHelper(128, 16);
6455
+ this._debugHelpers.push(gridHelper);
6456
+ this.scene.add(gridHelper);
6457
+ const gridHelper2 = new import_three19.GridHelper(128, 16);
6458
+ this._debugHelpers.push(gridHelper2);
6459
+ gridHelper2.rotation.x = 90 * (Math.PI / 180);
6460
+ this.scene.add(gridHelper2);
6461
+ const gridHelper3 = new import_three19.GridHelper(128, 16);
6462
+ this._debugHelpers.push(gridHelper3);
6463
+ gridHelper3.rotation.z = 90 * (Math.PI / 180);
6464
+ this.scene.add(gridHelper3);
6227
6465
  }
6228
- function handleTouchStartDollyRotate() {
6229
- if (scope.enableZoom) handleTouchStartDolly();
6230
- if (scope.enableRotate) handleTouchStartRotate();
6466
+ if (this.options.debug.axes) {
6467
+ const axesHelper = new import_three19.AxesHelper(64);
6468
+ this._debugHelpers.push(axesHelper);
6469
+ this.scene.add(axesHelper);
6231
6470
  }
6232
- function handleTouchMoveRotate(event) {
6233
- if (pointers.length == 1) {
6234
- rotateEnd.set(event.pageX, event.pageY);
6235
- } else {
6236
- const position = getSecondPointerPosition(event);
6237
- const x = 0.5 * (event.pageX + position.x);
6238
- const y = 0.5 * (event.pageY + position.y);
6239
- rotateEnd.set(x, y);
6471
+ if (this.options.camera.position) {
6472
+ if (isVector3(this.options.camera.position)) {
6473
+ this.camera.position.set(this.options.camera.position.x, this.options.camera.position.y, this.options.camera.position.z);
6474
+ } else if (isTripleArray(this.options.camera.position)) {
6475
+ this.camera.position.set(this.options.camera.position[0], this.options.camera.position[1], this.options.camera.position[2]);
6240
6476
  }
6241
- rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
6242
- const element = scope.domElement;
6243
- rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
6244
- rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
6245
- rotateStart.copy(rotateEnd);
6246
6477
  }
6247
- function handleTouchMovePan(event) {
6248
- if (pointers.length === 1) {
6249
- panEnd.set(event.pageX, event.pageY);
6250
- } else {
6251
- const position = getSecondPointerPosition(event);
6252
- const x = 0.5 * (event.pageX + position.x);
6253
- const y = 0.5 * (event.pageY + position.y);
6254
- panEnd.set(x, y);
6478
+ if (this.options.camera.lookingAt) {
6479
+ if (isVector3(this.options.camera.lookingAt)) {
6480
+ this.camera.lookAt(this.options.camera.lookingAt);
6481
+ } else if (isTripleArray(this.options.camera.lookingAt)) {
6482
+ this.camera.lookAt(this.options.camera.lookingAt[0], this.options.camera.lookingAt[1], this.options.camera.lookingAt[2]);
6255
6483
  }
6256
- panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
6257
- pan(panDelta.x, panDelta.y);
6258
- panStart.copy(panEnd);
6259
6484
  }
6260
- function handleTouchMoveDolly(event) {
6261
- const position = getSecondPointerPosition(event);
6262
- const dx = event.pageX - position.x;
6263
- const dy = event.pageY - position.y;
6264
- const distance = Math.sqrt(dx * dx + dy * dy);
6265
- dollyEnd.set(0, distance);
6266
- dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed));
6267
- dollyOut(dollyDelta.y);
6268
- dollyStart.copy(dollyEnd);
6485
+ if (this.options.render.autoResize && !this._resizeListener) {
6486
+ this._resizeListener = () => {
6487
+ this.resize(this.viewWidth, this.viewHeight);
6488
+ };
6489
+ window.addEventListener("resize", this._resizeListener);
6269
6490
  }
6270
- function handleTouchMoveDollyPan(event) {
6271
- if (scope.enableZoom) handleTouchMoveDolly(event);
6272
- if (scope.enablePan) handleTouchMovePan(event);
6491
+ }
6492
+ get element() {
6493
+ return this._element;
6494
+ }
6495
+ appendTo(element) {
6496
+ if (this._disposed) return;
6497
+ this._element = element;
6498
+ this._element.appendChild(this.renderer.domElement);
6499
+ if (this.viewWidth == 0) {
6500
+ console.warn("0 element width");
6273
6501
  }
6274
- function handleTouchMoveDollyRotate(event) {
6275
- if (scope.enableZoom) handleTouchMoveDolly(event);
6276
- if (scope.enableRotate) handleTouchMoveRotate(event);
6502
+ if (this.viewHeight == 0) {
6503
+ console.warn("0 element height");
6277
6504
  }
6278
- function handleTouchEnd() {
6505
+ this.resize(this.viewWidth, this.viewHeight);
6506
+ }
6507
+ /**
6508
+ * Redraws when the dispatcher emits the selected event. Registering the same pair twice has no effect.
6509
+ * The renderer removes its listener on disposal; the caller retains ownership of the dispatcher.
6510
+ */
6511
+ registerEventDispatcher(dispatcher, changeEvent2 = "change") {
6512
+ if (this._disposed) return;
6513
+ let events = this._eventDispatchers.get(dispatcher);
6514
+ if (!events) {
6515
+ events = /* @__PURE__ */ new Set();
6516
+ this._eventDispatchers.set(dispatcher, events);
6279
6517
  }
6280
- function onPointerDown(event) {
6281
- if (scope.enabled === false) return;
6282
- if (pointers.length === 0) {
6283
- scope.domElement.setPointerCapture(event.pointerId);
6284
- scope.domElement.addEventListener("pointermove", onPointerMove);
6285
- scope.domElement.addEventListener("pointerup", onPointerUp);
6286
- }
6287
- addPointer(event);
6288
- if (event.pointerType === "touch") {
6289
- onTouchStart(event);
6290
- } else {
6291
- onMouseDown(event);
6292
- }
6518
+ if (events.has(changeEvent2)) return;
6519
+ events.add(changeEvent2);
6520
+ dispatcher.addEventListener(changeEvent2, this._changeListener);
6521
+ }
6522
+ resize(width, height) {
6523
+ if (this._disposed) return;
6524
+ if (isPerspectiveCamera(this.camera)) {
6525
+ this.camera.aspect = width / height;
6526
+ this.camera.updateProjectionMatrix();
6527
+ } else if (isOrthographicCamera(this.camera)) {
6528
+ this.camera.left = width / -2;
6529
+ this.camera.right = width / 2;
6530
+ this.camera.top = height / 2;
6531
+ this.camera.bottom = height / -2;
6532
+ this.camera.updateProjectionMatrix();
6293
6533
  }
6294
- function onPointerMove(event) {
6295
- if (scope.enabled === false) return;
6296
- if (event.pointerType === "touch") {
6297
- onTouchMove(event);
6298
- } else {
6299
- onMouseMove(event);
6300
- }
6534
+ this.renderer.setSize(width, height);
6535
+ this.composer?.setSize(width, height);
6536
+ this._dirty = true;
6537
+ }
6538
+ //<editor-fold desc="RENDER">
6539
+ get dirty() {
6540
+ return this._dirty || this.scene.dirty;
6541
+ }
6542
+ set dirty(dirty) {
6543
+ this._dirty = dirty;
6544
+ this.scene.dirty = dirty;
6545
+ }
6546
+ start() {
6547
+ if (this._disposed) return;
6548
+ this.stop();
6549
+ this.renderer.setAnimationLoop(this._animationLoop);
6550
+ }
6551
+ stop() {
6552
+ if (this._disposed) return;
6553
+ this.renderer.setAnimationLoop(null);
6554
+ this._nextFrameTime = void 0;
6555
+ }
6556
+ /**
6557
+ * Stops rendering and releases owned resources. Repeated calls have no effect, and a disposed
6558
+ * renderer cannot be restarted. Scene objects are detached; shared assets and caller-owned
6559
+ * controls must be managed by their owners.
6560
+ */
6561
+ dispose() {
6562
+ if (this._disposed) return;
6563
+ this.stop();
6564
+ this._disposed = true;
6565
+ if (this._resizeListener) {
6566
+ window.removeEventListener("resize", this._resizeListener);
6567
+ this._resizeListener = void 0;
6568
+ }
6569
+ for (const [dispatcher, events] of this._eventDispatchers) {
6570
+ for (const event of events) {
6571
+ dispatcher.removeEventListener(event, this._changeListener);
6572
+ }
6573
+ }
6574
+ this._eventDispatchers.clear();
6575
+ this._stats?.dom.remove();
6576
+ this._stats = void 0;
6577
+ this.renderer.domElement.remove();
6578
+ this._element = void 0;
6579
+ if (this._controls) {
6580
+ const controls = this._controls;
6581
+ this._controls = void 0;
6582
+ controls.enabled = false;
6583
+ controls.dispose();
6584
+ }
6585
+ this.scene.clear();
6586
+ for (const helper of this._debugHelpers) {
6587
+ helper.geometry.dispose();
6588
+ const materials = Array.isArray(helper.material) ? helper.material : [helper.material];
6589
+ for (const material of materials) {
6590
+ material.dispose();
6591
+ }
6592
+ }
6593
+ this._debugHelpers.length = 0;
6594
+ this.composer?.dispose();
6595
+ this.renderer.dispose();
6596
+ this.renderer.forceContextLoss();
6597
+ }
6598
+ animate(t = performance.now()) {
6599
+ if (this._disposed) return;
6600
+ if (this._controls?.enabled) {
6601
+ this._controls.update();
6602
+ }
6603
+ if (this._disposed) return;
6604
+ if (!this.dirty && !this.options.render.renderAlways) return;
6605
+ const interval = this._frameInterval;
6606
+ if (interval) {
6607
+ const next = this._nextFrameTime;
6608
+ if (next !== void 0 && t + 0.1 < next) return;
6609
+ this._nextFrameTime = next !== void 0 && t - next < interval ? next + interval : t + interval;
6301
6610
  }
6302
- function onPointerUp(event) {
6303
- if (scope.enabled === false) return;
6304
- if (event.pointerType === "touch") {
6305
- onTouchEnd();
6306
- } else {
6307
- onMouseUp(event);
6308
- }
6309
- removePointer(event);
6310
- if (pointers.length === 0) {
6311
- scope.domElement.releasePointerCapture(event.pointerId);
6312
- scope.domElement.removeEventListener("pointermove", onPointerMove);
6313
- scope.domElement.removeEventListener("pointerup", onPointerUp);
6314
- }
6611
+ if (this._stats) {
6612
+ this._stats.begin();
6315
6613
  }
6316
- function onPointerCancel(event) {
6317
- removePointer(event);
6614
+ if (this.options.composer.enabled && this.composer) {
6615
+ this.composer.render();
6616
+ } else {
6617
+ this.renderer.render(this.scene, this.camera);
6318
6618
  }
6319
- function onMouseDown(event) {
6320
- let mouseAction;
6321
- switch (event.button) {
6322
- case 0:
6323
- mouseAction = scope.mouseButtons.LEFT;
6324
- break;
6325
- case 1:
6326
- mouseAction = scope.mouseButtons.MIDDLE;
6327
- break;
6328
- case 2:
6329
- mouseAction = scope.mouseButtons.RIGHT;
6330
- break;
6331
- default:
6332
- mouseAction = -1;
6333
- }
6334
- switch (mouseAction) {
6335
- case import_three20.MOUSE.DOLLY:
6336
- if (scope.enableZoom === false) return;
6337
- handleMouseDownDolly(event);
6338
- state = STATE.DOLLY;
6339
- break;
6340
- case import_three20.MOUSE.ROTATE:
6341
- if (event.ctrlKey || event.metaKey || event.shiftKey) {
6342
- if (scope.enablePan === false) return;
6343
- handleMouseDownPan(event);
6344
- state = STATE.PAN;
6345
- } else {
6346
- if (scope.enableRotate === false) return;
6347
- handleMouseDownRotate(event);
6348
- state = STATE.ROTATE;
6349
- }
6350
- break;
6351
- case import_three20.MOUSE.PAN:
6352
- if (event.ctrlKey || event.metaKey || event.shiftKey) {
6353
- if (scope.enableRotate === false) return;
6354
- handleMouseDownRotate(event);
6355
- state = STATE.ROTATE;
6356
- } else {
6357
- if (scope.enablePan === false) return;
6358
- handleMouseDownPan(event);
6359
- state = STATE.PAN;
6360
- }
6361
- break;
6362
- default:
6363
- state = STATE.NONE;
6619
+ this.dirty = false;
6620
+ if (this._stats) {
6621
+ this._stats.end();
6622
+ }
6623
+ }
6624
+ //</editor-fold>
6625
+ toImage() {
6626
+ return this.renderer.domElement.toDataURL();
6627
+ }
6628
+ ///
6629
+ get attachedToBody() {
6630
+ return this.element === document.body;
6631
+ }
6632
+ get viewWidth() {
6633
+ return this.attachedToBody ? window.innerWidth : this.element?.offsetWidth || 0;
6634
+ }
6635
+ get viewHeight() {
6636
+ return this.attachedToBody ? window.innerHeight : this.element?.offsetHeight || 0;
6637
+ }
6638
+ get scene() {
6639
+ return this._scene;
6640
+ }
6641
+ get camera() {
6642
+ return this._camera;
6643
+ }
6644
+ get renderer() {
6645
+ return this._renderer;
6646
+ }
6647
+ get composer() {
6648
+ return this._composer;
6649
+ }
6650
+ /** Renderer-owned controls, or undefined when disabled at construction or after disposal. */
6651
+ get controls() {
6652
+ return this._controls;
6653
+ }
6654
+ ///
6655
+ };
6656
+
6657
+ // src/skin/Skins.ts
6658
+ var Skins = class {
6659
+ //<editor-fold desc="Skins">
6660
+ static async fromUuidOrUsername(uuidOrUsername) {
6661
+ if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
6662
+ return this.fromUuid(uuidOrUsername);
6663
+ }
6664
+ return this.fromUsername(uuidOrUsername);
6665
+ }
6666
+ static async fromUuid(uuid) {
6667
+ return this.getSkinProxySkinUrl(uuid);
6668
+ }
6669
+ static async fromUsername(username) {
6670
+ return this.usernameToUuid(username).then((uuid) => {
6671
+ if (uuid) {
6672
+ return this.fromUuid(uuid);
6364
6673
  }
6365
- if (state !== STATE.NONE) {
6366
- scope.dispatchEvent(_startEvent);
6674
+ return void 0;
6675
+ });
6676
+ }
6677
+ static async fromMineSkin(mineskinId) {
6678
+ return this.getMineSkin(mineskinId).then((mineskin) => {
6679
+ if (mineskin) {
6680
+ return mineskin["data"]["texture"]["value"]["urls"]["skins"];
6367
6681
  }
6682
+ return void 0;
6683
+ });
6684
+ }
6685
+ //</editor-fold>
6686
+ //<editor-fold desc="Capes">
6687
+ static async capeFromUuidOrUsername(uuidOrUsername) {
6688
+ if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
6689
+ return this.capeFromUuid(uuidOrUsername);
6368
6690
  }
6369
- function onMouseMove(event) {
6370
- if (scope.enabled === false) return;
6371
- switch (state) {
6372
- case STATE.ROTATE:
6373
- if (scope.enableRotate === false) return;
6374
- handleMouseMoveRotate(event);
6375
- break;
6376
- case STATE.DOLLY:
6377
- if (scope.enableZoom === false) return;
6378
- handleMouseMoveDolly(event);
6379
- break;
6380
- case STATE.PAN:
6381
- if (scope.enablePan === false) return;
6382
- handleMouseMovePan(event);
6383
- break;
6691
+ return this.capeFromUsername(uuidOrUsername);
6692
+ }
6693
+ static async capeFromUuid(uuid) {
6694
+ return this.getSkinProxyCapeUrl(uuid);
6695
+ }
6696
+ static async capeFromUsername(username) {
6697
+ return this.usernameToUuid(username).then((uuid) => {
6698
+ if (uuid) {
6699
+ return this.capeFromUuid(uuid);
6384
6700
  }
6385
- }
6386
- function onMouseUp(event) {
6387
- handleMouseUp(event);
6388
- scope.dispatchEvent(_endEvent);
6389
- state = STATE.NONE;
6390
- }
6391
- function onMouseWheel(event) {
6392
- if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE) return;
6393
- event.preventDefault();
6394
- scope.dispatchEvent(_startEvent);
6395
- handleMouseWheel(event);
6396
- scope.dispatchEvent(_endEvent);
6397
- }
6398
- function onKeyDown(event) {
6399
- if (scope.enabled === false || scope.enablePan === false) return;
6400
- handleKeyDown(event);
6401
- }
6402
- function onTouchStart(event) {
6403
- trackPointer(event);
6404
- switch (pointers.length) {
6405
- case 1:
6406
- switch (scope.touches.ONE) {
6407
- case import_three20.TOUCH.ROTATE:
6408
- if (scope.enableRotate === false) return;
6409
- handleTouchStartRotate();
6410
- state = STATE.TOUCH_ROTATE;
6411
- break;
6412
- case import_three20.TOUCH.PAN:
6413
- if (scope.enablePan === false) return;
6414
- handleTouchStartPan();
6415
- state = STATE.TOUCH_PAN;
6416
- break;
6417
- default:
6418
- state = STATE.NONE;
6419
- }
6420
- break;
6421
- case 2:
6422
- switch (scope.touches.TWO) {
6423
- case import_three20.TOUCH.DOLLY_PAN:
6424
- if (scope.enableZoom === false && scope.enablePan === false) return;
6425
- handleTouchStartDollyPan();
6426
- state = STATE.TOUCH_DOLLY_PAN;
6427
- break;
6428
- case import_three20.TOUCH.DOLLY_ROTATE:
6429
- if (scope.enableZoom === false && scope.enableRotate === false) return;
6430
- handleTouchStartDollyRotate();
6431
- state = STATE.TOUCH_DOLLY_ROTATE;
6432
- break;
6433
- default:
6434
- state = STATE.NONE;
6435
- }
6436
- break;
6437
- default:
6438
- state = STATE.NONE;
6701
+ return void 0;
6702
+ });
6703
+ }
6704
+ static async capeFromCapesDev(uuid, capeType = "minecraft") {
6705
+ return this.getCapesDev(uuid, capeType).then((cape) => {
6706
+ if (cape) {
6707
+ return cape?.stillImageUrl;
6439
6708
  }
6440
- if (state !== STATE.NONE) {
6441
- scope.dispatchEvent(_startEvent);
6709
+ return void 0;
6710
+ });
6711
+ }
6712
+ //</editor-fold>
6713
+ //<editor-fold desc="Helpers">
6714
+ static async usernameToUuid(username) {
6715
+ return this.usernameToUuidSkinProxy(username);
6716
+ }
6717
+ static async usernameToUuidSkinProxy(username) {
6718
+ return Requests.genericRequest({
6719
+ baseURL: "https://minecraft-skin-proxy.inventive.workers.dev",
6720
+ url: "/uuid/" + username
6721
+ }).then((res) => {
6722
+ if (res.status === 200) {
6723
+ return res.data["id"];
6442
6724
  }
6443
- }
6444
- function onTouchMove(event) {
6445
- trackPointer(event);
6446
- switch (state) {
6447
- case STATE.TOUCH_ROTATE:
6448
- if (scope.enableRotate === false) return;
6449
- handleTouchMoveRotate(event);
6450
- scope.update();
6451
- break;
6452
- case STATE.TOUCH_PAN:
6453
- if (scope.enablePan === false) return;
6454
- handleTouchMovePan(event);
6455
- scope.update();
6456
- break;
6457
- case STATE.TOUCH_DOLLY_PAN:
6458
- if (scope.enableZoom === false && scope.enablePan === false) return;
6459
- handleTouchMoveDollyPan(event);
6460
- scope.update();
6461
- break;
6462
- case STATE.TOUCH_DOLLY_ROTATE:
6463
- if (scope.enableZoom === false && scope.enableRotate === false) return;
6464
- handleTouchMoveDollyRotate(event);
6465
- scope.update();
6466
- break;
6467
- default:
6468
- state = STATE.NONE;
6725
+ return void 0;
6726
+ }).catch((err) => {
6727
+ console.warn(err);
6728
+ return void 0;
6729
+ });
6730
+ }
6731
+ static async usernameToUuidMineTools(username) {
6732
+ return Requests.genericRequest({
6733
+ baseURL: "https://api.minetools.eu",
6734
+ url: "/uuid/" + username
6735
+ }).then((res) => {
6736
+ if (res.status === 200) {
6737
+ return res.data["id"];
6469
6738
  }
6470
- }
6471
- function onTouchEnd(event) {
6472
- handleTouchEnd(event);
6473
- scope.dispatchEvent(_endEvent);
6474
- state = STATE.NONE;
6475
- }
6476
- function onContextMenu(event) {
6477
- if (scope.enabled === false) return;
6478
- event.preventDefault();
6479
- }
6480
- function addPointer(event) {
6481
- pointers.push(event);
6482
- }
6483
- function removePointer(event) {
6484
- delete pointerPositions[event.pointerId];
6485
- for (let i = 0; i < pointers.length; i++) {
6486
- if (pointers[i].pointerId == event.pointerId) {
6487
- pointers.splice(i, 1);
6488
- return;
6489
- }
6739
+ return void 0;
6740
+ }).catch((err) => {
6741
+ console.warn(err);
6742
+ return void 0;
6743
+ });
6744
+ }
6745
+ static async getProfileFromMinetools(uuid) {
6746
+ return Requests.genericRequest({
6747
+ baseURL: "https://api.minetools.eu",
6748
+ url: "/profile/" + uuid
6749
+ }).then((res) => {
6750
+ if (res.status === 200) {
6751
+ return res.data;
6490
6752
  }
6491
- }
6492
- function trackPointer(event) {
6493
- let position = pointerPositions[event.pointerId];
6494
- if (position === void 0) {
6495
- position = new import_three20.Vector2();
6496
- pointerPositions[event.pointerId] = position;
6753
+ });
6754
+ }
6755
+ static async getMineSkin(mineskinId) {
6756
+ return Requests.genericRequest({
6757
+ baseURL: "https://api.mineskin.org",
6758
+ url: "/get/uuid/" + mineskinId
6759
+ }).then((res) => {
6760
+ if (res.status === 200) {
6761
+ return res.data;
6497
6762
  }
6498
- position.set(event.pageX, event.pageY);
6499
- }
6500
- function getSecondPointerPosition(event) {
6501
- const pointer = event.pointerId === pointers[0].pointerId ? pointers[1] : pointers[0];
6502
- return pointerPositions[pointer.pointerId];
6503
- }
6504
- scope.domElement.addEventListener("contextmenu", onContextMenu);
6505
- scope.domElement.addEventListener("pointerdown", onPointerDown);
6506
- scope.domElement.addEventListener("pointercancel", onPointerCancel);
6507
- scope.domElement.addEventListener("wheel", onMouseWheel, { passive: false });
6508
- this.update();
6763
+ return void 0;
6764
+ }).catch((err) => {
6765
+ console.warn(err);
6766
+ return void 0;
6767
+ });
6509
6768
  }
6510
- };
6511
- var MapControls = class extends OrbitControls {
6512
- constructor(object, domElement) {
6513
- super(object, domElement);
6514
- this.screenSpacePanning = false;
6515
- this.mouseButtons.LEFT = import_three20.MOUSE.PAN;
6516
- this.mouseButtons.RIGHT = import_three20.MOUSE.ROTATE;
6517
- this.touches.ONE = import_three20.TOUCH.PAN;
6518
- this.touches.TWO = import_three20.TOUCH.DOLLY_ROTATE;
6769
+ static async getCapesDev(uuid, type = "all") {
6770
+ return Requests.genericRequest({
6771
+ baseURL: "https://api.capes.dev",
6772
+ url: "/load/" + uuid + "/" + type
6773
+ }).then((res) => {
6774
+ if (res.status === 200) {
6775
+ return res.data;
6776
+ }
6777
+ return void 0;
6778
+ }).catch((err) => {
6779
+ console.warn(err);
6780
+ return void 0;
6781
+ });
6782
+ }
6783
+ static getCrafatarSkinUrl(uuid) {
6784
+ return "https://crafatar.com/skins/" + uuid;
6519
6785
  }
6786
+ static getCrafatarCapeUrl(uuid) {
6787
+ return "https://crafatar.com/capes/" + uuid;
6788
+ }
6789
+ static getMcHeadsSkinUrl(uuid) {
6790
+ return "https://mc-heads.net/skin/" + uuid;
6791
+ }
6792
+ static getMineSkinPlayerSkinUrl(uuid) {
6793
+ return "https://mineskin.org/skin/player/" + uuid;
6794
+ }
6795
+ static getSkinProxySkinUrl(uuid) {
6796
+ return "https://minecraft-skin-proxy.inventive.workers.dev/skin/" + uuid;
6797
+ }
6798
+ static getSkinProxyCapeUrl(uuid) {
6799
+ return "https://minecraft-skin-proxy.inventive.workers.dev/cape/" + uuid;
6800
+ }
6801
+ //</editor-fold>
6520
6802
  };
6521
6803
 
6522
6804
  // src/world/Chunk.ts
@@ -6579,7 +6861,7 @@ var MineRenderWorld = class {
6579
6861
  console.log("CHUNKS", this._chunks);
6580
6862
  for (let chunk of this._chunks.values()) {
6581
6863
  console.log("dispose chunk", chunk);
6582
- await (chunk == null ? void 0 : chunk.dispose());
6864
+ await chunk?.dispose();
6583
6865
  }
6584
6866
  this._chunks.clear();
6585
6867
  }
@@ -6633,7 +6915,7 @@ var MineRenderWorld = class {
6633
6915
  };
6634
6916
 
6635
6917
  // src/world/Chunk.ts
6636
- var p12 = prefix("Chunk");
6918
+ var p11 = prefix("Chunk");
6637
6919
  var Chunk = class _Chunk {
6638
6920
  constructor(scene, x, y, z) {
6639
6921
  this._blocks = [];
@@ -6685,7 +6967,7 @@ var Chunk = class _Chunk {
6685
6967
  const index = _Chunk.chunkPosToBlockIndex(pos);
6686
6968
  const current = this._blocks[index];
6687
6969
  if (typeof current !== "undefined") {
6688
- console.debug(p12, "deleting existing block at", pos, worldPos, index);
6970
+ console.debug(p11, "deleting existing block at", pos, worldPos, index);
6689
6971
  current.object.removeFromScene();
6690
6972
  delete this._blocks[index];
6691
6973
  }
@@ -6752,6 +7034,7 @@ var Chunk = class _Chunk {
6752
7034
  AXES,
6753
7035
  ArchiveAssetSource,
6754
7036
  AssetKey,
7037
+ AssetLoadError,
6755
7038
  AssetLoader,
6756
7039
  AssetParser,
6757
7040
  AssetSource,
@@ -6809,6 +7092,7 @@ var Chunk = class _Chunk {
6809
7092
  OrbitControls,
6810
7093
  PersistentCache,
6811
7094
  Renderer,
7095
+ RequestError,
6812
7096
  Requests,
6813
7097
  SKIN_PARTS,
6814
7098
  SceneInspector,