minerender 2.1.0-alpha.1 → 2.1.0-alpha.10

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({
@@ -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
 
@@ -192,6 +184,7 @@ __export(index_node_exports, {
192
184
  OrbitControls: () => OrbitControls,
193
185
  PersistentCache: () => PersistentCache,
194
186
  Renderer: () => Renderer,
187
+ RequestError: () => RequestError,
195
188
  Requests: () => Requests,
196
189
  SKIN_PARTS: () => SKIN_PARTS,
197
190
  SceneInspector: () => SceneInspector,
@@ -302,25 +295,29 @@ var Env = class {
302
295
  };
303
296
 
304
297
  // src/cache/PersistentCache.ts
305
- var _PersistentCache = class _PersistentCache {
298
+ var PersistentCache = class _PersistentCache {
306
299
  constructor(backing) {
307
300
  this.backing = backing;
308
301
  }
302
+ static {
303
+ /** Bump to invalidate every persisted entry. */
304
+ this.VERSION = 2;
305
+ }
309
306
  static open(name) {
310
307
  return Env.provider.openCache(name, _PersistentCache.VERSION);
311
308
  }
309
+ /** Loads a missing entry and stores only non-nullish results. */
312
310
  async getOrLoad(key, loader) {
313
311
  let v = await this.get(key);
314
312
  if (typeof v === "undefined" || v === null) {
315
313
  v = await loader(key);
316
- await this.put(key, v);
314
+ if (typeof v !== "undefined" && v !== null) {
315
+ await this.put(key, v);
316
+ }
317
317
  }
318
318
  return v;
319
319
  }
320
320
  };
321
- /** Bump to invalidate every persisted entry. */
322
- _PersistentCache.VERSION = 1;
323
- var PersistentCache = _PersistentCache;
324
321
 
325
322
  // src/env/node/NodeCache.ts
326
323
  var NodeCache = class extends PersistentCache {
@@ -494,8 +491,7 @@ function serializeImageKey(key) {
494
491
  return md5(key.src);
495
492
  }
496
493
  function serializeBoxGeometryKey(key) {
497
- var _a;
498
- return md5([key.width, key.height, key.depth, (_a = key.uv) == null ? void 0 : _a.join(":")].join("_"));
494
+ return md5([key.width, key.height, key.depth, key.uv?.join(":")].join("_"));
499
495
  }
500
496
  function serializeTextureKey(key) {
501
497
  return md5([key.src, key.format, key.rotation].join("$"));
@@ -510,7 +506,61 @@ function serializeMeshKey(key) {
510
506
  // src/cache/Caching.ts
511
507
  var import_loading_cache = require("@inventivetalent/loading-cache");
512
508
  var import_time = require("@inventivetalent/time");
513
- var Caching = class {
509
+ var Caching = class _Caching {
510
+ static {
511
+ 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();
512
+ }
513
+ static {
514
+ 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();
515
+ }
516
+ static {
517
+ 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();
518
+ }
519
+ static {
520
+ 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();
521
+ }
522
+ static {
523
+ 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();
524
+ }
525
+ static {
526
+ 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();
527
+ }
528
+ static {
529
+ 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();
530
+ }
531
+ static {
532
+ 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();
533
+ }
534
+ static {
535
+ 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();
536
+ }
537
+ static {
538
+ 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();
539
+ }
540
+ static {
541
+ 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();
542
+ }
543
+ static {
544
+ 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();
545
+ }
546
+ static {
547
+ 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();
548
+ }
549
+ static {
550
+ 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();
551
+ }
552
+ static {
553
+ this.listAssetCache = _Caching.createAssetCache();
554
+ }
555
+ static {
556
+ this.defaultBlockStatesCache = _Caching.createAssetCache();
557
+ }
558
+ static {
559
+ this.entityModelsCache = _Caching.createAssetCache();
560
+ }
561
+ static createAssetCache() {
562
+ 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();
563
+ }
514
564
  /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */
515
565
  static get all() {
516
566
  return [
@@ -527,7 +577,10 @@ var Caching = class {
527
577
  this.rawModelCache,
528
578
  this.mergedModelCache,
529
579
  this.modelTextureAtlasCache,
530
- this.blockStateCache
580
+ this.blockStateCache,
581
+ this.listAssetCache,
582
+ this.defaultBlockStatesCache,
583
+ this.entityModelsCache
531
584
  ];
532
585
  }
533
586
  static clear() {
@@ -538,8 +591,8 @@ var Caching = class {
538
591
  /**
539
592
  * Clears every cache and stops its expiry timer.
540
593
  *
541
- * loading-cache reschedules that timer indefinitely, so a Node process will not exit until
542
- * this is called - see {@link shutdown}.
594
+ * Expiry timers are unref'd in Node, so idle processes can exit without this cleanup.
595
+ * Use {@link shutdown} to also stop requests and the shared Ticker.
543
596
  */
544
597
  static end() {
545
598
  for (const cache of this.all) {
@@ -553,20 +606,6 @@ var Caching = class {
553
606
  };
554
607
  }
555
608
  };
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
609
 
571
610
  // src/Geometries.ts
572
611
  var Geometries = class _Geometries {
@@ -587,13 +626,14 @@ var Geometries = class _Geometries {
587
626
  };
588
627
 
589
628
  // src/Materials.ts
590
- var import_three6 = require("three");
629
+ var import_three5 = require("three");
591
630
 
592
631
  // src/texture/Textures.ts
593
- var import_three5 = require("three");
632
+ var import_three4 = require("three");
594
633
 
595
634
  // src/texture/TextureLoader.ts
596
- var import_three4 = require("three");
635
+ var import_three3 = require("three");
636
+ var THREE = __toESM(require("three"));
597
637
 
598
638
  // src/canvas/CanvasCompat.ts
599
639
  function createImage(width, height) {
@@ -604,9 +644,7 @@ function createCanvas2(width, height) {
604
644
  }
605
645
 
606
646
  // src/request/Requests.ts
607
- var import_axios = __toESM(require("axios"));
608
647
  var import_jobqu = require("jobqu");
609
- var import_time2 = require("@inventivetalent/time");
610
648
 
611
649
  // src/util/log.ts
612
650
  var Reset = "\x1B[0m";
@@ -616,198 +654,174 @@ function prefix(prefix2) {
616
654
  return `${FgGreen}MR${BgBlack}${prefix2 ?? ""}${Reset}`;
617
655
  }
618
656
 
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();
657
+ // src/request/Requests.ts
658
+ var p = prefix("Requests");
659
+ var RequestError = class extends Error {
660
+ constructor(message, response, cause) {
661
+ super(message);
662
+ this.response = response;
663
+ this.cause = cause;
664
+ this.name = "RequestError";
638
665
  }
639
666
  };
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);
667
+ async function fetchRequest(config, defaultBaseURL) {
668
+ const { url, baseURL = defaultBaseURL, timeout = 5e3, responseType = "json", signal, ...options } = config;
669
+ const target = baseURL && !/^([a-z][a-z\d+.-]*:|\/\/)/i.test(url) ? `${baseURL.replace(/\/+$/, "")}/${url.replace(/^\/+/, "")}` : url;
670
+ const headers = new Headers(options.headers);
671
+ if (typeof window === "undefined" && !headers.has("User-Agent")) {
672
+ headers.set("User-Agent", "MineRender");
673
+ }
674
+ const attemptSignal = AbortSignal.any([
675
+ ...signal ? [signal] : [],
676
+ ...timeout === 0 ? [] : [AbortSignal.timeout(timeout)]
677
+ ]);
678
+ const request = new Request(target, { ...options, headers, signal: attemptSignal });
679
+ attemptSignal.throwIfAborted();
680
+ try {
681
+ const response = await fetch(request);
682
+ const result = {
683
+ data: void 0,
684
+ status: response.status,
685
+ statusText: response.statusText,
686
+ headers: response.headers,
687
+ url: response.url
688
+ };
689
+ if (!response.ok) {
690
+ await response.body?.cancel().catch(() => {
691
+ });
692
+ throw new RequestError(`Request failed with status ${response.status}`, result);
693
+ }
694
+ const emptyBody = request.method === "HEAD" || response.status === 204 || response.status === 205;
695
+ const data = responseType === "arraybuffer" ? await response.arrayBuffer() : emptyBody || response.body === null ? void 0 : await response.json();
696
+ return { ...result, data };
697
+ } catch (error) {
698
+ attemptSignal.throwIfAborted();
699
+ if (/^https?:/.test(request.url) && request.redirect !== "error" && error instanceof TypeError) {
700
+ throw new RequestError("Network request failed", void 0, error);
664
701
  }
702
+ throw error;
665
703
  }
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
704
  }
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;
705
+ async function abortable(promise, signal) {
706
+ if (!signal) return promise;
707
+ let abort;
708
+ const cancelled = new Promise((_, reject) => {
709
+ abort = () => reject(signal.reason);
710
+ signal.addEventListener("abort", abort, { once: true });
711
+ if (signal.aborted) abort();
712
+ });
713
+ try {
714
+ return await Promise.race([promise, cancelled]);
715
+ } finally {
716
+ signal.removeEventListener("abort", abort);
687
717
  }
688
718
  }
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
- });
719
+ var RequestQueue = class {
720
+ constructor() {
721
+ this.pendingRequests = 0;
722
+ this.stopped = new AbortController();
723
+ this.queue = new import_jobqu.JobQueue(
724
+ (request) => fetchRequest(request, this.baseURL),
725
+ { interval: 10, maxPerRun: 1, maxActive: 8 }
726
+ );
767
727
  }
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;
728
+ async request(request) {
729
+ this.pendingRequests++;
730
+ const signal = request.signal;
731
+ try {
732
+ for (let retries = 0; ; retries++) {
733
+ signal?.throwIfAborted();
734
+ try {
735
+ return await abortable(this.queue.add(request), signal);
736
+ } catch (error) {
737
+ console.debug(p, "Request failed", error);
738
+ const delay = this.retryDelay(error, request, retries);
739
+ if (delay === void 0) {
740
+ throw error;
775
741
  }
776
- } else {
777
- request["minerenderRetry"] = 3;
778
- return true;
742
+ await this.waitForRetry(delay, signal);
779
743
  }
780
744
  }
745
+ } finally {
746
+ if (signal?.aborted) {
747
+ this.queue.remove(request);
748
+ }
749
+ this.pendingRequests--;
781
750
  }
782
- return false;
751
+ }
752
+ retryDelay(error, request, retries) {
753
+ if (this.stopped.signal.aborted || retries >= 3 || (request.method ?? "get").toLowerCase() !== "get" || request.signal?.aborted) {
754
+ return void 0;
755
+ }
756
+ if (error instanceof RequestError) {
757
+ const status = error.response?.status;
758
+ if (status !== void 0 && status !== 408 && status !== 429 && !(status >= 500 && status < 600)) return void 0;
759
+ } else if (!(error instanceof DOMException && error.name === "TimeoutError")) {
760
+ return void 0;
761
+ }
762
+ let delay = 100 * 2 ** retries;
763
+ const retryAfter = error instanceof RequestError ? error.response?.headers.get("Retry-After") : void 0;
764
+ if (retryAfter !== void 0 && retryAfter !== null) {
765
+ const seconds = Number(retryAfter);
766
+ if (!retryAfter.trim() || !Number.isFinite(seconds) || seconds < 0) {
767
+ return void 0;
768
+ }
769
+ delay = Math.max(delay, seconds * 1e3);
770
+ }
771
+ return delay;
772
+ }
773
+ async waitForRetry(delay, signal) {
774
+ let timer;
775
+ const waiting = new Promise((resolve) => {
776
+ timer = setTimeout(resolve, delay);
777
+ });
778
+ try {
779
+ await abortable(waiting, AbortSignal.any([this.stopped.signal, ...signal ? [signal] : []]));
780
+ } finally {
781
+ clearTimeout(timer);
782
+ }
783
+ }
784
+ get pendingSize() {
785
+ return this.pendingRequests;
786
+ }
787
+ end() {
788
+ this.queue.end();
789
+ this.stopped.abort(new import_jobqu.JobCancelledError("ended"));
790
+ }
791
+ };
792
+ var Requests = class {
793
+ static {
794
+ this.genericQueue = new RequestQueue();
795
+ }
796
+ static {
797
+ this.mcAssetRequestQueue = new RequestQueue();
798
+ }
799
+ static genericRequest(request) {
800
+ return this.genericQueue.request(request);
801
+ }
802
+ static mcAssetRequest(request) {
803
+ return this.mcAssetRequestQueue.request(request);
783
804
  }
784
805
  static setMcAssetRoot(root) {
785
- this.mcAssetInstance.defaults.baseURL = root;
806
+ this.mcAssetRequestQueue.baseURL = root;
786
807
  }
808
+ /** Counts unsettled calls, including retry delays and requests still running after shutdown. */
787
809
  static get queueSizes() {
788
810
  return {
789
- generic: this.genericQueue.size,
790
- mcAsset: this.mcAssetRequestQueue.size
811
+ generic: this.genericQueue.pendingSize,
812
+ mcAsset: this.mcAssetRequestQueue.pendingSize
791
813
  };
792
814
  }
793
815
  /**
794
- * Stops both queue timers. jobqu reschedules itself indefinitely, so a Node process will not
795
- * exit until this is called - see {@link shutdown}.
816
+ * Permanently stops both queues and rejects waiting, retrying, and future requests.
817
+ * Requests already running can finish. Idle queues hold no timer, so Node can exit without
818
+ * this cleanup. See {@link shutdown}.
796
819
  */
797
820
  static end() {
798
821
  this.genericQueue.end();
799
822
  this.mcAssetRequestQueue.end();
800
823
  }
801
824
  };
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
825
 
812
826
  // src/WrappedImage.ts
813
827
  var WrappedImage = class {
@@ -872,29 +886,41 @@ var ImageLoader = class _ImageLoader {
872
886
  static async loadAsync(src) {
873
887
  return new Promise((resolve, reject) => {
874
888
  const image = this._createImage();
875
- image.src = src;
876
889
  image.onload = () => resolve(image);
877
- image.onerror = (err) => reject(err);
890
+ image.onerror = (err) => reject(err instanceof Error ? err : new Error("Failed to decode image"));
891
+ image.src = src;
878
892
  });
879
893
  }
880
894
  static loadElement(src, onload, onerr) {
881
895
  const image = this._createImage();
882
- image.src = src;
883
896
  if (onload)
884
897
  image.onload = onload;
885
898
  if (onerr)
886
899
  image.onerror = onerr;
900
+ image.src = src;
887
901
  return image;
888
902
  }
889
903
  static async loadData(src) {
890
904
  console.debug(p2, "loadData", src);
891
- return await this.infoToData(await this.getInfo(src));
905
+ const image = await this.loadCanvasData(src);
906
+ return image.data.getImageData(0, 0, image.width, image.height);
892
907
  }
893
908
  static async loadCanvasData(src) {
894
- return await this.infoToCanvasData(await this.getInfo(src));
909
+ const keyStr = serializeImageKey({ src });
910
+ const info = this.getInfo(src);
911
+ const cached = Caching.rawImageCache.getIfPresent(keyStr);
912
+ try {
913
+ return await this.infoToCanvasData(await info);
914
+ } catch (err) {
915
+ if (cached && Caching.rawImageCache.getIfPresent(keyStr) === cached) {
916
+ Caching.rawImageCache.invalidate(keyStr);
917
+ }
918
+ throw err;
919
+ }
895
920
  }
896
921
  static async infoToCanvasData(info) {
897
- const image = await _ImageLoader.loadAsync(info.src);
922
+ const type = info.type === "jpg" ? "jpeg" : info.type ?? "png";
923
+ const image = await _ImageLoader.loadAsync(`data:image/${type};base64,${info.data.toString("base64")}`);
898
924
  const canvas = createCanvas2(info.width, info.height);
899
925
  const context = canvas.getContext("2d");
900
926
  context.drawImage(image, 0, 0);
@@ -905,11 +931,8 @@ var ImageLoader = class _ImageLoader {
905
931
  };
906
932
  }
907
933
  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);
934
+ const image = await this.infoToCanvasData(info);
935
+ return image.data.getImageData(0, 0, image.width, image.height);
913
936
  }
914
937
  static async getData(src) {
915
938
  const keyStr = serializeImageKey({ src });
@@ -924,38 +947,25 @@ var ImageLoader = class _ImageLoader {
924
947
  });
925
948
  }
926
949
  static async processResponse(response) {
927
- const src = response.config.url;
950
+ const src = response.url;
928
951
  const data = import_buffer.Buffer.from(response.data);
929
952
  const { width, height, type } = Env.provider.imageSize(data);
953
+ if (!width || !height) {
954
+ throw new Error("Invalid or unsupported image dimensions");
955
+ }
930
956
  return {
931
957
  src,
932
- width: width || 0,
933
- height: height || 0,
958
+ width,
959
+ height,
934
960
  type,
935
961
  data
936
962
  };
937
963
  }
938
964
  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
965
  return Requests.genericRequest({
948
966
  url: src,
949
967
  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
- });
968
+ }).then(this.processResponse);
959
969
  }
960
970
  static async getInfo(src) {
961
971
  const keyStr = serializeImageKey({ src });
@@ -977,25 +987,39 @@ var ImageLoader = class _ImageLoader {
977
987
 
978
988
  // src/texture/TextureLoader.ts
979
989
  var TextureLoader = class {
990
+ static {
991
+ this.failedTextures = /* @__PURE__ */ new WeakSet();
992
+ }
993
+ /** Reports whether image loading failed, so cached textures can be retried. */
994
+ static hasFailed(texture) {
995
+ return this.failedTextures.has(texture);
996
+ }
980
997
  static createTexture() {
981
- return new import_three4.Texture();
998
+ return new import_three3.Texture();
982
999
  }
983
- static loadInBackground(src, format = import_three4.RGBAFormat, rotation = 0) {
1000
+ static loadInBackground(src, format = import_three3.RGBAFormat, rotation = 0) {
984
1001
  const texture = this.createTexture();
985
- const image = ImageLoader.loadElement(src);
986
- image.onload = function() {
1002
+ texture.colorSpace = THREE.SRGBColorSpace;
1003
+ const image = ImageLoader.loadElement(src, () => {
987
1004
  texture.needsUpdate = true;
988
- };
1005
+ }, (error) => {
1006
+ this.failedTextures.add(texture);
1007
+ console.warn("Failed to load texture", src, error);
1008
+ });
989
1009
  texture.image = image;
990
1010
  texture.format = format;
991
1011
  texture.rotation = rotation;
992
1012
  return Textures.initTextureProps(texture);
993
1013
  }
994
- static load(src, format = import_three4.RGBAFormat, rotation = 0) {
995
- const texture = new import_three4.Texture();
1014
+ static load(src, format = import_three3.RGBAFormat, rotation = 0) {
1015
+ const texture = new import_three3.Texture();
1016
+ texture.colorSpace = THREE.SRGBColorSpace;
996
1017
  ImageLoader.getData(src).then((image) => {
997
- texture.needsUpdate = true;
998
1018
  texture.image = image;
1019
+ texture.needsUpdate = true;
1020
+ }).catch((error) => {
1021
+ this.failedTextures.add(texture);
1022
+ console.warn("Failed to load texture", src, error);
999
1023
  });
1000
1024
  texture.format = format;
1001
1025
  texture.rotation = rotation;
@@ -1004,11 +1028,11 @@ var TextureLoader = class {
1004
1028
  };
1005
1029
 
1006
1030
  // src/texture/Textures.ts
1007
- var THREE = __toESM(require("three"));
1031
+ var THREE2 = __toESM(require("three"));
1008
1032
  var Textures = class _Textures {
1009
1033
  static initTextureProps(texture) {
1010
- texture.magFilter = THREE.NearestFilter;
1011
- texture.minFilter = THREE.NearestFilter;
1034
+ texture.magFilter = THREE2.NearestFilter;
1035
+ texture.minFilter = THREE2.NearestFilter;
1012
1036
  texture.anisotropy = 0;
1013
1037
  return texture;
1014
1038
  }
@@ -1016,13 +1040,19 @@ var Textures = class _Textures {
1016
1040
  return TextureLoader.load(key.src, key.format, key.rotation);
1017
1041
  }
1018
1042
  static createAsset(key) {
1019
- return new import_three5.Texture();
1043
+ return new import_three4.Texture();
1020
1044
  }
1021
1045
  static createCanvasTexture(canvas) {
1022
- return this.initTextureProps(new import_three5.CanvasTexture(canvas));
1046
+ const texture = new import_three4.CanvasTexture(canvas);
1047
+ texture.colorSpace = THREE2.SRGBColorSpace;
1048
+ return this.initTextureProps(texture);
1023
1049
  }
1024
1050
  static getImage(key) {
1025
1051
  const keyStr = serializeTextureKey(key);
1052
+ const cached = Caching.textureCache.peek(keyStr);
1053
+ if (cached && TextureLoader.hasFailed(cached)) {
1054
+ Caching.textureCache.invalidate(keyStr);
1055
+ }
1026
1056
  return Caching.textureCache.get(keyStr, (k) => {
1027
1057
  return _Textures.createImage(key);
1028
1058
  });
@@ -1030,7 +1060,10 @@ var Textures = class _Textures {
1030
1060
  };
1031
1061
 
1032
1062
  // src/Materials.ts
1033
- var _Materials = class _Materials {
1063
+ var Materials = class _Materials {
1064
+ static {
1065
+ this.MISSING_TEXTURE_SRC = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX/AP8AAACfphTyAAAAFUlEQVQoz2MIhQKGVVAwKjIqQrwIAHRz/wFI17TEAAAAAElFTkSuQmCC";
1066
+ }
1034
1067
  // resolved lazily: as a static field this decoded an image the moment the library was
1035
1068
  // imported, which needs both a DOM and an EnvProvider to already be in place
1036
1069
  static get MISSING_TEXTURE() {
@@ -1038,26 +1071,26 @@ var _Materials = class _Materials {
1038
1071
  }
1039
1072
  static createImage(key) {
1040
1073
  const transparent = key.transparent || false;
1041
- return new import_three6.MeshBasicMaterial({
1074
+ return new import_three5.MeshBasicMaterial({
1042
1075
  map: Textures.getImage(key.texture),
1043
1076
  transparent,
1044
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1077
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1045
1078
  alphaTest: 0.5
1046
1079
  });
1047
1080
  }
1048
1081
  static createBasicCanvasMaterial(canvas, transparent = false, shade = false) {
1049
1082
  if (shade) {
1050
- return new import_three6.MeshStandardMaterial({
1083
+ return new import_three5.MeshStandardMaterial({
1051
1084
  map: Textures.createCanvasTexture(canvas),
1052
1085
  transparent,
1053
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1086
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1054
1087
  alphaTest: 0.5
1055
1088
  });
1056
1089
  }
1057
- return new import_three6.MeshBasicMaterial({
1090
+ return new import_three5.MeshBasicMaterial({
1058
1091
  map: Textures.createCanvasTexture(canvas),
1059
1092
  transparent,
1060
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1093
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1061
1094
  alphaTest: 0.5
1062
1095
  });
1063
1096
  }
@@ -1136,16 +1169,19 @@ var _Materials = class _Materials {
1136
1169
  gl_FragColor = vec4(lift + color.rgb * light2, 1.0);
1137
1170
 
1138
1171
  }
1172
+
1173
+ #include <tonemapping_fragment>
1174
+ #include <colorspace_fragment>
1139
1175
  }
1140
1176
  `;
1141
1177
  try {
1142
- return new import_three6.ShaderMaterial({
1178
+ return new import_three5.ShaderMaterial({
1143
1179
  uniforms: {
1144
1180
  SHADE: { value: true },
1145
1181
  BRIGHTNESS: { value: 1 },
1146
1182
  EMISSIVE: { value: false },
1147
1183
  base: {
1148
- value: new import_three6.Color(12698049)
1184
+ value: new import_three5.Color(12698049)
1149
1185
  /*TODO*/
1150
1186
  },
1151
1187
  map: { value: Textures.createCanvasTexture(canvas) }
@@ -1154,7 +1190,7 @@ var _Materials = class _Materials {
1154
1190
  fragmentShader: fragShader,
1155
1191
  vertexColors: true,
1156
1192
  transparent,
1157
- side: transparent ? import_three6.DoubleSide : import_three6.FrontSide,
1193
+ side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
1158
1194
  alphaTest: 0.5
1159
1195
  });
1160
1196
  } catch (e) {
@@ -1164,6 +1200,10 @@ var _Materials = class _Materials {
1164
1200
  }
1165
1201
  static getImage(key) {
1166
1202
  const keyStr = serializeMaterialKey(key);
1203
+ const map = Caching.materialCache.peek(keyStr)?.map;
1204
+ if (map && TextureLoader.hasFailed(map)) {
1205
+ Caching.materialCache.invalidate(keyStr);
1206
+ }
1167
1207
  return Caching.materialCache.get(keyStr, (k) => {
1168
1208
  return _Materials.createImage(key);
1169
1209
  });
@@ -1184,14 +1224,12 @@ var _Materials = class _Materials {
1184
1224
  }
1185
1225
  }
1186
1226
  };
1187
- _Materials.MISSING_TEXTURE_SRC = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABAAQMAAACQp+OdAAAABlBMVEX/AP8AAACfphTyAAAAFUlEQVQoz2MIhQKGVVAwKjIqQrwIAHRz/wFI17TEAAAAAElFTkSuQmCC";
1188
- var Materials = _Materials;
1189
1227
 
1190
1228
  // src/Meshes.ts
1191
- var import_three7 = require("three");
1229
+ var import_three6 = require("three");
1192
1230
  var Meshes = class _Meshes {
1193
1231
  static createBox(key) {
1194
- return new import_three7.Mesh(Geometries.getBox(key.geometry), Materials.getImage(key.material));
1232
+ return new import_three6.Mesh(Geometries.getBox(key.geometry), Materials.getImage(key.material));
1195
1233
  }
1196
1234
  static getBox(key) {
1197
1235
  const keyStr = serializeMeshKey(key);
@@ -1240,7 +1278,7 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1240
1278
  this.root = root;
1241
1279
  }
1242
1280
  static parse(assetType, str, origin) {
1243
- let namespace = (origin == null ? void 0 : origin.namespace) || DEFAULT_NAMESPACE;
1281
+ let namespace = origin?.namespace || DEFAULT_NAMESPACE;
1244
1282
  if (str.includes(":")) {
1245
1283
  let split2 = str.split(":");
1246
1284
  namespace = split2[0];
@@ -1253,8 +1291,8 @@ var AssetKey = class _AssetKey extends BasicAssetKey {
1253
1291
  split.shift();
1254
1292
  }
1255
1293
  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);
1294
+ let extension = assetType === "textures" ? ".png" : origin?.assetType || ".json";
1295
+ return new _AssetKey(namespace, path, assetType, type, "assets", extension, origin?.root);
1258
1296
  }
1259
1297
  toString() {
1260
1298
  let a = [
@@ -1317,9 +1355,6 @@ var ModelMerger = class {
1317
1355
  }
1318
1356
  };
1319
1357
 
1320
- // src/assets/Models.ts
1321
- var import_typescript_memoize = require("typescript-memoize");
1322
-
1323
1358
  // src/assets/source/parser/AssetParsers.ts
1324
1359
  var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1325
1360
  AssetParser2["MODEL"] = "model";
@@ -1333,14 +1368,14 @@ var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1333
1368
  })(AssetParser || {});
1334
1369
 
1335
1370
  // src/assets/Models.ts
1336
- var _Models = class _Models {
1371
+ var Models = class _Models {
1337
1372
  // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading
1338
1373
  // the library, and would require an EnvProvider before any entry has had a chance to register
1339
1374
  static get PERSISTENT_CACHE() {
1340
1375
  return this._persistentCache ??= PersistentCache.open("minerender-models");
1341
1376
  }
1342
1377
  static async getItemList() {
1343
- return AssetLoader.get(new AssetKey(
1378
+ const key = new AssetKey(
1344
1379
  DEFAULT_NAMESPACE,
1345
1380
  "_list",
1346
1381
  "models",
@@ -1348,7 +1383,10 @@ var _Models = class _Models {
1348
1383
  "assets",
1349
1384
  ".json",
1350
1385
  DEFAULT_ROOT
1351
- ), "list" /* LIST */).then((r) => (r == null ? void 0 : r.files) ?? []);
1386
+ );
1387
+ return Caching.listAssetCache.get(key.serialize(), () => {
1388
+ return AssetLoader.get(key, "list" /* LIST */);
1389
+ }).then((r) => r?.files ?? []);
1352
1390
  }
1353
1391
  static async loadAndMerge(key) {
1354
1392
  const model = await this.getRaw(key);
@@ -1395,19 +1433,15 @@ var _Models = class _Models {
1395
1433
  return this.PERSISTENT_CACHE.clear();
1396
1434
  }
1397
1435
  };
1398
- __decorateClass([
1399
- (0, import_typescript_memoize.Memoize)()
1400
- ], _Models, "getItemList", 1);
1401
- var Models = _Models;
1402
1436
 
1403
1437
  // src/assets/BlockStates.ts
1404
- var import_typescript_memoize2 = require("typescript-memoize");
1405
1438
  var BlockStates = class {
1406
1439
  static get PERSISTENT_CACHE() {
1407
1440
  return this._persistentCache ??= PersistentCache.open("minerender-blockstates");
1408
1441
  }
1442
+ // BlockState names are hardcoded
1409
1443
  static async getList() {
1410
- return AssetLoader.get(new AssetKey(
1444
+ const key = new AssetKey(
1411
1445
  DEFAULT_NAMESPACE,
1412
1446
  "_list",
1413
1447
  "blockstates",
@@ -1415,11 +1449,16 @@ var BlockStates = class {
1415
1449
  "assets",
1416
1450
  ".json",
1417
1451
  DEFAULT_ROOT
1418
- ), "list" /* LIST */).then((r) => (r == null ? void 0 : r.files) ?? []);
1452
+ );
1453
+ return Caching.listAssetCache.get(key.serialize(), () => {
1454
+ return AssetLoader.get(key, "list" /* LIST */);
1455
+ }).then((r) => r?.files ?? []);
1419
1456
  }
1420
1457
  static async getDefaultStates() {
1421
1458
  const key = AssetKey.parse("blockstates", "minerender:defaultBlockStates");
1422
- return AssetLoader.get(key, "json" /* JSON */);
1459
+ return Caching.defaultBlockStatesCache.get(key.serialize(), () => {
1460
+ return AssetLoader.get(key, "json" /* JSON */);
1461
+ });
1423
1462
  }
1424
1463
  static async getDefaultState(key) {
1425
1464
  const defaultStates = await this.getDefaultStates();
@@ -1458,12 +1497,6 @@ var BlockStates = class {
1458
1497
  await this.PERSISTENT_CACHE.clear();
1459
1498
  }
1460
1499
  };
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
1500
  var DefaultBlockStates = class {
1468
1501
  };
1469
1502
 
@@ -1491,32 +1524,235 @@ var AssetSource = class {
1491
1524
  }
1492
1525
  };
1493
1526
 
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
+ // src/util/BatchedExecutor.ts
1528
+ var BatchedExecutor = class {
1529
+ constructor(interval = 1, batch = 30) {
1530
+ this.interval = interval;
1531
+ this.batch = batch;
1532
+ this.queue = [];
1533
+ this.task = setInterval(() => this.run());
1534
+ }
1535
+ submit(task) {
1536
+ this.queue.push(task);
1537
+ }
1538
+ run() {
1539
+ for (let i = 0; i < this.batch; i++) {
1540
+ this.runNext();
1541
+ }
1542
+ }
1543
+ runNext() {
1544
+ let next = this.queue.shift();
1545
+ if (next) next();
1500
1546
  }
1501
1547
  };
1502
1548
 
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;
1514
- }
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") {
1549
+ // src/util/model.ts
1550
+ var import_three7 = require("three");
1551
+ function applyElementRotation(rotation, geometry) {
1552
+ const origin = new import_three7.Vector3(rotation.origin[0], rotation.origin[1], rotation.origin[2]);
1553
+ geometry.translate(-origin.x, -origin.y, -origin.z);
1554
+ switch (rotation.axis) {
1555
+ case "X" /* X */:
1556
+ geometry.rotateX(toRadians(rotation.angle));
1557
+ break;
1558
+ case "y" /* Y */:
1559
+ geometry.rotateY(toRadians(rotation.angle));
1560
+ break;
1561
+ case "z" /* Z */:
1562
+ geometry.rotateZ(toRadians(rotation.angle));
1563
+ break;
1564
+ }
1565
+ if (rotation.rescale) {
1566
+ if (Math.abs(rotation.angle) === 22.5) {
1567
+ const s = 1 / Math.cos(0.39269909262657166);
1568
+ geometry.scale(s, 1, s);
1569
+ } else {
1570
+ const s = 1 / Math.cos(0.7853981852531433);
1571
+ geometry.scale(s, 1, s);
1572
+ }
1573
+ }
1574
+ geometry.translate(origin.x, origin.y, origin.z);
1575
+ }
1576
+ function applyModelPartRotation(modelPart, geometry) {
1577
+ const origin = new import_three7.Vector3(modelPart.pivotX, modelPart.pivotY, modelPart.pivotZ);
1578
+ geometry.translate(-origin.x, -origin.y, -origin.z);
1579
+ geometry.rotateX(toRadians(modelPart.pitch));
1580
+ geometry.rotateY(toRadians(modelPart.yaw));
1581
+ geometry.rotateZ(toRadians(modelPart.roll));
1582
+ geometry.translate(origin.x, origin.y, origin.z);
1583
+ }
1584
+ function applyGenericRotation(axis, rotation, obj) {
1585
+ switch (axis) {
1586
+ case "X" /* X */:
1587
+ obj.rotateOnAxis(new import_three7.Vector3(1, 0, 0), toRadians(rotation));
1588
+ break;
1589
+ case "y" /* Y */:
1590
+ obj.rotateOnAxis(new import_three7.Vector3(0, 1, 0), toRadians(rotation));
1591
+ break;
1592
+ case "z" /* Z */:
1593
+ obj.rotateOnAxis(new import_three7.Vector3(0, 0, 1), toRadians(rotation));
1594
+ break;
1595
+ }
1596
+ }
1597
+ function addBox3WireframeToObject(box, obj, color = 16777215, w = 2) {
1598
+ let size = new import_three7.Vector3();
1599
+ box.getSize(size);
1600
+ let boxGeo = new import_three7.BoxGeometry(size.x, size.y, size.z, 1, 1, 1);
1601
+ let wireGeo = new import_three7.EdgesGeometry(boxGeo);
1602
+ let wireMat = new import_three7.LineBasicMaterial({ color, linewidth: w });
1603
+ let wireframe = new import_three7.LineSegments(wireGeo, wireMat);
1604
+ obj.add(wireframe);
1605
+ let axes = new import_three7.AxesHelper(1);
1606
+ obj.add(axes);
1607
+ }
1608
+ function addWireframeToObject(obj, color = 16777215, w = 2) {
1609
+ let boxGeo = new import_three7.BoxGeometry(16, 16, 16, 1, 1, 1);
1610
+ let wireGeo = new import_three7.EdgesGeometry(boxGeo);
1611
+ let wireMat = new import_three7.LineBasicMaterial({ color, linewidth: w });
1612
+ let wireframe = new import_three7.LineSegments(wireGeo, wireMat);
1613
+ obj.add(wireframe);
1614
+ let axes = new import_three7.AxesHelper(1);
1615
+ obj.add(axes);
1616
+ }
1617
+ function addWireframeToMesh(geo, mesh, color = 16777215, w = 2) {
1618
+ let wireGeo = new import_three7.EdgesGeometry(geo);
1619
+ let wireMat = new import_three7.LineBasicMaterial({ color, linewidth: w });
1620
+ let wireframe = new import_three7.LineSegments(wireGeo, wireMat);
1621
+ mesh.add(wireframe);
1622
+ let axes = new import_three7.AxesHelper(1);
1623
+ mesh.add(axes);
1624
+ }
1625
+
1626
+ // src/util/performance.ts
1627
+ function captureException(e, ...extra) {
1628
+ console.error(e, extra);
1629
+ }
1630
+ function timingStart(marker) {
1631
+ console.time(marker);
1632
+ }
1633
+ function timingEnd(marker) {
1634
+ console.timeEnd(marker);
1635
+ }
1636
+
1637
+ // src/util/three.ts
1638
+ function isObject3D(obj) {
1639
+ return obj.isObject3D;
1640
+ }
1641
+ function isMesh(obj) {
1642
+ return obj.isMesh;
1643
+ }
1644
+ function isInstancedMesh(obj) {
1645
+ return obj.isInstancedMesh;
1646
+ }
1647
+ function isPerspectiveCamera(obj) {
1648
+ return obj.isPerspectiveCamera;
1649
+ }
1650
+ function isOrthographicCamera(obj) {
1651
+ return obj.isOrthographicCamera;
1652
+ }
1653
+
1654
+ // src/nbt/NBTHelper.ts
1655
+ var NBTHelper = class {
1656
+ static async fromBuffer(buffer) {
1657
+ const prismarineNbt = await import("prismarine-nbt");
1658
+ const { parsed, type, metadata } = await prismarineNbt.parse(buffer);
1659
+ return parsed;
1660
+ }
1661
+ };
1662
+
1663
+ // src/assets/source/HostedAssetSource.ts
1664
+ var import_ts_deepmerge2 = __toESM(require_dist());
1665
+ var p3 = prefix("HostedAssetSource");
1666
+ var DEFAULT_OPTIONS = {
1667
+ retryDefaults: true
1668
+ };
1669
+ var HostedAssetSource = class _HostedAssetSource extends AssetSource {
1670
+ static {
1671
+ this.MODEL = {
1672
+ config(request) {
1673
+ },
1674
+ parse(response) {
1675
+ return response.data;
1676
+ }
1677
+ };
1678
+ }
1679
+ static {
1680
+ this.BLOCKSTATE = {
1681
+ config(request) {
1682
+ },
1683
+ parse(response) {
1684
+ return response.data;
1685
+ }
1686
+ };
1687
+ }
1688
+ static {
1689
+ this.META = {
1690
+ config(request) {
1691
+ },
1692
+ parse(response) {
1693
+ return response.data;
1694
+ }
1695
+ };
1696
+ }
1697
+ static {
1698
+ this.NBT = {
1699
+ config(request) {
1700
+ request.responseType = "arraybuffer";
1701
+ },
1702
+ parse(response) {
1703
+ return NBTHelper.fromBuffer(Buffer.from(response.data));
1704
+ }
1705
+ };
1706
+ }
1707
+ static {
1708
+ this.IMAGE = {
1709
+ config(request) {
1710
+ request.responseType = "arraybuffer";
1711
+ },
1712
+ async parse(response) {
1713
+ return await ImageLoader.processResponse(response);
1714
+ }
1715
+ };
1716
+ }
1717
+ static {
1718
+ this.LIST = {
1719
+ config(request) {
1720
+ },
1721
+ parse(response) {
1722
+ return response.data;
1723
+ }
1724
+ };
1725
+ }
1726
+ static {
1727
+ this.JSON = {
1728
+ config(request) {
1729
+ },
1730
+ parse(response) {
1731
+ return response.data;
1732
+ }
1733
+ };
1734
+ }
1735
+ static {
1736
+ this.PARSER_MAP = /* @__PURE__ */ new Map([
1737
+ ["model" /* MODEL */, _HostedAssetSource.MODEL],
1738
+ ["blockstate" /* BLOCKSTATE */, _HostedAssetSource.BLOCKSTATE],
1739
+ ["meta" /* META */, _HostedAssetSource.META],
1740
+ ["nbt" /* NBT */, _HostedAssetSource.NBT],
1741
+ ["image" /* IMAGE */, _HostedAssetSource.IMAGE],
1742
+ ["list" /* LIST */, _HostedAssetSource.LIST],
1743
+ ["json" /* JSON */, _HostedAssetSource.JSON]
1744
+ ]);
1745
+ }
1746
+ async loadOrRetryWithDefaults(key, parser) {
1747
+ const direct = await this.load(key, parser);
1748
+ if (typeof direct !== "undefined") {
1749
+ return direct;
1750
+ }
1751
+ if (key.namespace !== DEFAULT_NAMESPACE) {
1752
+ console.info(p3, "Retrying", key, "with default namespace");
1753
+ const namespaceKey = new AssetKey(DEFAULT_NAMESPACE, key.path, key.assetType, key.type, key.rootType, key.extension, key.root);
1754
+ const namespaced = await this.load(namespaceKey, parser);
1755
+ if (typeof namespaced !== "undefined") {
1520
1756
  return namespaced;
1521
1757
  }
1522
1758
  if (typeof key.root !== "undefined" && key.root !== DEFAULT_ROOT || typeof this.root !== "undefined" && this.root !== DEFAULT_ROOT) {
@@ -1563,7 +1799,7 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1563
1799
  return void 0;
1564
1800
  }
1565
1801
  }
1566
- console.debug(p3, "Failed to load", key, err == null ? void 0 : err.message);
1802
+ console.debug(p3, "Failed to load", key, err?.message);
1567
1803
  return void 0;
1568
1804
  });
1569
1805
  }
@@ -1589,67 +1825,6 @@ var _HostedAssetSource = class _HostedAssetSource extends AssetSource {
1589
1825
  return this.load(key, responseParser);
1590
1826
  }
1591
1827
  };
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
1828
 
1654
1829
  // src/assets/source/archive/BrowserArchiveProxy.ts
1655
1830
  var import_zip = require("@zip.js/zip.js");
@@ -1725,7 +1900,7 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1725
1900
  return void 0;
1726
1901
  }
1727
1902
  }
1728
- console.debug(p4, "Failed to load", key, err == null ? void 0 : err.message);
1903
+ console.debug(p4, "Failed to load", key, err?.message);
1729
1904
  return void 0;
1730
1905
  });
1731
1906
  }
@@ -1756,7 +1931,7 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1756
1931
  return void 0;
1757
1932
  }
1758
1933
  }
1759
- console.debug(p4, "Failed to load", key, err == null ? void 0 : err.message);
1934
+ console.debug(p4, "Failed to load", key, err?.message);
1760
1935
  return void 0;
1761
1936
  });
1762
1937
  }
@@ -1766,9 +1941,14 @@ var ArchiveAssetSource = class _ArchiveAssetSource extends AssetSource {
1766
1941
  };
1767
1942
 
1768
1943
  // src/assets/AssetLoader.ts
1769
- var import_ts_deepmerge3 = __toESM(require_dist());
1770
1944
  var p5 = prefix("AssetLoader");
1771
- var _AssetLoader = class _AssetLoader {
1945
+ var AssetLoader = class {
1946
+ static {
1947
+ this.ROOT = DEFAULT_ROOT;
1948
+ }
1949
+ static {
1950
+ this._SOURCES = [];
1951
+ }
1772
1952
  static addSource(key, source, override = true) {
1773
1953
  if (override) {
1774
1954
  const existing = this.removeSource(key);
@@ -1789,8 +1969,11 @@ var _AssetLoader = class _AssetLoader {
1789
1969
  }
1790
1970
  return void 0;
1791
1971
  }
1972
+ static {
1973
+ this.addSource("mcassets-fallback", new HostedAssetSource("https://raw.githubusercontent.com/InventivetalentDev/minerender-fallback-assets/master", { retryDefaults: false }));
1974
+ this.addSource("mcassets", new HostedAssetSource(DEFAULT_ROOT, { retryDefaults: false }));
1975
+ }
1792
1976
  static async getAll(key, parser) {
1793
- console.log(this._SOURCES);
1794
1977
  let promises = [];
1795
1978
  for (const source of this._SOURCES) {
1796
1979
  promises.push(source.source.get(key, parser));
@@ -1799,31 +1982,18 @@ var _AssetLoader = class _AssetLoader {
1799
1982
  return results.filter((r) => r != void 0);
1800
1983
  });
1801
1984
  }
1985
+ /** Returns the first defined result in source-priority order, without merging assets. */
1802
1986
  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
- }
1987
+ const sources = [...this._SOURCES];
1988
+ for (const source of sources) {
1989
+ const result = await source.source.get(key, parser);
1990
+ if (result !== void 0) {
1991
+ return result;
1817
1992
  }
1818
- return void 0;
1819
- });
1993
+ }
1994
+ return void 0;
1820
1995
  }
1821
1996
  };
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
1997
 
1828
1998
  // src/assets/ModelTextures.ts
1829
1999
  var ModelTextures = class {
@@ -1831,11 +2001,21 @@ var ModelTextures = class {
1831
2001
  return this._persistentMetaCache ??= PersistentCache.open("minerender-texturemeta");
1832
2002
  }
1833
2003
  static async get(key) {
1834
- const asset = await this.preload(key);
1835
- if (asset) {
1836
- return ImageLoader.infoToCanvasData(asset);
2004
+ const keyStr = key.serialize();
2005
+ const pending = this.preload(key);
2006
+ const cached = Caching.textureAssetCache.getIfPresent(keyStr);
2007
+ try {
2008
+ const asset = await pending;
2009
+ if (asset) {
2010
+ return await ImageLoader.infoToCanvasData(asset);
2011
+ }
2012
+ return void 0;
2013
+ } catch (err) {
2014
+ if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {
2015
+ Caching.textureAssetCache.invalidate(keyStr);
2016
+ }
2017
+ throw err;
1837
2018
  }
1838
- return void 0;
1839
2019
  }
1840
2020
  static async preload(key) {
1841
2021
  const keyStr = key.serialize();
@@ -1909,7 +2089,28 @@ var CanvasImage = class {
1909
2089
  };
1910
2090
 
1911
2091
  // src/Ticker.ts
1912
- var _Ticker = class _Ticker {
2092
+ var Ticker = class _Ticker {
2093
+ static {
2094
+ this.TPS = 20;
2095
+ }
2096
+ static {
2097
+ this.counter = 0;
2098
+ }
2099
+ static {
2100
+ this._tickers = /* @__PURE__ */ new Map();
2101
+ }
2102
+ static {
2103
+ this.oneSecondTps = 0;
2104
+ }
2105
+ static {
2106
+ this.oneSecondTicks = 0;
2107
+ }
2108
+ static {
2109
+ this.fiveSecondTps = 0;
2110
+ }
2111
+ static {
2112
+ this.fiveSecondTicks = 0;
2113
+ }
1913
2114
  static schedule(fn, ms) {
1914
2115
  const handle = setInterval(fn, ms);
1915
2116
  const unref = handle.unref;
@@ -1971,14 +2172,6 @@ var _Ticker = class _Ticker {
1971
2172
  this._tickers.clear();
1972
2173
  }
1973
2174
  };
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
2175
 
1983
2176
  // src/texture/TextureAtlas.ts
1984
2177
  var TextureAtlas = class {
@@ -2004,6 +2197,9 @@ var TextureAtlas = class {
2004
2197
 
2005
2198
  // src/model/ModelGenerator.ts
2006
2199
  var ModelGenerator = class {
2200
+ static {
2201
+ this.ITEM_LAYERS = ["layer0", "layer1", "layer2", "layer3", "layer4"];
2202
+ }
2007
2203
  static generateItemModel(imageData, layer) {
2008
2204
  const mainElement = {
2009
2205
  from: [0, 0, 7.5],
@@ -2023,7 +2219,6 @@ var ModelGenerator = class {
2023
2219
  return [mainElement];
2024
2220
  }
2025
2221
  };
2026
- ModelGenerator.ITEM_LAYERS = ["layer0", "layer1", "layer2", "layer3", "layer4"];
2027
2222
 
2028
2223
  // src/UVMapper.ts
2029
2224
  var p6 = prefix("UVMapper");
@@ -2199,7 +2394,6 @@ var UVMapper = class {
2199
2394
  return [tl, tr, bl, br];
2200
2395
  }
2201
2396
  static async createAtlas(originalModel) {
2202
- var _a;
2203
2397
  const textureMap = {};
2204
2398
  const metaMap = {};
2205
2399
  const model = { ...originalModel };
@@ -2279,16 +2473,15 @@ var UVMapper = class {
2279
2473
  if (texture.animated) {
2280
2474
  hasAnimation = true;
2281
2475
  const meta = metaMap[textureKey];
2282
- const frameTime = ((_a = meta == null ? void 0 : meta.animation) == null ? void 0 : _a.frametime) ?? 1;
2476
+ const frameTime = meta?.animation?.frametime ?? 1;
2283
2477
  console.log(meta);
2284
2478
  console.log(frameTime);
2285
2479
  let t = 0;
2286
2480
  let f = 0;
2287
2481
  animatorFunctions[textureKey] = () => {
2288
- var _a2;
2289
2482
  if (t++ >= frameTime) {
2290
2483
  t = 0;
2291
- const frames = (_a2 = meta == null ? void 0 : meta.animation) == null ? void 0 : _a2.frames;
2484
+ const frames = meta?.animation?.frames;
2292
2485
  const frame = frames ? frames[f] : f;
2293
2486
  image.putData(texture.getFrameSectionData(frame), x, y, 0, 0, maxWidth, maxWidth);
2294
2487
  f++;
@@ -2515,17 +2708,20 @@ function shutdown() {
2515
2708
  }
2516
2709
 
2517
2710
  // src/assets/Entities.ts
2518
- var import_typescript_memoize3 = require("typescript-memoize");
2519
2711
  var Entities = class {
2520
2712
  static async getBlockEntityModels() {
2521
2713
  const key = AssetKey.parse("models", "minerender:blockEntityModels");
2522
2714
  console.log(key);
2523
- return AssetLoader.get(key, "json" /* JSON */);
2715
+ return Caching.entityModelsCache.get(key.serialize(), () => {
2716
+ return AssetLoader.get(key, "json" /* JSON */);
2717
+ });
2524
2718
  }
2525
2719
  static async getEntityModels() {
2526
2720
  const key = AssetKey.parse("models", "minerender:entityModels");
2527
2721
  console.log(key);
2528
- return AssetLoader.get(key, "json" /* JSON */);
2722
+ return Caching.entityModelsCache.get(key.serialize(), () => {
2723
+ return AssetLoader.get(key, "json" /* JSON */);
2724
+ });
2529
2725
  }
2530
2726
  // BlockEntity names are hardcoded
2531
2727
  static async getBlockList() {
@@ -2571,12 +2767,6 @@ var Entities = class {
2571
2767
  };
2572
2768
  }
2573
2769
  };
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
2770
  var EntityModels = class {
2581
2771
  };
2582
2772
  var BlockEntityModels = class {
@@ -2640,18 +2830,26 @@ var MineRenderError = class _MineRenderError extends Error {
2640
2830
  };
2641
2831
 
2642
2832
  // src/renderer/SceneObject.ts
2643
- var import_ts_deepmerge4 = __toESM(require_dist());
2833
+ var import_ts_deepmerge3 = __toESM(require_dist());
2644
2834
  var p7 = prefix("SceneObject");
2645
- var _SceneObject = class _SceneObject extends import_three9.Object3D {
2835
+ var SceneObject = class _SceneObject extends import_three9.Object3D {
2646
2836
  constructor(options) {
2647
2837
  super();
2648
2838
  this.isSceneObject = true;
2649
2839
  this.materialCallbacks = {};
2650
2840
  this._isInstanced = false;
2651
2841
  this._instanceCounter = 0;
2652
- this.options = (0, import_ts_deepmerge4.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
2842
+ this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
2653
2843
  console.log("SceneObject options", this.options);
2654
2844
  }
2845
+ static {
2846
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge3.default)({}, {
2847
+ instanceMeshes: true,
2848
+ maxInstanceCount: 50,
2849
+ mergeMeshes: true,
2850
+ wireframe: false
2851
+ });
2852
+ }
2655
2853
  set scene(scene) {
2656
2854
  if (!!this._scene) throw new MineRenderError("Scene already set");
2657
2855
  this._scene = scene;
@@ -2993,34 +3191,29 @@ var _SceneObject = class _SceneObject extends import_three9.Object3D {
2993
3191
  this.notifyDirty();
2994
3192
  }
2995
3193
  removeFromScene() {
2996
- var _a;
2997
- (_a = this._scene) == null ? void 0 : _a.remove(this);
3194
+ this._scene?.remove(this);
2998
3195
  this.notifyDirty();
2999
3196
  }
3000
3197
  //</editor-fold>
3001
3198
  };
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
3199
  function isSceneObject(obj) {
3010
3200
  return obj.isSceneObject;
3011
3201
  }
3012
3202
 
3013
3203
  // src/entity/scene/EntityObject.ts
3014
- var import_ts_deepmerge5 = __toESM(require_dist());
3204
+ var import_ts_deepmerge4 = __toESM(require_dist());
3015
3205
  var import_three11 = require("three");
3016
- var THREE2 = __toESM(require("three"));
3206
+ var THREE3 = __toESM(require("three"));
3017
3207
  var EntityObject = class extends SceneObject {
3018
3208
  constructor(entity, options) {
3019
3209
  super();
3020
3210
  this.entity = entity;
3021
3211
  this.isEntityObject = true;
3022
3212
  this.meshesCreated = false;
3023
- this.options = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
3213
+ this.options = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
3214
+ }
3215
+ static {
3216
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, {});
3024
3217
  }
3025
3218
  async init() {
3026
3219
  this.createMeshes();
@@ -3029,17 +3222,19 @@ var EntityObject = class extends SceneObject {
3029
3222
  dispose() {
3030
3223
  super.dispose();
3031
3224
  }
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,
3225
+ get textureKey() {
3226
+ return new AssetKey(
3227
+ this.entity.key?.namespace ?? DEFAULT_NAMESPACE,
3036
3228
  this.entity.key.path,
3037
3229
  //TODO: texture may differ from entity name; most of them are in subdirectories for multiple variants etc.
3038
3230
  "textures",
3039
3231
  "entity",
3040
3232
  "assets",
3041
3233
  ".png"
3042
- ));
3234
+ );
3235
+ }
3236
+ async loadTextures() {
3237
+ this.imageData = await ModelTextures.get(this.textureKey);
3043
3238
  }
3044
3239
  //TODO: abstract this, since extracted model data can be used for entities, blocks, players
3045
3240
  createMeshes(force = false) {
@@ -3058,8 +3253,8 @@ var EntityObject = class extends SceneObject {
3058
3253
  const l = cube.maxZ - cube.minZ;
3059
3254
  const uv = texture.toUvArray(w, h, l);
3060
3255
  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));
3256
+ cubeGeo.applyMatrix4(new THREE3.Matrix4().makeTranslation(w / 2, h / 2, l / 2));
3257
+ cubeGeo.applyMatrix4(new THREE3.Matrix4().makeTranslation(cube.minX, cube.minY, cube.minZ));
3063
3258
  applyModelPartRotation(part, cubeGeo);
3064
3259
  const mesh = this.createMesh(partName, cubeGeo, mat);
3065
3260
  partAnchor.add(mesh);
@@ -3072,24 +3267,25 @@ var EntityObject = class extends SceneObject {
3072
3267
  this.meshesCreated = true;
3073
3268
  }
3074
3269
  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
- }
3270
+ const assetKeyStr = this.textureKey.serialize();
3271
+ const keyStr = `entity:${assetKeyStr}`;
3272
+ let mat = Caching.materialCache.getIfPresent(keyStr);
3273
+ if (!mat) {
3274
+ const pending = this.loadTextures();
3275
+ const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
3276
+ await pending;
3277
+ if (!this.imageData) return;
3278
+ const canvas = this.imageData.data.canvas;
3279
+ const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
3280
+ mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
3281
+ this.imageData = void 0;
3282
+ }
3283
+ this.iterateAllMeshes((mesh) => {
3284
+ mesh.material = mat;
3285
+ });
3286
+ this.notifyDirty();
3090
3287
  }
3091
3288
  };
3092
- EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, {});
3093
3289
  function isEntityObject(obj) {
3094
3290
  return obj.isEntityObject;
3095
3291
  }
@@ -3130,8 +3326,7 @@ var SceneInspector = class {
3130
3326
  return out;
3131
3327
  }
3132
3328
  onClick(event) {
3133
- var _a;
3134
- if (((_a = event.target) == null ? void 0 : _a.nodeName) !== "CANVAS") return;
3329
+ if (event.target?.nodeName !== "CANVAS") return;
3135
3330
  if (!event.ctrlKey) return;
3136
3331
  setTimeout(() => {
3137
3332
  this.mouse.x = event.clientX / window.innerWidth * 2 - 1;
@@ -4081,26 +4276,28 @@ function computeMorphedAttributes(object) {
4081
4276
  }
4082
4277
 
4083
4278
  // src/model/scene/ModelObject.ts
4084
- var import_ts_deepmerge6 = __toESM(require_dist());
4279
+ var import_ts_deepmerge5 = __toESM(require_dist());
4085
4280
  var p10 = prefix("ModelObject");
4086
- var _ModelObject = class _ModelObject extends SceneObject {
4281
+ var ModelObject = class _ModelObject extends SceneObject {
4087
4282
  constructor(originalModel, options) {
4088
4283
  super(options);
4089
4284
  this.originalModel = originalModel;
4090
4285
  this.isModelObject = true;
4091
4286
  this.meshesCreated = false;
4092
- this.options = (0, import_ts_deepmerge6.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
4287
+ this.options = (0, import_ts_deepmerge5.default)({}, _ModelObject.DEFAULT_OPTIONS, options ?? {});
4093
4288
  console.log("ModelObject options", this.options);
4094
4289
  }
4290
+ static {
4291
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge5.default)({}, SceneObject.DEFAULT_OPTIONS, {});
4292
+ }
4095
4293
  async init() {
4096
4294
  await this.loadTextures();
4097
4295
  this.createMeshes();
4098
4296
  this.applyTextures();
4099
4297
  }
4100
4298
  dispose() {
4101
- var _a;
4102
4299
  super.dispose();
4103
- (_a = this.atlas) == null ? void 0 : _a.dispose();
4300
+ this.atlas?.dispose();
4104
4301
  }
4105
4302
  get textureAtlas() {
4106
4303
  return this.atlas;
@@ -4110,13 +4307,12 @@ var _ModelObject = class _ModelObject extends SceneObject {
4110
4307
  this.atlas = await UVMapper.getAtlas(this.originalModel);
4111
4308
  }
4112
4309
  createMeshes(force = false) {
4113
- var _a;
4114
4310
  if (this.meshesCreated && !force) return;
4115
4311
  const mat = Materials.MISSING_TEXTURE;
4116
4312
  let allGeos = [];
4117
4313
  if (this.atlas) {
4118
4314
  if (this.atlas.model.elements) {
4119
- (_a = this.atlas.model.elements) == null ? void 0 : _a.forEach((el) => {
4315
+ this.atlas.model.elements?.forEach((el) => {
4120
4316
  const elGeo = this._getBoxGeometryFromElement(el).clone();
4121
4317
  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
4318
  elGeo.applyMatrix4(new import_three15.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
@@ -4189,17 +4385,15 @@ var _ModelObject = class _ModelObject extends SceneObject {
4189
4385
  }
4190
4386
  }
4191
4387
  };
4192
- _ModelObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge6.default)({}, SceneObject.DEFAULT_OPTIONS, {});
4193
- var ModelObject = _ModelObject;
4194
4388
  function isModelObject(obj) {
4195
4389
  return obj.isModelObject;
4196
4390
  }
4197
4391
 
4198
4392
  // src/model/block/scene/BlockObject.ts
4199
- var import_ts_deepmerge7 = __toESM(require_dist());
4393
+ var import_ts_deepmerge6 = __toESM(require_dist());
4200
4394
  var import_three16 = require("three");
4201
4395
  var p11 = prefix("BlockObject");
4202
- var _BlockObject = class _BlockObject extends SceneObject {
4396
+ var BlockObject = class _BlockObject extends SceneObject {
4203
4397
  constructor(blockState, options) {
4204
4398
  super(options);
4205
4399
  this.blockState = blockState;
@@ -4212,7 +4406,12 @@ var _BlockObject = class _BlockObject extends SceneObject {
4212
4406
  this._instanceModel = [];
4213
4407
  this._variants = [];
4214
4408
  this._models = [];
4215
- this.options = (0, import_ts_deepmerge7.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
4409
+ this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
4410
+ }
4411
+ static {
4412
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge6.default)({}, ModelObject.DEFAULT_OPTIONS, {
4413
+ applyDefaultState: true
4414
+ });
4216
4415
  }
4217
4416
  async init() {
4218
4417
  if (this.options.applyDefaultState) {
@@ -4501,10 +4700,6 @@ var _BlockObject = class _BlockObject extends SceneObject {
4501
4700
  //TODO: should override rotation + scale methods
4502
4701
  //TODO
4503
4702
  };
4504
- _BlockObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge7.default)({}, ModelObject.DEFAULT_OPTIONS, {
4505
- applyDefaultState: true
4506
- });
4507
- var BlockObject = _BlockObject;
4508
4703
  function isBlockObject(obj) {
4509
4704
  return obj.isBlockObject;
4510
4705
  }
@@ -4529,11 +4724,10 @@ var StructureParser = class {
4529
4724
  throw new MineRenderError("Structure does not have palette(s)");
4530
4725
  }
4531
4726
  const blocks = nbt.blocks.value.value.map((block) => {
4532
- var _a;
4533
4727
  const state = palette.value.value[block.state.value];
4534
4728
  if (state.Name.value === "minecraft:air") return void 0;
4535
4729
  const props = {};
4536
- for (let k in (_a = state.Properties) == null ? void 0 : _a.value) {
4730
+ for (let k in state.Properties?.value) {
4537
4731
  props[k] = state.Properties.value[k].value;
4538
4732
  }
4539
4733
  return {
@@ -4552,7 +4746,7 @@ var StructureParser = class {
4552
4746
 
4553
4747
  // src/renderer/MineRenderScene.ts
4554
4748
  var import_three17 = require("three");
4555
- var import_ts_deepmerge9 = __toESM(require_dist());
4749
+ var import_ts_deepmerge8 = __toESM(require_dist());
4556
4750
 
4557
4751
  // src/skin/SkinPart.ts
4558
4752
  var SkinPart = /* @__PURE__ */ ((SkinPart2) => {
@@ -5283,7 +5477,7 @@ var slimSkinGeometries = {
5283
5477
  };
5284
5478
 
5285
5479
  // src/skin/scene/SkinObject.ts
5286
- var import_ts_deepmerge8 = __toESM(require_dist());
5480
+ var import_ts_deepmerge7 = __toESM(require_dist());
5287
5481
  var SkinObject = class extends SceneObject {
5288
5482
  constructor(options) {
5289
5483
  super();
@@ -5291,7 +5485,7 @@ var SkinObject = class extends SceneObject {
5291
5485
  this.legacy = false;
5292
5486
  this.skinTextureWidth = 64;
5293
5487
  this.skinTextureHeight = 64;
5294
- this.options = (0, import_ts_deepmerge8.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
5488
+ this.options = (0, import_ts_deepmerge7.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
5295
5489
  }
5296
5490
  async init() {
5297
5491
  this.createMeshes();
@@ -5395,31 +5589,64 @@ var SkinObject = class extends SceneObject {
5395
5589
  };
5396
5590
 
5397
5591
  // src/renderer/MineRenderScene.ts
5398
- var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5592
+ var MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5399
5593
  constructor(options) {
5400
5594
  super();
5401
5595
  this.isMineRenderScene = true;
5402
5596
  this.stats = new SceneStats();
5403
5597
  this.instanceManager = new InstanceManager();
5404
5598
  this.dirty = true;
5405
- this.options = (0, import_ts_deepmerge9.default)({}, _MineRenderScene.DEFAULT_OPTIONS, options ?? {});
5599
+ this.observedObjects = /* @__PURE__ */ new Set();
5600
+ this.onObjectChange = (event) => {
5601
+ if (event.target?.parent === this) {
5602
+ this.dirty = true;
5603
+ }
5604
+ };
5605
+ this.options = (0, import_ts_deepmerge8.default)({}, _MineRenderScene.DEFAULT_OPTIONS, options ?? {});
5406
5606
  }
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++;
5607
+ static {
5608
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge8.default)({}, {});
5609
+ }
5610
+ add(...objects) {
5611
+ for (const object of objects) {
5612
+ this.dirty = true;
5613
+ try {
5614
+ super.add(object);
5615
+ } finally {
5616
+ if (object?.isObject3D && object !== this) {
5617
+ this.updateObjectRegistration(object, object.parent === this);
5618
+ }
5413
5619
  }
5414
- obj.addEventListener("change", (event) => {
5415
- this.dirty = true;
5416
- });
5417
5620
  }
5418
- return super.add(...object);
5621
+ return this;
5419
5622
  }
5420
- remove(...object) {
5421
- this.dirty = true;
5422
- return super.remove(...object);
5623
+ remove(...objects) {
5624
+ for (const object of objects) {
5625
+ if (!this.children.includes(object)) continue;
5626
+ this.dirty = true;
5627
+ this.updateObjectRegistration(object, false);
5628
+ try {
5629
+ super.remove(object);
5630
+ } finally {
5631
+ this.updateObjectRegistration(object, object.parent === this);
5632
+ }
5633
+ }
5634
+ return this;
5635
+ }
5636
+ updateObjectRegistration(object, attached) {
5637
+ if (this.observedObjects.has(object) === attached) return;
5638
+ if (attached) {
5639
+ this.observedObjects.add(object);
5640
+ object.addEventListener("change", this.onObjectChange);
5641
+ } else {
5642
+ this.observedObjects.delete(object);
5643
+ object.removeEventListener("change", this.onObjectChange);
5644
+ }
5645
+ const change = attached ? 1 : -1;
5646
+ this.stats.objectCount += change;
5647
+ if (isSceneObject(object)) {
5648
+ this.stats.sceneObjectCount += change;
5649
+ }
5423
5650
  }
5424
5651
  async initAndAdd(...object) {
5425
5652
  this.dirty = true;
@@ -5429,13 +5656,12 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5429
5656
  return this.add(...object);
5430
5657
  }
5431
5658
  async addSceneObject(asset, objectSupplier, _options, parent = this) {
5432
- var _a, _b;
5433
5659
  console.log("addSceneObject", asset);
5434
5660
  console.log("parent", parent);
5435
5661
  console.log(_options);
5436
5662
  this.dirty = true;
5437
5663
  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") {
5664
+ if (obj?.options?.instanceMeshes && asset.key && asset.key?.assetType === "models") {
5439
5665
  console.log("instanceMeshes + key");
5440
5666
  const key = asset.key.serialize();
5441
5667
  return this.instanceManager.getOrCreate(key, async () => {
@@ -5475,414 +5701,22 @@ var _MineRenderScene = class _MineRenderScene extends import_three17.Scene {
5475
5701
  return this.addSceneObject(entity, () => new EntityObject(entity, options), options, parent);
5476
5702
  }
5477
5703
  };
5478
- _MineRenderScene.DEFAULT_OPTIONS = (0, import_ts_deepmerge9.default)({}, {});
5479
- var MineRenderScene = _MineRenderScene;
5480
5704
  function isMineRenderScene(obj) {
5481
5705
  return obj.isMineRenderScene;
5482
5706
  }
5483
5707
 
5484
5708
  // src/renderer/Renderer.ts
5485
- var import_three18 = require("three");
5486
- var import_ts_deepmerge10 = __toESM(require_dist());
5709
+ var import_three19 = require("three");
5710
+ var import_ts_deepmerge9 = __toESM(require_dist());
5487
5711
  var import_stats = __toESM(require("stats.js"));
5488
5712
  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);
5505
- }
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
- );
5531
- }
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);
5568
- }
5569
- if (this.options.debug.axes) {
5570
- const axesHelper = new import_three18.AxesHelper(64);
5571
- this.scene.add(axesHelper);
5572
- }
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]);
5578
- }
5579
- }
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]);
5585
- }
5586
- }
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");
5602
- }
5603
- if (this.viewHeight == 0) {
5604
- console.warn("0 element height");
5605
- }
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();
5626
- }
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();
5654
- }
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);
5660
- }
5661
- }
5662
- this.dirty = false;
5663
- if (this._stats) {
5664
- this._stats.end();
5665
- }
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);
5739
- }
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"];
5757
- }
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);
5766
- }
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"];
5800
- }
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"];
5814
- }
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;
5828
- }
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;
5838
- }
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;
5852
- }
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
5713
 
5880
5714
  // src/three/OrbitControls.js
5881
- var import_three20 = require("three");
5715
+ var import_three18 = require("three");
5882
5716
  var _changeEvent = { type: "change" };
5883
5717
  var _startEvent = { type: "start" };
5884
5718
  var _endEvent = { type: "end" };
5885
- var OrbitControls = class extends import_three20.EventDispatcher {
5719
+ var OrbitControls = class extends import_three18.EventDispatcher {
5886
5720
  constructor(object, domElement) {
5887
5721
  super();
5888
5722
  if (domElement === void 0) console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.');
@@ -5891,7 +5725,7 @@ var OrbitControls = class extends import_three20.EventDispatcher {
5891
5725
  this.domElement = domElement;
5892
5726
  this.domElement.style.touchAction = "none";
5893
5727
  this.enabled = true;
5894
- this.target = new import_three20.Vector3();
5728
+ this.target = new import_three18.Vector3();
5895
5729
  this.minDistance = 0;
5896
5730
  this.maxDistance = Infinity;
5897
5731
  this.minZoom = 0;
@@ -5913,8 +5747,8 @@ var OrbitControls = class extends import_three20.EventDispatcher {
5913
5747
  this.autoRotate = false;
5914
5748
  this.autoRotateSpeed = 2;
5915
5749
  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 };
5750
+ this.mouseButtons = { LEFT: import_three18.MOUSE.ROTATE, MIDDLE: import_three18.MOUSE.DOLLY, RIGHT: import_three18.MOUSE.PAN };
5751
+ this.touches = { ONE: import_three18.TOUCH.ROTATE, TWO: import_three18.TOUCH.DOLLY_PAN };
5918
5752
  this.target0 = this.target.clone();
5919
5753
  this.position0 = this.object.position.clone();
5920
5754
  this.zoom0 = this.object.zoom;
@@ -5943,11 +5777,11 @@ var OrbitControls = class extends import_three20.EventDispatcher {
5943
5777
  state = STATE.NONE;
5944
5778
  };
5945
5779
  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));
5780
+ const offset = new import_three18.Vector3();
5781
+ const quat = new import_three18.Quaternion().setFromUnitVectors(object.up, new import_three18.Vector3(0, 1, 0));
5948
5782
  const quatInverse = quat.clone().invert();
5949
- const lastPosition = new import_three20.Vector3();
5950
- const lastQuaternion = new import_three20.Quaternion();
5783
+ const lastPosition = new import_three18.Vector3();
5784
+ const lastQuaternion = new import_three18.Quaternion();
5951
5785
  const twoPI = 2 * Math.PI;
5952
5786
  return function update() {
5953
5787
  const position = scope.object.position;
@@ -6033,20 +5867,20 @@ var OrbitControls = class extends import_three20.EventDispatcher {
6033
5867
  };
6034
5868
  let state = STATE.NONE;
6035
5869
  const EPS = 1e-6;
6036
- const spherical = new import_three20.Spherical();
6037
- const sphericalDelta = new import_three20.Spherical();
5870
+ const spherical = new import_three18.Spherical();
5871
+ const sphericalDelta = new import_three18.Spherical();
6038
5872
  let scale = 1;
6039
- const panOffset = new import_three20.Vector3();
5873
+ const panOffset = new import_three18.Vector3();
6040
5874
  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();
5875
+ const rotateStart = new import_three18.Vector2();
5876
+ const rotateEnd = new import_three18.Vector2();
5877
+ const rotateDelta = new import_three18.Vector2();
5878
+ const panStart = new import_three18.Vector2();
5879
+ const panEnd = new import_three18.Vector2();
5880
+ const panDelta = new import_three18.Vector2();
5881
+ const dollyStart = new import_three18.Vector2();
5882
+ const dollyEnd = new import_three18.Vector2();
5883
+ const dollyDelta = new import_three18.Vector2();
6050
5884
  const pointers = [];
6051
5885
  const pointerPositions = {};
6052
5886
  function getAutoRotationAngle() {
@@ -6062,7 +5896,7 @@ var OrbitControls = class extends import_three20.EventDispatcher {
6062
5896
  sphericalDelta.phi -= angle;
6063
5897
  }
6064
5898
  const panLeft = function() {
6065
- const v = new import_three20.Vector3();
5899
+ const v = new import_three18.Vector3();
6066
5900
  return function panLeft2(distance, objectMatrix) {
6067
5901
  v.setFromMatrixColumn(objectMatrix, 0);
6068
5902
  v.multiplyScalar(-distance);
@@ -6070,7 +5904,7 @@ var OrbitControls = class extends import_three20.EventDispatcher {
6070
5904
  };
6071
5905
  }();
6072
5906
  const panUp = function() {
6073
- const v = new import_three20.Vector3();
5907
+ const v = new import_three18.Vector3();
6074
5908
  return function panUp2(distance, objectMatrix) {
6075
5909
  if (scope.screenSpacePanning === true) {
6076
5910
  v.setFromMatrixColumn(objectMatrix, 1);
@@ -6083,7 +5917,7 @@ var OrbitControls = class extends import_three20.EventDispatcher {
6083
5917
  };
6084
5918
  }();
6085
5919
  const pan = function() {
6086
- const offset = new import_three20.Vector3();
5920
+ const offset = new import_three18.Vector3();
6087
5921
  return function pan2(deltaX, deltaY) {
6088
5922
  const element = scope.domElement;
6089
5923
  if (scope.object.isPerspectiveCamera) {
@@ -6126,397 +5960,880 @@ var OrbitControls = class extends import_three20.EventDispatcher {
6126
5960
  scope.enableZoom = false;
6127
5961
  }
6128
5962
  }
6129
- function handleMouseDownRotate(event) {
6130
- rotateStart.set(event.clientX, event.clientY);
6131
- }
6132
- function handleMouseDownDolly(event) {
6133
- dollyStart.set(event.clientX, event.clientY);
5963
+ function handleMouseDownRotate(event) {
5964
+ rotateStart.set(event.clientX, event.clientY);
5965
+ }
5966
+ function handleMouseDownDolly(event) {
5967
+ dollyStart.set(event.clientX, event.clientY);
5968
+ }
5969
+ function handleMouseDownPan(event) {
5970
+ panStart.set(event.clientX, event.clientY);
5971
+ }
5972
+ function handleMouseMoveRotate(event) {
5973
+ rotateEnd.set(event.clientX, event.clientY);
5974
+ rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
5975
+ const element = scope.domElement;
5976
+ rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
5977
+ rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
5978
+ rotateStart.copy(rotateEnd);
5979
+ scope.update();
5980
+ }
5981
+ function handleMouseMoveDolly(event) {
5982
+ dollyEnd.set(event.clientX, event.clientY);
5983
+ dollyDelta.subVectors(dollyEnd, dollyStart);
5984
+ if (dollyDelta.y > 0) {
5985
+ dollyOut(getZoomScale());
5986
+ } else if (dollyDelta.y < 0) {
5987
+ dollyIn(getZoomScale());
5988
+ }
5989
+ dollyStart.copy(dollyEnd);
5990
+ scope.update();
5991
+ }
5992
+ function handleMouseMovePan(event) {
5993
+ panEnd.set(event.clientX, event.clientY);
5994
+ panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
5995
+ pan(panDelta.x, panDelta.y);
5996
+ panStart.copy(panEnd);
5997
+ scope.update();
5998
+ }
5999
+ function handleMouseUp() {
6000
+ }
6001
+ function handleMouseWheel(event) {
6002
+ if (event.deltaY < 0) {
6003
+ dollyIn(getZoomScale());
6004
+ } else if (event.deltaY > 0) {
6005
+ dollyOut(getZoomScale());
6006
+ }
6007
+ scope.update();
6008
+ }
6009
+ function handleKeyDown(event) {
6010
+ let needsUpdate = false;
6011
+ switch (event.code) {
6012
+ case scope.keys.UP:
6013
+ pan(0, scope.keyPanSpeed);
6014
+ needsUpdate = true;
6015
+ break;
6016
+ case scope.keys.BOTTOM:
6017
+ pan(0, -scope.keyPanSpeed);
6018
+ needsUpdate = true;
6019
+ break;
6020
+ case scope.keys.LEFT:
6021
+ pan(scope.keyPanSpeed, 0);
6022
+ needsUpdate = true;
6023
+ break;
6024
+ case scope.keys.RIGHT:
6025
+ pan(-scope.keyPanSpeed, 0);
6026
+ needsUpdate = true;
6027
+ break;
6028
+ }
6029
+ if (needsUpdate) {
6030
+ event.preventDefault();
6031
+ scope.update();
6032
+ }
6033
+ }
6034
+ function handleTouchStartRotate() {
6035
+ if (pointers.length === 1) {
6036
+ rotateStart.set(pointers[0].pageX, pointers[0].pageY);
6037
+ } else {
6038
+ const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
6039
+ const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
6040
+ rotateStart.set(x, y);
6041
+ }
6042
+ }
6043
+ function handleTouchStartPan() {
6044
+ if (pointers.length === 1) {
6045
+ panStart.set(pointers[0].pageX, pointers[0].pageY);
6046
+ } else {
6047
+ const x = 0.5 * (pointers[0].pageX + pointers[1].pageX);
6048
+ const y = 0.5 * (pointers[0].pageY + pointers[1].pageY);
6049
+ panStart.set(x, y);
6050
+ }
6051
+ }
6052
+ function handleTouchStartDolly() {
6053
+ const dx = pointers[0].pageX - pointers[1].pageX;
6054
+ const dy = pointers[0].pageY - pointers[1].pageY;
6055
+ const distance = Math.sqrt(dx * dx + dy * dy);
6056
+ dollyStart.set(0, distance);
6057
+ }
6058
+ function handleTouchStartDollyPan() {
6059
+ if (scope.enableZoom) handleTouchStartDolly();
6060
+ if (scope.enablePan) handleTouchStartPan();
6061
+ }
6062
+ function handleTouchStartDollyRotate() {
6063
+ if (scope.enableZoom) handleTouchStartDolly();
6064
+ if (scope.enableRotate) handleTouchStartRotate();
6065
+ }
6066
+ function handleTouchMoveRotate(event) {
6067
+ if (pointers.length == 1) {
6068
+ rotateEnd.set(event.pageX, event.pageY);
6069
+ } else {
6070
+ const position = getSecondPointerPosition(event);
6071
+ const x = 0.5 * (event.pageX + position.x);
6072
+ const y = 0.5 * (event.pageY + position.y);
6073
+ rotateEnd.set(x, y);
6074
+ }
6075
+ rotateDelta.subVectors(rotateEnd, rotateStart).multiplyScalar(scope.rotateSpeed);
6076
+ const element = scope.domElement;
6077
+ rotateLeft(2 * Math.PI * rotateDelta.x / element.clientHeight);
6078
+ rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight);
6079
+ rotateStart.copy(rotateEnd);
6080
+ }
6081
+ function handleTouchMovePan(event) {
6082
+ if (pointers.length === 1) {
6083
+ panEnd.set(event.pageX, event.pageY);
6084
+ } else {
6085
+ const position = getSecondPointerPosition(event);
6086
+ const x = 0.5 * (event.pageX + position.x);
6087
+ const y = 0.5 * (event.pageY + position.y);
6088
+ panEnd.set(x, y);
6089
+ }
6090
+ panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
6091
+ pan(panDelta.x, panDelta.y);
6092
+ panStart.copy(panEnd);
6093
+ }
6094
+ function handleTouchMoveDolly(event) {
6095
+ const position = getSecondPointerPosition(event);
6096
+ const dx = event.pageX - position.x;
6097
+ const dy = event.pageY - position.y;
6098
+ const distance = Math.sqrt(dx * dx + dy * dy);
6099
+ dollyEnd.set(0, distance);
6100
+ dollyDelta.set(0, Math.pow(dollyEnd.y / dollyStart.y, scope.zoomSpeed));
6101
+ dollyOut(dollyDelta.y);
6102
+ dollyStart.copy(dollyEnd);
6103
+ }
6104
+ function handleTouchMoveDollyPan(event) {
6105
+ if (scope.enableZoom) handleTouchMoveDolly(event);
6106
+ if (scope.enablePan) handleTouchMovePan(event);
6107
+ }
6108
+ function handleTouchMoveDollyRotate(event) {
6109
+ if (scope.enableZoom) handleTouchMoveDolly(event);
6110
+ if (scope.enableRotate) handleTouchMoveRotate(event);
6111
+ }
6112
+ function handleTouchEnd() {
6113
+ }
6114
+ function onPointerDown(event) {
6115
+ if (scope.enabled === false) return;
6116
+ if (pointers.length === 0) {
6117
+ scope.domElement.setPointerCapture(event.pointerId);
6118
+ scope.domElement.addEventListener("pointermove", onPointerMove);
6119
+ scope.domElement.addEventListener("pointerup", onPointerUp);
6120
+ }
6121
+ addPointer(event);
6122
+ if (event.pointerType === "touch") {
6123
+ onTouchStart(event);
6124
+ } else {
6125
+ onMouseDown(event);
6126
+ }
6127
+ }
6128
+ function onPointerMove(event) {
6129
+ if (scope.enabled === false) return;
6130
+ if (event.pointerType === "touch") {
6131
+ onTouchMove(event);
6132
+ } else {
6133
+ onMouseMove(event);
6134
+ }
6135
+ }
6136
+ function onPointerUp(event) {
6137
+ if (scope.enabled === false) return;
6138
+ if (event.pointerType === "touch") {
6139
+ onTouchEnd();
6140
+ } else {
6141
+ onMouseUp(event);
6142
+ }
6143
+ removePointer(event);
6144
+ if (pointers.length === 0) {
6145
+ scope.domElement.releasePointerCapture(event.pointerId);
6146
+ scope.domElement.removeEventListener("pointermove", onPointerMove);
6147
+ scope.domElement.removeEventListener("pointerup", onPointerUp);
6148
+ }
6149
+ }
6150
+ function onPointerCancel(event) {
6151
+ removePointer(event);
6152
+ }
6153
+ function onMouseDown(event) {
6154
+ let mouseAction;
6155
+ switch (event.button) {
6156
+ case 0:
6157
+ mouseAction = scope.mouseButtons.LEFT;
6158
+ break;
6159
+ case 1:
6160
+ mouseAction = scope.mouseButtons.MIDDLE;
6161
+ break;
6162
+ case 2:
6163
+ mouseAction = scope.mouseButtons.RIGHT;
6164
+ break;
6165
+ default:
6166
+ mouseAction = -1;
6167
+ }
6168
+ switch (mouseAction) {
6169
+ case import_three18.MOUSE.DOLLY:
6170
+ if (scope.enableZoom === false) return;
6171
+ handleMouseDownDolly(event);
6172
+ state = STATE.DOLLY;
6173
+ break;
6174
+ case import_three18.MOUSE.ROTATE:
6175
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
6176
+ if (scope.enablePan === false) return;
6177
+ handleMouseDownPan(event);
6178
+ state = STATE.PAN;
6179
+ } else {
6180
+ if (scope.enableRotate === false) return;
6181
+ handleMouseDownRotate(event);
6182
+ state = STATE.ROTATE;
6183
+ }
6184
+ break;
6185
+ case import_three18.MOUSE.PAN:
6186
+ if (event.ctrlKey || event.metaKey || event.shiftKey) {
6187
+ if (scope.enableRotate === false) return;
6188
+ handleMouseDownRotate(event);
6189
+ state = STATE.ROTATE;
6190
+ } else {
6191
+ if (scope.enablePan === false) return;
6192
+ handleMouseDownPan(event);
6193
+ state = STATE.PAN;
6194
+ }
6195
+ break;
6196
+ default:
6197
+ state = STATE.NONE;
6198
+ }
6199
+ if (state !== STATE.NONE) {
6200
+ scope.dispatchEvent(_startEvent);
6201
+ }
6202
+ }
6203
+ function onMouseMove(event) {
6204
+ if (scope.enabled === false) return;
6205
+ switch (state) {
6206
+ case STATE.ROTATE:
6207
+ if (scope.enableRotate === false) return;
6208
+ handleMouseMoveRotate(event);
6209
+ break;
6210
+ case STATE.DOLLY:
6211
+ if (scope.enableZoom === false) return;
6212
+ handleMouseMoveDolly(event);
6213
+ break;
6214
+ case STATE.PAN:
6215
+ if (scope.enablePan === false) return;
6216
+ handleMouseMovePan(event);
6217
+ break;
6218
+ }
6219
+ }
6220
+ function onMouseUp(event) {
6221
+ handleMouseUp(event);
6222
+ scope.dispatchEvent(_endEvent);
6223
+ state = STATE.NONE;
6134
6224
  }
6135
- function handleMouseDownPan(event) {
6136
- panStart.set(event.clientX, event.clientY);
6225
+ function onMouseWheel(event) {
6226
+ if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE) return;
6227
+ event.preventDefault();
6228
+ scope.dispatchEvent(_startEvent);
6229
+ handleMouseWheel(event);
6230
+ scope.dispatchEvent(_endEvent);
6137
6231
  }
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();
6232
+ function onKeyDown(event) {
6233
+ if (scope.enabled === false || scope.enablePan === false) return;
6234
+ handleKeyDown(event);
6146
6235
  }
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());
6236
+ function onTouchStart(event) {
6237
+ trackPointer(event);
6238
+ switch (pointers.length) {
6239
+ case 1:
6240
+ switch (scope.touches.ONE) {
6241
+ case import_three18.TOUCH.ROTATE:
6242
+ if (scope.enableRotate === false) return;
6243
+ handleTouchStartRotate();
6244
+ state = STATE.TOUCH_ROTATE;
6245
+ break;
6246
+ case import_three18.TOUCH.PAN:
6247
+ if (scope.enablePan === false) return;
6248
+ handleTouchStartPan();
6249
+ state = STATE.TOUCH_PAN;
6250
+ break;
6251
+ default:
6252
+ state = STATE.NONE;
6253
+ }
6254
+ break;
6255
+ case 2:
6256
+ switch (scope.touches.TWO) {
6257
+ case import_three18.TOUCH.DOLLY_PAN:
6258
+ if (scope.enableZoom === false && scope.enablePan === false) return;
6259
+ handleTouchStartDollyPan();
6260
+ state = STATE.TOUCH_DOLLY_PAN;
6261
+ break;
6262
+ case import_three18.TOUCH.DOLLY_ROTATE:
6263
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
6264
+ handleTouchStartDollyRotate();
6265
+ state = STATE.TOUCH_DOLLY_ROTATE;
6266
+ break;
6267
+ default:
6268
+ state = STATE.NONE;
6269
+ }
6270
+ break;
6271
+ default:
6272
+ state = STATE.NONE;
6154
6273
  }
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());
6274
+ if (state !== STATE.NONE) {
6275
+ scope.dispatchEvent(_startEvent);
6172
6276
  }
6173
- scope.update();
6174
6277
  }
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;
6278
+ function onTouchMove(event) {
6279
+ trackPointer(event);
6280
+ switch (state) {
6281
+ case STATE.TOUCH_ROTATE:
6282
+ if (scope.enableRotate === false) return;
6283
+ handleTouchMoveRotate(event);
6284
+ scope.update();
6181
6285
  break;
6182
- case scope.keys.BOTTOM:
6183
- pan(0, -scope.keyPanSpeed);
6184
- needsUpdate = true;
6286
+ case STATE.TOUCH_PAN:
6287
+ if (scope.enablePan === false) return;
6288
+ handleTouchMovePan(event);
6289
+ scope.update();
6185
6290
  break;
6186
- case scope.keys.LEFT:
6187
- pan(scope.keyPanSpeed, 0);
6188
- needsUpdate = true;
6291
+ case STATE.TOUCH_DOLLY_PAN:
6292
+ if (scope.enableZoom === false && scope.enablePan === false) return;
6293
+ handleTouchMoveDollyPan(event);
6294
+ scope.update();
6189
6295
  break;
6190
- case scope.keys.RIGHT:
6191
- pan(-scope.keyPanSpeed, 0);
6192
- needsUpdate = true;
6296
+ case STATE.TOUCH_DOLLY_ROTATE:
6297
+ if (scope.enableZoom === false && scope.enableRotate === false) return;
6298
+ handleTouchMoveDollyRotate(event);
6299
+ scope.update();
6193
6300
  break;
6301
+ default:
6302
+ state = STATE.NONE;
6194
6303
  }
6195
- if (needsUpdate) {
6196
- event.preventDefault();
6197
- scope.update();
6304
+ }
6305
+ function onTouchEnd(event) {
6306
+ handleTouchEnd(event);
6307
+ scope.dispatchEvent(_endEvent);
6308
+ state = STATE.NONE;
6309
+ }
6310
+ function onContextMenu(event) {
6311
+ if (scope.enabled === false) return;
6312
+ event.preventDefault();
6313
+ }
6314
+ function addPointer(event) {
6315
+ pointers.push(event);
6316
+ }
6317
+ function removePointer(event) {
6318
+ delete pointerPositions[event.pointerId];
6319
+ for (let i = 0; i < pointers.length; i++) {
6320
+ if (pointers[i].pointerId == event.pointerId) {
6321
+ pointers.splice(i, 1);
6322
+ return;
6323
+ }
6198
6324
  }
6199
6325
  }
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);
6326
+ function trackPointer(event) {
6327
+ let position = pointerPositions[event.pointerId];
6328
+ if (position === void 0) {
6329
+ position = new import_three18.Vector2();
6330
+ pointerPositions[event.pointerId] = position;
6207
6331
  }
6332
+ position.set(event.pageX, event.pageY);
6208
6333
  }
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);
6334
+ function getSecondPointerPosition(event) {
6335
+ const pointer = event.pointerId === pointers[0].pointerId ? pointers[1] : pointers[0];
6336
+ return pointerPositions[pointer.pointerId];
6337
+ }
6338
+ scope.domElement.addEventListener("contextmenu", onContextMenu);
6339
+ scope.domElement.addEventListener("pointerdown", onPointerDown);
6340
+ scope.domElement.addEventListener("pointercancel", onPointerCancel);
6341
+ scope.domElement.addEventListener("wheel", onMouseWheel, { passive: false });
6342
+ this.update();
6343
+ }
6344
+ };
6345
+ var MapControls = class extends OrbitControls {
6346
+ constructor(object, domElement) {
6347
+ super(object, domElement);
6348
+ this.screenSpacePanning = false;
6349
+ this.mouseButtons.LEFT = import_three18.MOUSE.PAN;
6350
+ this.mouseButtons.RIGHT = import_three18.MOUSE.ROTATE;
6351
+ this.touches.ONE = import_three18.TOUCH.PAN;
6352
+ this.touches.TWO = import_three18.TOUCH.DOLLY_ROTATE;
6353
+ }
6354
+ };
6355
+
6356
+ // src/renderer/Renderer.ts
6357
+ var Renderer = class _Renderer {
6358
+ constructor(options) {
6359
+ this._dirty = true;
6360
+ this._resizeListener = void 0;
6361
+ this._disposed = false;
6362
+ this._debugHelpers = [];
6363
+ this._eventDispatchers = /* @__PURE__ */ new Map();
6364
+ this._changeListener = () => {
6365
+ this._dirty = true;
6366
+ };
6367
+ this.options = (0, import_ts_deepmerge9.default)({}, _Renderer.DEFAULT_OPTIONS, options ?? {});
6368
+ this._animationLoop = this.animate.bind(this);
6369
+ this._frameInterval = this.options.render.fpsLimit > 0 ? 1e3 / this.options.render.fpsLimit : void 0;
6370
+ this._scene = this.createScene();
6371
+ this._camera = this.createCamera();
6372
+ this._renderer = this.createRenderer();
6373
+ this._composer = this.createComposer();
6374
+ if (this.options.render.stats) {
6375
+ this._stats = new import_stats.default();
6376
+ document.body.appendChild(this._stats.dom);
6377
+ }
6378
+ this.init();
6379
+ this._controls = this.createControls();
6380
+ }
6381
+ static {
6382
+ this.DEFAULT_OPTIONS = (0, import_ts_deepmerge9.default)({}, {
6383
+ camera: {
6384
+ type: "perspective",
6385
+ near: 1,
6386
+ far: 5e3,
6387
+ perspective: {
6388
+ aspect: void 0,
6389
+ fov: 50
6390
+ },
6391
+ orthographic: {
6392
+ left: void 0,
6393
+ right: void 0,
6394
+ top: void 0,
6395
+ bottom: void 0
6396
+ },
6397
+ position: new import_three19.Vector3(50, 50, 50),
6398
+ lookingAt: new import_three19.Vector3(0, 0, 0)
6399
+ },
6400
+ render: {
6401
+ fpsLimit: 60,
6402
+ stats: false,
6403
+ antialias: true,
6404
+ shade: true,
6405
+ autoResize: true,
6406
+ renderAlways: false
6407
+ },
6408
+ composer: {
6409
+ enabled: true
6410
+ },
6411
+ controls: {
6412
+ enabled: false
6413
+ },
6414
+ debug: {
6415
+ grid: false,
6416
+ axes: false
6216
6417
  }
6418
+ });
6419
+ }
6420
+ //<editor-fold desc="INIT">
6421
+ createScene() {
6422
+ return new MineRenderScene();
6423
+ }
6424
+ createCamera() {
6425
+ switch (this.options.camera.type) {
6426
+ case "perspective":
6427
+ default:
6428
+ return new import_three19.PerspectiveCamera(
6429
+ this.options.camera.perspective.fov,
6430
+ this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
6431
+ this.options.camera.near,
6432
+ this.options.camera.far
6433
+ );
6434
+ case "orthographic":
6435
+ return new import_three19.OrthographicCamera(
6436
+ this.options.camera.orthographic.left ?? this.viewWidth / -2,
6437
+ this.options.camera.orthographic.right ?? this.viewWidth / 2,
6438
+ this.options.camera.orthographic.top ?? this.viewHeight / 2,
6439
+ this.options.camera.orthographic.bottom ?? this.viewHeight / -2,
6440
+ this.options.camera.near,
6441
+ this.options.camera.far
6442
+ );
6217
6443
  }
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);
6444
+ }
6445
+ createRenderer() {
6446
+ const renderer = new import_three19.WebGLRenderer({
6447
+ antialias: this.options.render.antialias,
6448
+ alpha: true,
6449
+ powerPreference: "high-performance",
6450
+ depth: true
6451
+ });
6452
+ renderer.setClearColor(0, 0);
6453
+ renderer.shadowMap.enabled = true;
6454
+ renderer.shadowMap.type = import_three19.PCFSoftShadowMap;
6455
+ renderer.outputColorSpace = import_three19.SRGBColorSpace;
6456
+ renderer.setSize(this.viewWidth, this.viewHeight);
6457
+ return renderer;
6458
+ }
6459
+ createComposer() {
6460
+ if (!this.options.composer.enabled) return void 0;
6461
+ const composer = new import_postprocessing.EffectComposer(this.renderer);
6462
+ composer.setSize(this.viewWidth, this.viewHeight);
6463
+ composer.addPass(new import_postprocessing.RenderPass(this.scene, this.camera));
6464
+ return composer;
6465
+ }
6466
+ createControls() {
6467
+ if (!this.options.controls?.enabled) return void 0;
6468
+ const position = this.camera.position.clone();
6469
+ const controls = new OrbitControls(this.camera, this.renderer.domElement);
6470
+ this.camera.position.copy(position);
6471
+ const target = this.options.camera.lookingAt;
6472
+ if (isVector3(target)) {
6473
+ controls.target.copy(target);
6474
+ } else if (isTripleArray(target)) {
6475
+ controls.target.set(target[0], target[1], target[2]);
6476
+ }
6477
+ controls.update();
6478
+ controls.saveState();
6479
+ this.registerEventDispatcher(controls);
6480
+ return controls;
6481
+ }
6482
+ //</editor-fold>
6483
+ init() {
6484
+ if (this._disposed) return;
6485
+ if (typeof window["__THREE_DEVTOOLS__"] !== "undefined") {
6486
+ window["__THREE_DEVTOOLS__"].dispatchEvent(new CustomEvent("observe", { detail: this.scene }));
6223
6487
  }
6224
- function handleTouchStartDollyPan() {
6225
- if (scope.enableZoom) handleTouchStartDolly();
6226
- if (scope.enablePan) handleTouchStartPan();
6488
+ if (this.options.debug.grid) {
6489
+ const gridHelper = new import_three19.GridHelper(128, 16);
6490
+ this._debugHelpers.push(gridHelper);
6491
+ this.scene.add(gridHelper);
6492
+ const gridHelper2 = new import_three19.GridHelper(128, 16);
6493
+ this._debugHelpers.push(gridHelper2);
6494
+ gridHelper2.rotation.x = 90 * (Math.PI / 180);
6495
+ this.scene.add(gridHelper2);
6496
+ const gridHelper3 = new import_three19.GridHelper(128, 16);
6497
+ this._debugHelpers.push(gridHelper3);
6498
+ gridHelper3.rotation.z = 90 * (Math.PI / 180);
6499
+ this.scene.add(gridHelper3);
6227
6500
  }
6228
- function handleTouchStartDollyRotate() {
6229
- if (scope.enableZoom) handleTouchStartDolly();
6230
- if (scope.enableRotate) handleTouchStartRotate();
6501
+ if (this.options.debug.axes) {
6502
+ const axesHelper = new import_three19.AxesHelper(64);
6503
+ this._debugHelpers.push(axesHelper);
6504
+ this.scene.add(axesHelper);
6231
6505
  }
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);
6506
+ if (this.options.camera.position) {
6507
+ if (isVector3(this.options.camera.position)) {
6508
+ this.camera.position.set(this.options.camera.position.x, this.options.camera.position.y, this.options.camera.position.z);
6509
+ } else if (isTripleArray(this.options.camera.position)) {
6510
+ this.camera.position.set(this.options.camera.position[0], this.options.camera.position[1], this.options.camera.position[2]);
6240
6511
  }
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
6512
  }
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);
6513
+ if (this.options.camera.lookingAt) {
6514
+ if (isVector3(this.options.camera.lookingAt)) {
6515
+ this.camera.lookAt(this.options.camera.lookingAt);
6516
+ } else if (isTripleArray(this.options.camera.lookingAt)) {
6517
+ this.camera.lookAt(this.options.camera.lookingAt[0], this.options.camera.lookingAt[1], this.options.camera.lookingAt[2]);
6255
6518
  }
6256
- panDelta.subVectors(panEnd, panStart).multiplyScalar(scope.panSpeed);
6257
- pan(panDelta.x, panDelta.y);
6258
- panStart.copy(panEnd);
6259
6519
  }
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);
6520
+ if (this.options.render.autoResize && !this._resizeListener) {
6521
+ this._resizeListener = () => {
6522
+ this.resize(this.viewWidth, this.viewHeight);
6523
+ };
6524
+ window.addEventListener("resize", this._resizeListener);
6269
6525
  }
6270
- function handleTouchMoveDollyPan(event) {
6271
- if (scope.enableZoom) handleTouchMoveDolly(event);
6272
- if (scope.enablePan) handleTouchMovePan(event);
6526
+ }
6527
+ get element() {
6528
+ return this._element;
6529
+ }
6530
+ appendTo(element) {
6531
+ if (this._disposed) return;
6532
+ this._element = element;
6533
+ this._element.appendChild(this.renderer.domElement);
6534
+ if (this.viewWidth == 0) {
6535
+ console.warn("0 element width");
6273
6536
  }
6274
- function handleTouchMoveDollyRotate(event) {
6275
- if (scope.enableZoom) handleTouchMoveDolly(event);
6276
- if (scope.enableRotate) handleTouchMoveRotate(event);
6537
+ if (this.viewHeight == 0) {
6538
+ console.warn("0 element height");
6277
6539
  }
6278
- function handleTouchEnd() {
6540
+ this.resize(this.viewWidth, this.viewHeight);
6541
+ }
6542
+ /**
6543
+ * Redraws when the dispatcher emits the selected event. Registering the same pair twice has no effect.
6544
+ * The renderer removes its listener on disposal; the caller retains ownership of the dispatcher.
6545
+ */
6546
+ registerEventDispatcher(dispatcher, changeEvent2 = "change") {
6547
+ if (this._disposed) return;
6548
+ let events = this._eventDispatchers.get(dispatcher);
6549
+ if (!events) {
6550
+ events = /* @__PURE__ */ new Set();
6551
+ this._eventDispatchers.set(dispatcher, events);
6279
6552
  }
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
- }
6553
+ if (events.has(changeEvent2)) return;
6554
+ events.add(changeEvent2);
6555
+ dispatcher.addEventListener(changeEvent2, this._changeListener);
6556
+ }
6557
+ resize(width, height) {
6558
+ if (this._disposed) return;
6559
+ if (isPerspectiveCamera(this.camera)) {
6560
+ this.camera.aspect = width / height;
6561
+ this.camera.updateProjectionMatrix();
6562
+ } else if (isOrthographicCamera(this.camera)) {
6563
+ this.camera.left = width / -2;
6564
+ this.camera.right = width / 2;
6565
+ this.camera.top = height / 2;
6566
+ this.camera.bottom = height / -2;
6567
+ this.camera.updateProjectionMatrix();
6293
6568
  }
6294
- function onPointerMove(event) {
6295
- if (scope.enabled === false) return;
6296
- if (event.pointerType === "touch") {
6297
- onTouchMove(event);
6298
- } else {
6299
- onMouseMove(event);
6300
- }
6569
+ this.renderer.setSize(width, height);
6570
+ this.composer?.setSize(width, height);
6571
+ this._dirty = true;
6572
+ }
6573
+ //<editor-fold desc="RENDER">
6574
+ get dirty() {
6575
+ return this._dirty || this.scene.dirty;
6576
+ }
6577
+ set dirty(dirty) {
6578
+ this._dirty = dirty;
6579
+ this.scene.dirty = dirty;
6580
+ }
6581
+ start() {
6582
+ if (this._disposed) return;
6583
+ this.stop();
6584
+ this.renderer.setAnimationLoop(this._animationLoop);
6585
+ }
6586
+ stop() {
6587
+ if (this._disposed) return;
6588
+ this.renderer.setAnimationLoop(null);
6589
+ this._nextFrameTime = void 0;
6590
+ }
6591
+ /**
6592
+ * Stops rendering and releases owned resources. Repeated calls have no effect, and a disposed
6593
+ * renderer cannot be restarted. Scene objects are detached; shared assets and caller-owned
6594
+ * controls must be managed by their owners.
6595
+ */
6596
+ dispose() {
6597
+ if (this._disposed) return;
6598
+ this.stop();
6599
+ this._disposed = true;
6600
+ if (this._resizeListener) {
6601
+ window.removeEventListener("resize", this._resizeListener);
6602
+ this._resizeListener = void 0;
6603
+ }
6604
+ for (const [dispatcher, events] of this._eventDispatchers) {
6605
+ for (const event of events) {
6606
+ dispatcher.removeEventListener(event, this._changeListener);
6607
+ }
6608
+ }
6609
+ this._eventDispatchers.clear();
6610
+ this._stats?.dom.remove();
6611
+ this._stats = void 0;
6612
+ this.renderer.domElement.remove();
6613
+ this._element = void 0;
6614
+ if (this._controls) {
6615
+ const controls = this._controls;
6616
+ this._controls = void 0;
6617
+ controls.enabled = false;
6618
+ controls.dispose();
6619
+ }
6620
+ this.scene.clear();
6621
+ for (const helper of this._debugHelpers) {
6622
+ helper.geometry.dispose();
6623
+ const materials = Array.isArray(helper.material) ? helper.material : [helper.material];
6624
+ for (const material of materials) {
6625
+ material.dispose();
6626
+ }
6627
+ }
6628
+ this._debugHelpers.length = 0;
6629
+ this.composer?.dispose();
6630
+ this.renderer.dispose();
6631
+ this.renderer.forceContextLoss();
6632
+ }
6633
+ animate(t = performance.now()) {
6634
+ if (this._disposed) return;
6635
+ if (this._controls?.enabled) {
6636
+ this._controls.update();
6637
+ }
6638
+ if (this._disposed) return;
6639
+ if (!this.dirty && !this.options.render.renderAlways) return;
6640
+ const interval = this._frameInterval;
6641
+ if (interval) {
6642
+ const next = this._nextFrameTime;
6643
+ if (next !== void 0 && t + 0.1 < next) return;
6644
+ this._nextFrameTime = next !== void 0 && t - next < interval ? next + interval : t + interval;
6301
6645
  }
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
- }
6646
+ if (this._stats) {
6647
+ this._stats.begin();
6315
6648
  }
6316
- function onPointerCancel(event) {
6317
- removePointer(event);
6649
+ if (this.options.composer.enabled && this.composer) {
6650
+ this.composer.render();
6651
+ } else {
6652
+ this.renderer.render(this.scene, this.camera);
6318
6653
  }
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;
6654
+ this.dirty = false;
6655
+ if (this._stats) {
6656
+ this._stats.end();
6657
+ }
6658
+ }
6659
+ //</editor-fold>
6660
+ toImage() {
6661
+ return this.renderer.domElement.toDataURL();
6662
+ }
6663
+ ///
6664
+ get attachedToBody() {
6665
+ return this.element === document.body;
6666
+ }
6667
+ get viewWidth() {
6668
+ return this.attachedToBody ? window.innerWidth : this.element?.offsetWidth || 0;
6669
+ }
6670
+ get viewHeight() {
6671
+ return this.attachedToBody ? window.innerHeight : this.element?.offsetHeight || 0;
6672
+ }
6673
+ get scene() {
6674
+ return this._scene;
6675
+ }
6676
+ get camera() {
6677
+ return this._camera;
6678
+ }
6679
+ get renderer() {
6680
+ return this._renderer;
6681
+ }
6682
+ get composer() {
6683
+ return this._composer;
6684
+ }
6685
+ /** Renderer-owned controls, or undefined when disabled at construction or after disposal. */
6686
+ get controls() {
6687
+ return this._controls;
6688
+ }
6689
+ ///
6690
+ };
6691
+
6692
+ // src/skin/Skins.ts
6693
+ var Skins = class {
6694
+ //<editor-fold desc="Skins">
6695
+ static async fromUuidOrUsername(uuidOrUsername) {
6696
+ if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
6697
+ return this.fromUuid(uuidOrUsername);
6698
+ }
6699
+ return this.fromUsername(uuidOrUsername);
6700
+ }
6701
+ static async fromUuid(uuid) {
6702
+ return this.getSkinProxySkinUrl(uuid);
6703
+ }
6704
+ static async fromUsername(username) {
6705
+ return this.usernameToUuid(username).then((uuid) => {
6706
+ if (uuid) {
6707
+ return this.fromUuid(uuid);
6364
6708
  }
6365
- if (state !== STATE.NONE) {
6366
- scope.dispatchEvent(_startEvent);
6709
+ return void 0;
6710
+ });
6711
+ }
6712
+ static async fromMineSkin(mineskinId) {
6713
+ return this.getMineSkin(mineskinId).then((mineskin) => {
6714
+ if (mineskin) {
6715
+ return mineskin["data"]["texture"]["value"]["urls"]["skins"];
6367
6716
  }
6717
+ return void 0;
6718
+ });
6719
+ }
6720
+ //</editor-fold>
6721
+ //<editor-fold desc="Capes">
6722
+ static async capeFromUuidOrUsername(uuidOrUsername) {
6723
+ if (uuidOrUsername.length === 32 || uuidOrUsername.length === 36) {
6724
+ return this.capeFromUuid(uuidOrUsername);
6368
6725
  }
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;
6726
+ return this.capeFromUsername(uuidOrUsername);
6727
+ }
6728
+ static async capeFromUuid(uuid) {
6729
+ return this.getSkinProxyCapeUrl(uuid);
6730
+ }
6731
+ static async capeFromUsername(username) {
6732
+ return this.usernameToUuid(username).then((uuid) => {
6733
+ if (uuid) {
6734
+ return this.capeFromUuid(uuid);
6384
6735
  }
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;
6736
+ return void 0;
6737
+ });
6738
+ }
6739
+ static async capeFromCapesDev(uuid, capeType = "minecraft") {
6740
+ return this.getCapesDev(uuid, capeType).then((cape) => {
6741
+ if (cape) {
6742
+ return cape?.stillImageUrl;
6439
6743
  }
6440
- if (state !== STATE.NONE) {
6441
- scope.dispatchEvent(_startEvent);
6744
+ return void 0;
6745
+ });
6746
+ }
6747
+ //</editor-fold>
6748
+ //<editor-fold desc="Helpers">
6749
+ static async usernameToUuid(username) {
6750
+ return this.usernameToUuidSkinProxy(username);
6751
+ }
6752
+ static async usernameToUuidSkinProxy(username) {
6753
+ return Requests.genericRequest({
6754
+ baseURL: "https://minecraft-skin-proxy.inventive.workers.dev",
6755
+ url: "/uuid/" + username
6756
+ }).then((res) => {
6757
+ if (res.status === 200) {
6758
+ return res.data["id"];
6442
6759
  }
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;
6760
+ return void 0;
6761
+ }).catch((err) => {
6762
+ console.warn(err);
6763
+ return void 0;
6764
+ });
6765
+ }
6766
+ static async usernameToUuidMineTools(username) {
6767
+ return Requests.genericRequest({
6768
+ baseURL: "https://api.minetools.eu",
6769
+ url: "/uuid/" + username
6770
+ }).then((res) => {
6771
+ if (res.status === 200) {
6772
+ return res.data["id"];
6469
6773
  }
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
- }
6774
+ return void 0;
6775
+ }).catch((err) => {
6776
+ console.warn(err);
6777
+ return void 0;
6778
+ });
6779
+ }
6780
+ static async getProfileFromMinetools(uuid) {
6781
+ return Requests.genericRequest({
6782
+ baseURL: "https://api.minetools.eu",
6783
+ url: "/profile/" + uuid
6784
+ }).then((res) => {
6785
+ if (res.status === 200) {
6786
+ return res.data;
6490
6787
  }
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;
6788
+ });
6789
+ }
6790
+ static async getMineSkin(mineskinId) {
6791
+ return Requests.genericRequest({
6792
+ baseURL: "https://api.mineskin.org",
6793
+ url: "/get/uuid/" + mineskinId
6794
+ }).then((res) => {
6795
+ if (res.status === 200) {
6796
+ return res.data;
6497
6797
  }
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();
6798
+ return void 0;
6799
+ }).catch((err) => {
6800
+ console.warn(err);
6801
+ return void 0;
6802
+ });
6509
6803
  }
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;
6804
+ static async getCapesDev(uuid, type = "all") {
6805
+ return Requests.genericRequest({
6806
+ baseURL: "https://api.capes.dev",
6807
+ url: "/load/" + uuid + "/" + type
6808
+ }).then((res) => {
6809
+ if (res.status === 200) {
6810
+ return res.data;
6811
+ }
6812
+ return void 0;
6813
+ }).catch((err) => {
6814
+ console.warn(err);
6815
+ return void 0;
6816
+ });
6817
+ }
6818
+ static getCrafatarSkinUrl(uuid) {
6819
+ return "https://crafatar.com/skins/" + uuid;
6519
6820
  }
6821
+ static getCrafatarCapeUrl(uuid) {
6822
+ return "https://crafatar.com/capes/" + uuid;
6823
+ }
6824
+ static getMcHeadsSkinUrl(uuid) {
6825
+ return "https://mc-heads.net/skin/" + uuid;
6826
+ }
6827
+ static getMineSkinPlayerSkinUrl(uuid) {
6828
+ return "https://mineskin.org/skin/player/" + uuid;
6829
+ }
6830
+ static getSkinProxySkinUrl(uuid) {
6831
+ return "https://minecraft-skin-proxy.inventive.workers.dev/skin/" + uuid;
6832
+ }
6833
+ static getSkinProxyCapeUrl(uuid) {
6834
+ return "https://minecraft-skin-proxy.inventive.workers.dev/cape/" + uuid;
6835
+ }
6836
+ //</editor-fold>
6520
6837
  };
6521
6838
 
6522
6839
  // src/world/Chunk.ts
@@ -6579,7 +6896,7 @@ var MineRenderWorld = class {
6579
6896
  console.log("CHUNKS", this._chunks);
6580
6897
  for (let chunk of this._chunks.values()) {
6581
6898
  console.log("dispose chunk", chunk);
6582
- await (chunk == null ? void 0 : chunk.dispose());
6899
+ await chunk?.dispose();
6583
6900
  }
6584
6901
  this._chunks.clear();
6585
6902
  }
@@ -6809,6 +7126,7 @@ var Chunk = class _Chunk {
6809
7126
  OrbitControls,
6810
7127
  PersistentCache,
6811
7128
  Renderer,
7129
+ RequestError,
6812
7130
  Requests,
6813
7131
  SKIN_PARTS,
6814
7132
  SceneInspector,