minerender 2.1.0-alpha.7 → 2.1.0-alpha.9

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.
@@ -65,6 +65,7 @@ declare abstract class PersistentCache<B = unknown> {
65
65
  static open(name: string): PersistentCache;
66
66
  protected constructor(backing: B);
67
67
  abstract get<T>(key: string): Promise<T>;
68
+ /** Loads a missing entry and stores only non-nullish results. */
68
69
  getOrLoad<T>(key: string, loader: (key: string) => Promise<T>): Promise<T>;
69
70
  abstract put<T>(key: string, value: T): Promise<T>;
70
71
  abstract delete<T>(key: string): Promise<void>;
@@ -853,6 +854,7 @@ declare class EntityObject extends SceneObject {
853
854
  constructor(entity: EntityModel, options?: Partial<EntityObjectOptions>);
854
855
  init(): Promise<void>;
855
856
  dispose(): void;
857
+ private get textureKey();
856
858
  protected loadTextures(): Promise<void>;
857
859
  protected createMeshes(force?: boolean): void;
858
860
  protected applyTextures(): Promise<void>;
@@ -1213,6 +1215,10 @@ declare class Caching {
1213
1215
  static readonly mergedModelCache: AsyncLoadingCache<CacheKey, Model>;
1214
1216
  static readonly modelTextureAtlasCache: AsyncLoadingCache<CacheKey, TextureAtlas>;
1215
1217
  static readonly blockStateCache: AsyncLoadingCache<CacheKey, BlockState>;
1218
+ static readonly listAssetCache: AsyncLoadingCache<CacheKey, ListAsset>;
1219
+ static readonly defaultBlockStatesCache: AsyncLoadingCache<CacheKey, DefaultBlockStates>;
1220
+ static readonly entityModelsCache: AsyncLoadingCache<CacheKey, EntityModels>;
1221
+ private static createAssetCache;
1216
1222
  /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */
1217
1223
  private static get all();
1218
1224
  static clear(): void;
@@ -1512,6 +1518,9 @@ declare class Skins {
1512
1518
  }
1513
1519
 
1514
1520
  declare class TextureLoader {
1521
+ private static readonly failedTextures;
1522
+ /** Reports whether image loading failed, so cached textures can be retried. */
1523
+ static hasFailed(texture: Texture): boolean;
1515
1524
  protected static createTexture(): Texture;
1516
1525
  static loadInBackground(src: string, format?: PixelFormat, rotation?: number): Texture;
1517
1526
  static load(src: string, format?: PixelFormat, rotation?: number): Texture;
@@ -65,6 +65,7 @@ declare abstract class PersistentCache<B = unknown> {
65
65
  static open(name: string): PersistentCache;
66
66
  protected constructor(backing: B);
67
67
  abstract get<T>(key: string): Promise<T>;
68
+ /** Loads a missing entry and stores only non-nullish results. */
68
69
  getOrLoad<T>(key: string, loader: (key: string) => Promise<T>): Promise<T>;
69
70
  abstract put<T>(key: string, value: T): Promise<T>;
70
71
  abstract delete<T>(key: string): Promise<void>;
@@ -853,6 +854,7 @@ declare class EntityObject extends SceneObject {
853
854
  constructor(entity: EntityModel, options?: Partial<EntityObjectOptions>);
854
855
  init(): Promise<void>;
855
856
  dispose(): void;
857
+ private get textureKey();
856
858
  protected loadTextures(): Promise<void>;
857
859
  protected createMeshes(force?: boolean): void;
858
860
  protected applyTextures(): Promise<void>;
@@ -1213,6 +1215,10 @@ declare class Caching {
1213
1215
  static readonly mergedModelCache: AsyncLoadingCache<CacheKey, Model>;
1214
1216
  static readonly modelTextureAtlasCache: AsyncLoadingCache<CacheKey, TextureAtlas>;
1215
1217
  static readonly blockStateCache: AsyncLoadingCache<CacheKey, BlockState>;
1218
+ static readonly listAssetCache: AsyncLoadingCache<CacheKey, ListAsset>;
1219
+ static readonly defaultBlockStatesCache: AsyncLoadingCache<CacheKey, DefaultBlockStates>;
1220
+ static readonly entityModelsCache: AsyncLoadingCache<CacheKey, EntityModels>;
1221
+ private static createAssetCache;
1216
1222
  /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */
1217
1223
  private static get all();
1218
1224
  static clear(): void;
@@ -1512,6 +1518,9 @@ declare class Skins {
1512
1518
  }
1513
1519
 
1514
1520
  declare class TextureLoader {
1521
+ private static readonly failedTextures;
1522
+ /** Reports whether image loading failed, so cached textures can be retried. */
1523
+ static hasFailed(texture: Texture): boolean;
1515
1524
  protected static createTexture(): Texture;
1516
1525
  static loadInBackground(src: string, format?: PixelFormat, rotation?: number): Texture;
1517
1526
  static load(src: string, format?: PixelFormat, rotation?: number): Texture;
@@ -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({
@@ -309,11 +301,14 @@ var _PersistentCache = class _PersistentCache {
309
301
  static open(name) {
310
302
  return Env.provider.openCache(name, _PersistentCache.VERSION);
311
303
  }
304
+ /** Loads a missing entry and stores only non-nullish results. */
312
305
  async getOrLoad(key, loader) {
313
306
  let v = await this.get(key);
314
307
  if (typeof v === "undefined" || v === null) {
315
308
  v = await loader(key);
316
- await this.put(key, v);
309
+ if (typeof v !== "undefined" && v !== null) {
310
+ await this.put(key, v);
311
+ }
317
312
  }
318
313
  return v;
319
314
  }
@@ -510,7 +505,10 @@ function serializeMeshKey(key) {
510
505
  // src/cache/Caching.ts
511
506
  var import_loading_cache = require("@inventivetalent/loading-cache");
512
507
  var import_time = require("@inventivetalent/time");
513
- var Caching = class {
508
+ var _Caching = class _Caching {
509
+ static createAssetCache() {
510
+ 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();
511
+ }
514
512
  /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */
515
513
  static get all() {
516
514
  return [
@@ -527,7 +525,10 @@ var Caching = class {
527
525
  this.rawModelCache,
528
526
  this.mergedModelCache,
529
527
  this.modelTextureAtlasCache,
530
- this.blockStateCache
528
+ this.blockStateCache,
529
+ this.listAssetCache,
530
+ this.defaultBlockStatesCache,
531
+ this.entityModelsCache
531
532
  ];
532
533
  }
533
534
  static clear() {
@@ -553,20 +554,24 @@ var Caching = class {
553
554
  };
554
555
  }
555
556
  };
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();
557
+ _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();
558
+ _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();
559
+ _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();
560
+ _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();
561
+ _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();
562
+ _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();
563
+ _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();
564
+ _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();
565
+ _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();
566
+ _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();
567
+ _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();
568
+ _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();
569
+ _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();
570
+ _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();
571
+ _Caching.listAssetCache = _Caching.createAssetCache();
572
+ _Caching.defaultBlockStatesCache = _Caching.createAssetCache();
573
+ _Caching.entityModelsCache = _Caching.createAssetCache();
574
+ var Caching = _Caching;
570
575
 
571
576
  // src/Geometries.ts
572
577
  var Geometries = class _Geometries {
@@ -874,29 +879,41 @@ var ImageLoader = class _ImageLoader {
874
879
  static async loadAsync(src) {
875
880
  return new Promise((resolve, reject) => {
876
881
  const image = this._createImage();
877
- image.src = src;
878
882
  image.onload = () => resolve(image);
879
- image.onerror = (err) => reject(err);
883
+ image.onerror = (err) => reject(err instanceof Error ? err : new Error("Failed to decode image"));
884
+ image.src = src;
880
885
  });
881
886
  }
882
887
  static loadElement(src, onload, onerr) {
883
888
  const image = this._createImage();
884
- image.src = src;
885
889
  if (onload)
886
890
  image.onload = onload;
887
891
  if (onerr)
888
892
  image.onerror = onerr;
893
+ image.src = src;
889
894
  return image;
890
895
  }
891
896
  static async loadData(src) {
892
897
  console.debug(p2, "loadData", src);
893
- return await this.infoToData(await this.getInfo(src));
898
+ const image = await this.loadCanvasData(src);
899
+ return image.data.getImageData(0, 0, image.width, image.height);
894
900
  }
895
901
  static async loadCanvasData(src) {
896
- return await this.infoToCanvasData(await this.getInfo(src));
902
+ const keyStr = serializeImageKey({ src });
903
+ const info = this.getInfo(src);
904
+ const cached = Caching.rawImageCache.getIfPresent(keyStr);
905
+ try {
906
+ return await this.infoToCanvasData(await info);
907
+ } catch (err) {
908
+ if (cached && Caching.rawImageCache.getIfPresent(keyStr) === cached) {
909
+ Caching.rawImageCache.invalidate(keyStr);
910
+ }
911
+ throw err;
912
+ }
897
913
  }
898
914
  static async infoToCanvasData(info) {
899
- const image = await _ImageLoader.loadAsync(info.src);
915
+ const type = info.type === "jpg" ? "jpeg" : info.type ?? "png";
916
+ const image = await _ImageLoader.loadAsync(`data:image/${type};base64,${info.data.toString("base64")}`);
900
917
  const canvas = createCanvas2(info.width, info.height);
901
918
  const context = canvas.getContext("2d");
902
919
  context.drawImage(image, 0, 0);
@@ -907,11 +924,8 @@ var ImageLoader = class _ImageLoader {
907
924
  };
908
925
  }
909
926
  static async infoToData(info) {
910
- const image = await _ImageLoader.loadAsync(info.src);
911
- const canvas = createCanvas2(info.width, info.height);
912
- const context = canvas.getContext("2d");
913
- context.drawImage(image, 0, 0);
914
- return context.getImageData(0, 0, canvas.width, canvas.height);
927
+ const image = await this.infoToCanvasData(info);
928
+ return image.data.getImageData(0, 0, image.width, image.height);
915
929
  }
916
930
  static async getData(src) {
917
931
  const keyStr = serializeImageKey({ src });
@@ -926,13 +940,17 @@ var ImageLoader = class _ImageLoader {
926
940
  });
927
941
  }
928
942
  static async processResponse(response) {
929
- const src = response.config.url;
943
+ var _a;
944
+ const src = (_a = response.config) == null ? void 0 : _a.url;
930
945
  const data = import_buffer.Buffer.from(response.data);
931
946
  const { width, height, type } = Env.provider.imageSize(data);
947
+ if (!width || !height) {
948
+ throw new Error("Invalid or unsupported image dimensions");
949
+ }
932
950
  return {
933
951
  src,
934
- width: width || 0,
935
- height: height || 0,
952
+ width,
953
+ height,
936
954
  type,
937
955
  data
938
956
  };
@@ -949,15 +967,7 @@ var ImageLoader = class _ImageLoader {
949
967
  return Requests.genericRequest({
950
968
  url: src,
951
969
  responseType: "arraybuffer"
952
- }).then(this.processResponse).catch((err) => {
953
- return {
954
- src,
955
- width: 0,
956
- height: 0,
957
- type: void 0,
958
- data: import_buffer.Buffer.from([0])
959
- };
960
- });
970
+ }).then(this.processResponse);
961
971
  }
962
972
  static async getInfo(src) {
963
973
  const keyStr = serializeImageKey({ src });
@@ -979,16 +989,22 @@ var ImageLoader = class _ImageLoader {
979
989
 
980
990
  // src/texture/TextureLoader.ts
981
991
  var TextureLoader = class {
992
+ /** Reports whether image loading failed, so cached textures can be retried. */
993
+ static hasFailed(texture) {
994
+ return this.failedTextures.has(texture);
995
+ }
982
996
  static createTexture() {
983
997
  return new import_three4.Texture();
984
998
  }
985
999
  static loadInBackground(src, format = import_three4.RGBAFormat, rotation = 0) {
986
1000
  const texture = this.createTexture();
987
1001
  texture.colorSpace = THREE.SRGBColorSpace;
988
- const image = ImageLoader.loadElement(src);
989
- image.onload = function() {
1002
+ const image = ImageLoader.loadElement(src, () => {
990
1003
  texture.needsUpdate = true;
991
- };
1004
+ }, (error) => {
1005
+ this.failedTextures.add(texture);
1006
+ console.warn("Failed to load texture", src, error);
1007
+ });
992
1008
  texture.image = image;
993
1009
  texture.format = format;
994
1010
  texture.rotation = rotation;
@@ -998,14 +1014,18 @@ var TextureLoader = class {
998
1014
  const texture = new import_three4.Texture();
999
1015
  texture.colorSpace = THREE.SRGBColorSpace;
1000
1016
  ImageLoader.getData(src).then((image) => {
1001
- texture.needsUpdate = true;
1002
1017
  texture.image = image;
1018
+ texture.needsUpdate = true;
1019
+ }).catch((error) => {
1020
+ this.failedTextures.add(texture);
1021
+ console.warn("Failed to load texture", src, error);
1003
1022
  });
1004
1023
  texture.format = format;
1005
1024
  texture.rotation = rotation;
1006
1025
  return Textures.initTextureProps(texture);
1007
1026
  }
1008
1027
  };
1028
+ TextureLoader.failedTextures = /* @__PURE__ */ new WeakSet();
1009
1029
 
1010
1030
  // src/texture/Textures.ts
1011
1031
  var THREE2 = __toESM(require("three"));
@@ -1029,6 +1049,10 @@ var Textures = class _Textures {
1029
1049
  }
1030
1050
  static getImage(key) {
1031
1051
  const keyStr = serializeTextureKey(key);
1052
+ const cached = Caching.textureCache.peek(keyStr);
1053
+ if (cached && TextureLoader.hasFailed(cached)) {
1054
+ Caching.textureCache.invalidate(keyStr);
1055
+ }
1032
1056
  return Caching.textureCache.get(keyStr, (k) => {
1033
1057
  return _Textures.createImage(key);
1034
1058
  });
@@ -1172,7 +1196,12 @@ var _Materials = class _Materials {
1172
1196
  return this.createBasicCanvasMaterial(canvas, transparent, shade);
1173
1197
  }
1174
1198
  static getImage(key) {
1199
+ var _a;
1175
1200
  const keyStr = serializeMaterialKey(key);
1201
+ const map = (_a = Caching.materialCache.peek(keyStr)) == null ? void 0 : _a.map;
1202
+ if (map && TextureLoader.hasFailed(map)) {
1203
+ Caching.materialCache.invalidate(keyStr);
1204
+ }
1176
1205
  return Caching.materialCache.get(keyStr, (k) => {
1177
1206
  return _Materials.createImage(key);
1178
1207
  });
@@ -1326,9 +1355,6 @@ var ModelMerger = class {
1326
1355
  }
1327
1356
  };
1328
1357
 
1329
- // src/assets/Models.ts
1330
- var import_typescript_memoize = require("typescript-memoize");
1331
-
1332
1358
  // src/assets/source/parser/AssetParsers.ts
1333
1359
  var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1334
1360
  AssetParser2["MODEL"] = "model";
@@ -1342,14 +1368,14 @@ var AssetParser = /* @__PURE__ */ ((AssetParser2) => {
1342
1368
  })(AssetParser || {});
1343
1369
 
1344
1370
  // src/assets/Models.ts
1345
- var _Models = class _Models {
1371
+ var Models = class _Models {
1346
1372
  // opened lazily: touching the store at import time would hit IndexedDB/disk just for loading
1347
1373
  // the library, and would require an EnvProvider before any entry has had a chance to register
1348
1374
  static get PERSISTENT_CACHE() {
1349
1375
  return this._persistentCache ??= PersistentCache.open("minerender-models");
1350
1376
  }
1351
1377
  static async getItemList() {
1352
- return AssetLoader.get(new AssetKey(
1378
+ const key = new AssetKey(
1353
1379
  DEFAULT_NAMESPACE,
1354
1380
  "_list",
1355
1381
  "models",
@@ -1357,7 +1383,10 @@ var _Models = class _Models {
1357
1383
  "assets",
1358
1384
  ".json",
1359
1385
  DEFAULT_ROOT
1360
- ), "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 == null ? void 0 : r.files) ?? []);
1361
1390
  }
1362
1391
  static async loadAndMerge(key) {
1363
1392
  const model = await this.getRaw(key);
@@ -1404,19 +1433,15 @@ var _Models = class _Models {
1404
1433
  return this.PERSISTENT_CACHE.clear();
1405
1434
  }
1406
1435
  };
1407
- __decorateClass([
1408
- (0, import_typescript_memoize.Memoize)()
1409
- ], _Models, "getItemList", 1);
1410
- var Models = _Models;
1411
1436
 
1412
1437
  // src/assets/BlockStates.ts
1413
- var import_typescript_memoize2 = require("typescript-memoize");
1414
1438
  var BlockStates = class {
1415
1439
  static get PERSISTENT_CACHE() {
1416
1440
  return this._persistentCache ??= PersistentCache.open("minerender-blockstates");
1417
1441
  }
1442
+ // BlockState names are hardcoded
1418
1443
  static async getList() {
1419
- return AssetLoader.get(new AssetKey(
1444
+ const key = new AssetKey(
1420
1445
  DEFAULT_NAMESPACE,
1421
1446
  "_list",
1422
1447
  "blockstates",
@@ -1424,11 +1449,16 @@ var BlockStates = class {
1424
1449
  "assets",
1425
1450
  ".json",
1426
1451
  DEFAULT_ROOT
1427
- ), "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 == null ? void 0 : r.files) ?? []);
1428
1456
  }
1429
1457
  static async getDefaultStates() {
1430
1458
  const key = AssetKey.parse("blockstates", "minerender:defaultBlockStates");
1431
- return AssetLoader.get(key, "json" /* JSON */);
1459
+ return Caching.defaultBlockStatesCache.get(key.serialize(), () => {
1460
+ return AssetLoader.get(key, "json" /* JSON */);
1461
+ });
1432
1462
  }
1433
1463
  static async getDefaultState(key) {
1434
1464
  const defaultStates = await this.getDefaultStates();
@@ -1467,12 +1497,6 @@ var BlockStates = class {
1467
1497
  await this.PERSISTENT_CACHE.clear();
1468
1498
  }
1469
1499
  };
1470
- __decorateClass([
1471
- (0, import_typescript_memoize2.Memoize)()
1472
- ], BlockStates, "getList", 1);
1473
- __decorateClass([
1474
- (0, import_typescript_memoize2.Memoize)()
1475
- ], BlockStates, "getDefaultStates", 1);
1476
1500
  var DefaultBlockStates = class {
1477
1501
  };
1478
1502
 
@@ -1830,11 +1854,21 @@ var ModelTextures = class {
1830
1854
  return this._persistentMetaCache ??= PersistentCache.open("minerender-texturemeta");
1831
1855
  }
1832
1856
  static async get(key) {
1833
- const asset = await this.preload(key);
1834
- if (asset) {
1835
- return ImageLoader.infoToCanvasData(asset);
1857
+ const keyStr = key.serialize();
1858
+ const pending = this.preload(key);
1859
+ const cached = Caching.textureAssetCache.getIfPresent(keyStr);
1860
+ try {
1861
+ const asset = await pending;
1862
+ if (asset) {
1863
+ return await ImageLoader.infoToCanvasData(asset);
1864
+ }
1865
+ return void 0;
1866
+ } catch (err) {
1867
+ if (cached && Caching.textureAssetCache.getIfPresent(keyStr) === cached) {
1868
+ Caching.textureAssetCache.invalidate(keyStr);
1869
+ }
1870
+ throw err;
1836
1871
  }
1837
- return void 0;
1838
1872
  }
1839
1873
  static async preload(key) {
1840
1874
  const keyStr = key.serialize();
@@ -2514,17 +2548,20 @@ function shutdown() {
2514
2548
  }
2515
2549
 
2516
2550
  // src/assets/Entities.ts
2517
- var import_typescript_memoize3 = require("typescript-memoize");
2518
2551
  var Entities = class {
2519
2552
  static async getBlockEntityModels() {
2520
2553
  const key = AssetKey.parse("models", "minerender:blockEntityModels");
2521
2554
  console.log(key);
2522
- return AssetLoader.get(key, "json" /* JSON */);
2555
+ return Caching.entityModelsCache.get(key.serialize(), () => {
2556
+ return AssetLoader.get(key, "json" /* JSON */);
2557
+ });
2523
2558
  }
2524
2559
  static async getEntityModels() {
2525
2560
  const key = AssetKey.parse("models", "minerender:entityModels");
2526
2561
  console.log(key);
2527
- return AssetLoader.get(key, "json" /* JSON */);
2562
+ return Caching.entityModelsCache.get(key.serialize(), () => {
2563
+ return AssetLoader.get(key, "json" /* JSON */);
2564
+ });
2528
2565
  }
2529
2566
  // BlockEntity names are hardcoded
2530
2567
  static async getBlockList() {
@@ -2570,12 +2607,6 @@ var Entities = class {
2570
2607
  };
2571
2608
  }
2572
2609
  };
2573
- __decorateClass([
2574
- (0, import_typescript_memoize3.Memoize)()
2575
- ], Entities, "getBlockEntityModels", 1);
2576
- __decorateClass([
2577
- (0, import_typescript_memoize3.Memoize)()
2578
- ], Entities, "getEntityModels", 1);
2579
2610
  var EntityModels = class {
2580
2611
  };
2581
2612
  var BlockEntityModels = class {
@@ -3028,9 +3059,9 @@ var EntityObject = class extends SceneObject {
3028
3059
  dispose() {
3029
3060
  super.dispose();
3030
3061
  }
3031
- async loadTextures() {
3062
+ get textureKey() {
3032
3063
  var _a;
3033
- this.imageData = await ModelTextures.get(new AssetKey(
3064
+ return new AssetKey(
3034
3065
  ((_a = this.entity.key) == null ? void 0 : _a.namespace) ?? DEFAULT_NAMESPACE,
3035
3066
  this.entity.key.path,
3036
3067
  //TODO: texture may differ from entity name; most of them are in subdirectories for multiple variants etc.
@@ -3038,7 +3069,10 @@ var EntityObject = class extends SceneObject {
3038
3069
  "entity",
3039
3070
  "assets",
3040
3071
  ".png"
3041
- ));
3072
+ );
3073
+ }
3074
+ async loadTextures() {
3075
+ this.imageData = await ModelTextures.get(this.textureKey);
3042
3076
  }
3043
3077
  //TODO: abstract this, since extracted model data can be used for entities, blocks, players
3044
3078
  createMeshes(force = false) {
@@ -3071,21 +3105,23 @@ var EntityObject = class extends SceneObject {
3071
3105
  this.meshesCreated = true;
3072
3106
  }
3073
3107
  async applyTextures() {
3074
- var _a;
3075
- const textureAsset = await ModelTextures.preload(new AssetKey(
3076
- ((_a = this.entity.key) == null ? void 0 : _a.namespace) ?? DEFAULT_NAMESPACE,
3077
- this.entity.key.path,
3078
- "textures",
3079
- "entity",
3080
- "assets",
3081
- ".png"
3082
- ));
3083
- if (textureAsset) {
3084
- let mat = Materials.getImage({ texture: { src: textureAsset.src } });
3085
- this.iterateAllMeshes((mesh) => {
3086
- mesh.material = mat;
3087
- });
3088
- }
3108
+ const assetKeyStr = this.textureKey.serialize();
3109
+ const keyStr = `entity:${assetKeyStr}`;
3110
+ let mat = Caching.materialCache.getIfPresent(keyStr);
3111
+ if (!mat) {
3112
+ const pending = this.loadTextures();
3113
+ const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
3114
+ await pending;
3115
+ if (!this.imageData) return;
3116
+ const canvas = this.imageData.data.canvas;
3117
+ const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
3118
+ mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
3119
+ this.imageData = void 0;
3120
+ }
3121
+ this.iterateAllMeshes((mesh) => {
3122
+ mesh.material = mat;
3123
+ });
3124
+ this.notifyDirty();
3089
3125
  }
3090
3126
  };
3091
3127
  EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, {});