minerender 2.1.0-beta.7 → 2.1.0-beta.8

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.
Files changed (73) hide show
  1. package/README.md +10 -1
  2. package/dist/browser/esm/armor/Armor.mjs +84 -0
  3. package/dist/browser/esm/armor/Armor.mjs.map +1 -0
  4. package/dist/browser/esm/armor/index.mjs +3 -0
  5. package/dist/browser/esm/armor/index.mjs.map +1 -0
  6. package/dist/browser/esm/assets/BlockEntities.mjs +2 -0
  7. package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
  8. package/dist/browser/esm/assets/Entities.mjs +39 -11
  9. package/dist/browser/esm/assets/Entities.mjs.map +1 -1
  10. package/dist/browser/esm/assets/MineRenderData.mjs +8 -17
  11. package/dist/browser/esm/assets/MineRenderData.mjs.map +1 -1
  12. package/dist/browser/esm/assets/ModelTextures.mjs +13 -7
  13. package/dist/browser/esm/assets/ModelTextures.mjs.map +1 -1
  14. package/dist/browser/esm/assets/_versions/DatasetVersions.mjs +22 -0
  15. package/dist/browser/esm/assets/_versions/DatasetVersions.mjs.map +1 -0
  16. package/dist/browser/esm/cache/Caching.mjs +8 -0
  17. package/dist/browser/esm/cache/Caching.mjs.map +1 -1
  18. package/dist/browser/esm/entity/scene/EntityObject.mjs +31 -5
  19. package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
  20. package/dist/browser/esm/env/browser/BrowserEnv.mjs +11 -4
  21. package/dist/browser/esm/env/browser/BrowserEnv.mjs.map +1 -1
  22. package/dist/browser/esm/index.browser.d.mts +129 -13
  23. package/dist/browser/esm/index.browser.mjs.map +1 -1
  24. package/dist/browser/esm/index.mjs +1 -0
  25. package/dist/browser/esm/index.mjs.map +1 -1
  26. package/dist/browser/esm/model/ItemGlint.mjs +7 -6
  27. package/dist/browser/esm/model/ItemGlint.mjs.map +1 -1
  28. package/dist/browser/esm/model/block/scene/BlockObject.mjs +16 -5
  29. package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
  30. package/dist/browser/esm/scene/SceneDocument.mjs +35 -5
  31. package/dist/browser/esm/scene/SceneDocument.mjs.map +1 -1
  32. package/dist/browser/esm/scene/SceneDocumentLoader.mjs +14 -3
  33. package/dist/browser/esm/scene/SceneDocumentLoader.mjs.map +1 -1
  34. package/dist/browser/esm/skin/SkinGeometries.mjs +4 -1
  35. package/dist/browser/esm/skin/SkinGeometries.mjs.map +1 -1
  36. package/dist/browser/esm/skin/SkinPart.mjs +2 -0
  37. package/dist/browser/esm/skin/SkinPart.mjs.map +1 -1
  38. package/dist/browser/esm/skin/SkinTextureCoordinates.mjs +11 -1
  39. package/dist/browser/esm/skin/SkinTextureCoordinates.mjs.map +1 -1
  40. package/dist/browser/esm/skin/SkinTextures.mjs +1 -1
  41. package/dist/browser/esm/skin/SkinTextures.mjs.map +1 -1
  42. package/dist/browser/esm/skin/scene/SkinObject.mjs +119 -7
  43. package/dist/browser/esm/skin/scene/SkinObject.mjs.map +1 -1
  44. package/dist/browser/esm/texture/PalettedTextures.mjs +46 -0
  45. package/dist/browser/esm/texture/PalettedTextures.mjs.map +1 -0
  46. package/dist/browser/esm/texture/index.mjs +1 -0
  47. package/dist/browser/esm/texture/index.mjs.map +1 -1
  48. package/dist/browser/esm/util/util.mjs +0 -2
  49. package/dist/browser/esm/util/util.mjs.map +1 -1
  50. package/dist/browser/esm/world/Chunk.mjs +62 -33
  51. package/dist/browser/esm/world/Chunk.mjs.map +1 -1
  52. package/dist/browser/esm/world/MineRenderWorld.mjs +98 -13
  53. package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
  54. package/dist/browser/esm/world/SectionMesh.mjs +65 -9
  55. package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
  56. package/dist/browser/esm/world/SectionModels.mjs +21 -15
  57. package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
  58. package/dist/browser/esm/world/SectionWorker.mjs +8 -2
  59. package/dist/browser/esm/world/SectionWorker.mjs.map +1 -1
  60. package/dist/browser/esm/world/WorldStreamer.mjs +109 -15
  61. package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
  62. package/dist/browser/index.d.ts +129 -13
  63. package/dist/browser/index.js +1592 -894
  64. package/dist/browser/index.js.map +1 -1
  65. package/dist/bundle.js +1330 -619
  66. package/dist/bundle.js.map +1 -1
  67. package/dist/node/index.d.mts +117 -12
  68. package/dist/node/index.d.ts +117 -12
  69. package/dist/node/index.js +1505 -793
  70. package/dist/node/index.js.map +1 -1
  71. package/dist/node/index.mjs +1303 -593
  72. package/dist/node/index.mjs.map +1 -1
  73. package/package.json +2 -1
@@ -0,0 +1,22 @@
1
+ // src/assets/_versions/DatasetVersions.ts
2
+ var parseRelease = (value) => /^\d+\.\d+(?:\.\d+)?$/.test(value) ? value.split(".").map(Number) : void 0;
3
+ var compare = (left, right) => {
4
+ for (let i = 0; i < 3; i++) {
5
+ const difference = (left[i] ?? 0) - (right[i] ?? 0);
6
+ if (difference) return difference;
7
+ }
8
+ return 0;
9
+ };
10
+ var nearestRelease = (requestedVersion, published) => {
11
+ const requested = parseRelease(requestedVersion);
12
+ if (!requested) return void 0;
13
+ const versions = published.map((name) => ({ name, number: parseRelease(name) })).filter((entry) => !!entry.number).sort((left, right) => compare(left.number, right.number));
14
+ const sameLine = versions.filter((entry) => entry.number[0] === requested[0] && entry.number[1] === requested[1]);
15
+ const selected = sameLine.sort((left, right) => Math.abs((left.number[2] ?? 0) - (requested[2] ?? 0)) - Math.abs((right.number[2] ?? 0) - (requested[2] ?? 0)) || compare(left.number, right.number))[0] ?? versions.filter((entry) => compare(entry.number, requested) <= 0).pop() ?? versions[0];
16
+ return selected?.name;
17
+ };
18
+ export {
19
+ nearestRelease,
20
+ parseRelease
21
+ };
22
+ //# sourceMappingURL=DatasetVersions.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/assets/_versions/DatasetVersions.ts"],"sourcesContent":["/** Parses release versions; snapshots and other names yield undefined. */\nexport const parseRelease = (value: string): number[] | undefined => /^\\d+\\.\\d+(?:\\.\\d+)?$/.test(value) ? value.split(\".\").map(Number) : undefined;\nconst compare = (left: number[], right: number[]): number => {\n for (let i = 0; i < 3; i++) {\n const difference = (left[i] ?? 0) - (right[i] ?? 0);\n if (difference) return difference;\n }\n return 0;\n};\n\n/** Selects the nearest patch (older on ties), then the latest earlier release or oldest published release. */\nexport const nearestRelease = (requestedVersion: string, published: readonly string[]): string | undefined => {\n const requested = parseRelease(requestedVersion);\n if (!requested) return undefined;\n const versions = published.map(name => ({ name, number: parseRelease(name) }))\n .filter((entry): entry is { name: string; number: number[] } => !!entry.number)\n .sort((left, right) => compare(left.number, right.number));\n const sameLine = versions.filter(entry => entry.number[0] === requested[0] && entry.number[1] === requested[1]);\n const selected = sameLine.sort((left, right) => Math.abs((left.number[2] ?? 0) - (requested[2] ?? 0))\n - Math.abs((right.number[2] ?? 0) - (requested[2] ?? 0)) || compare(left.number, right.number))[0]\n ?? versions.filter(entry => compare(entry.number, requested) <= 0).pop()\n ?? versions[0];\n return selected?.name;\n};\n"],"mappings":";AACO,IAAM,eAAe,CAAC,UAAwC,uBAAuB,KAAK,KAAK,IAAI,MAAM,MAAM,GAAG,EAAE,IAAI,MAAM,IAAI;AACzI,IAAM,UAAU,CAAC,MAAgB,UAA4B;AACzD,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AACxB,UAAM,cAAc,KAAK,CAAC,KAAK,MAAM,MAAM,CAAC,KAAK;AACjD,QAAI,WAAY,QAAO;AAAA,EAC3B;AACA,SAAO;AACX;AAGO,IAAM,iBAAiB,CAAC,kBAA0B,cAAqD;AAC1G,QAAM,YAAY,aAAa,gBAAgB;AAC/C,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,WAAW,UAAU,IAAI,WAAS,EAAE,MAAM,QAAQ,aAAa,IAAI,EAAE,EAAE,EACxE,OAAO,CAAC,UAAuD,CAAC,CAAC,MAAM,MAAM,EAC7E,KAAK,CAAC,MAAM,UAAU,QAAQ,KAAK,QAAQ,MAAM,MAAM,CAAC;AAC7D,QAAM,WAAW,SAAS,OAAO,WAAS,MAAM,OAAO,CAAC,MAAM,UAAU,CAAC,KAAK,MAAM,OAAO,CAAC,MAAM,UAAU,CAAC,CAAC;AAC9G,QAAM,WAAW,SAAS,KAAK,CAAC,MAAM,UAAU,KAAK,KAAK,KAAK,OAAO,CAAC,KAAK,MAAM,UAAU,CAAC,KAAK,EAAE,IAC9F,KAAK,KAAK,MAAM,OAAO,CAAC,KAAK,MAAM,UAAU,CAAC,KAAK,EAAE,KAAK,QAAQ,KAAK,QAAQ,MAAM,MAAM,CAAC,EAAE,CAAC,KAC9F,SAAS,OAAO,WAAS,QAAQ,MAAM,QAAQ,SAAS,KAAK,CAAC,EAAE,IAAI,KACpE,SAAS,CAAC;AACjB,SAAO,UAAU;AACrB;","names":[]}
@@ -32,9 +32,12 @@ var _Caching = class _Caching {
32
32
  this.entityTextureCache,
33
33
  this.entityAnimationCache,
34
34
  this.blockEntityIndexCache,
35
+ this.entityDatasetVersionCache,
35
36
  this.fontCache,
36
37
  this.unihexCache,
37
38
  this.bannerPatternCache,
39
+ this.equipmentCache,
40
+ this.trimCache,
38
41
  this.mineRenderDataCache,
39
42
  this.usernameUuidCache,
40
43
  this.biomeCache
@@ -66,6 +69,8 @@ var _Caching = class _Caching {
66
69
  };
67
70
  }
68
71
  };
72
+ /** Cached in place of a missing asset. The caches drop `undefined` results, which would request the asset again. */
73
+ _Caching.MISSING = false;
69
74
  _Caching._generation = 0;
70
75
  _Caching.rawImageCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(5)).buildAsync();
71
76
  _Caching.imageDataCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(10)).buildAsync();
@@ -87,9 +92,12 @@ _Caching.entityModelCache = _Caching.createAssetCache();
87
92
  _Caching.entityTextureCache = _Caching.createAssetCache();
88
93
  _Caching.entityAnimationCache = _Caching.createAssetCache();
89
94
  _Caching.blockEntityIndexCache = _Caching.createAssetCache();
95
+ _Caching.entityDatasetVersionCache = _Caching.createAssetCache();
90
96
  _Caching.unihexCache = _Caching.createAssetCache();
91
97
  _Caching.fontCache = _Caching.createAssetCache();
92
98
  _Caching.bannerPatternCache = _Caching.createAssetCache();
99
+ _Caching.equipmentCache = _Caching.createAssetCache();
100
+ _Caching.trimCache = _Caching.createAssetCache();
93
101
  _Caching.mineRenderDataCache = _Caching.createAssetCache();
94
102
  _Caching.usernameUuidCache = Caches.builder().expireAfterWrite(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
95
103
  _Caching.biomeCache = _Caching.createAssetCache();
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/cache/Caching.ts"],"sourcesContent":["import { AsyncLoadingCache, Caches, Loader, LoadingCache, SimpleCache } from \"@inventivetalent/loading-cache\";\nimport { BoxGeometryKey, CacheKey, serializeBoxGeometryKey, serializeImageKey, TextureKey } from \"./CacheKey\";\nimport { Time } from \"@inventivetalent/time\";\nimport { ImageInfo, ImageLoader } from \"../image/ImageLoader\";\nimport { BoxGeometry, Material, Mesh, PixelFormat, RGBAFormat, Texture } from \"three\";\nimport { Materials } from \"../Materials\";\nimport { CompatImage } from \"../canvas/CanvasCompat\";\nimport { Model, TextureAsset } from \"../model/Model\";\nimport { WrappedImage } from \"../WrappedImage\";\nimport { TextureAtlas } from \"../texture/TextureAtlas\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport type { EntityModelFile } from \"../entity/EntityModel\";\nimport type { EntityAnimationFile } from \"../entity/EntityAnimation\";\nimport type { BlockEntityIndex } from \"../assets/BlockEntities\";\nimport type { ListAsset } from \"../ListAsset\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport type { AssetKey } from \"../assets/AssetKey\";\nimport type { UnihexFile } from \"../assets/_fonts/Unihex\";\nimport type { BitmapFont } from \"../assets/Fonts\";\nimport type { BannerPattern } from \"../assets/BannerPatterns\";\nimport type { Biome } from \"../assets/Biomes\";\n\n/** Shared in-memory caches for loaded assets and render resources. Persistent stores are managed separately. */\nexport class Caching {\n\n private static _generation = 0;\n\n /** Changes when shared assets are cleared, so derived caches can discard their old values. */\n public static get generation(): number { return this._generation; }\n\n static readonly rawImageCache: AsyncLoadingCache<CacheKey, ImageInfo> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(5))\n .buildAsync<CacheKey, ImageInfo>();\n static readonly imageDataCache: AsyncLoadingCache<CacheKey, ImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ImageData>();\n static readonly canvasImageDataCache: AsyncLoadingCache<CacheKey, ExtractableImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ExtractableImageData>();\n static readonly wrappedImageCache: AsyncLoadingCache<CacheKey, WrappedImage> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, WrappedImage>();\n\n static readonly boxGeometryCache: SimpleCache<CacheKey, BoxGeometry> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(20))\n .build<CacheKey, BoxGeometry>();\n\n static readonly textureCache: SimpleCache<CacheKey, Texture> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Texture>();\n\n static readonly materialCache: SimpleCache<CacheKey, Material> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Material>();\n\n static readonly boxMeshCache: SimpleCache<CacheKey, Mesh> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Mesh>();\n\n static readonly textureAssetCache: AsyncLoadingCache<CacheKey, TextureAsset> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAsset>();\n static readonly textureMetaCache: AsyncLoadingCache<CacheKey, MinecraftTextureMeta> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, MinecraftTextureMeta>();\n\n static readonly rawModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly mergedModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly modelTextureAtlasCache: AsyncLoadingCache<CacheKey, TextureAtlas> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAtlas>();\n\n static readonly blockStateCache: AsyncLoadingCache<CacheKey, BlockState> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, BlockState>();\n\n static readonly listAssetCache: AsyncLoadingCache<CacheKey, ListAsset> = Caching.createAssetCache<ListAsset>();\n\n static readonly blockTintCache: AsyncLoadingCache<CacheKey, number> = Caching.createAssetCache<number>();\n\n static readonly entityModelCache: AsyncLoadingCache<CacheKey, EntityModelFile> = Caching.createAssetCache<EntityModelFile>();\n\n static readonly entityTextureCache: AsyncLoadingCache<CacheKey, AssetKey> = Caching.createAssetCache<AssetKey>();\n\n static readonly entityAnimationCache: AsyncLoadingCache<CacheKey, EntityAnimationFile> = Caching.createAssetCache<EntityAnimationFile>();\n static readonly blockEntityIndexCache: AsyncLoadingCache<CacheKey, BlockEntityIndex> = Caching.createAssetCache<BlockEntityIndex>();\n static readonly unihexCache: AsyncLoadingCache<CacheKey, UnihexFile> = Caching.createAssetCache<UnihexFile>();\n static readonly fontCache: AsyncLoadingCache<CacheKey, BitmapFont> = Caching.createAssetCache<BitmapFont>();\n static readonly bannerPatternCache: AsyncLoadingCache<CacheKey, BannerPattern> = Caching.createAssetCache<BannerPattern>();\n static readonly mineRenderDataCache: AsyncLoadingCache<CacheKey, unknown> = Caching.createAssetCache<unknown>();\n static readonly usernameUuidCache: AsyncLoadingCache<CacheKey, string> = Caches.builder()\n .expireAfterWrite(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, string>();\n static readonly biomeCache: AsyncLoadingCache<CacheKey, Biome> = Caching.createAssetCache<Biome>();\n\n private static createAssetCache<T>(): AsyncLoadingCache<CacheKey, T> {\n return Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, T>();\n }\n\n\n /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */\n private static get all(): { invalidateAll(): void; end(): void }[] {\n return [\n this.rawImageCache,\n this.imageDataCache,\n this.canvasImageDataCache,\n this.wrappedImageCache,\n this.boxGeometryCache,\n this.textureCache,\n this.materialCache,\n this.boxMeshCache,\n this.textureAssetCache,\n this.textureMetaCache,\n this.rawModelCache,\n this.mergedModelCache,\n this.modelTextureAtlasCache,\n this.blockStateCache,\n this.listAssetCache,\n this.blockTintCache,\n this.entityModelCache,\n this.entityTextureCache,\n this.entityAnimationCache,\n this.blockEntityIndexCache,\n this.fontCache,\n this.unihexCache,\n this.bannerPatternCache,\n this.mineRenderDataCache,\n this.usernameUuidCache,\n this.biomeCache\n ];\n }\n\n /** Invalidates in-memory entries so later lookups reload them. Persisted entries are retained. */\n public static clear() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n }\n }\n\n /**\n * Clears every cache and stops its expiry timer.\n *\n * Expiry timers are unref'd in Node, so idle processes can exit without this cleanup.\n * Use {@link shutdown} to also stop requests and the shared Ticker.\n */\n public static end() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n cache.end();\n }\n }\n\n public static get cacheSizes() {\n return {\n //TODO\n }\n }\n\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/cache/Caching.ts"],"sourcesContent":["import { AsyncLoadingCache, Caches, Loader, LoadingCache, SimpleCache } from \"@inventivetalent/loading-cache\";\nimport { BoxGeometryKey, CacheKey, serializeBoxGeometryKey, serializeImageKey, TextureKey } from \"./CacheKey\";\nimport { Time } from \"@inventivetalent/time\";\nimport { ImageInfo, ImageLoader } from \"../image/ImageLoader\";\nimport { BoxGeometry, Material, Mesh, PixelFormat, RGBAFormat, Texture } from \"three\";\nimport { Materials } from \"../Materials\";\nimport { CompatImage } from \"../canvas/CanvasCompat\";\nimport { Model, TextureAsset } from \"../model/Model\";\nimport { WrappedImage } from \"../WrappedImage\";\nimport { TextureAtlas } from \"../texture/TextureAtlas\";\nimport { ExtractableImageData } from \"../ExtractableImageData\";\nimport { MinecraftTextureMeta } from \"../MinecraftTextureMeta\";\nimport type { EntityModelFile } from \"../entity/EntityModel\";\nimport type { EntityAnimationFile } from \"../entity/EntityAnimation\";\nimport type { BlockEntityIndex } from \"../assets/BlockEntities\";\nimport type { ListAsset } from \"../ListAsset\";\nimport { BlockState } from \"../model/block/BlockState\";\nimport type { AssetKey } from \"../assets/AssetKey\";\nimport type { UnihexFile } from \"../assets/_fonts/Unihex\";\nimport type { BitmapFont } from \"../assets/Fonts\";\nimport type { BannerPattern } from \"../assets/BannerPatterns\";\nimport type { Biome } from \"../assets/Biomes\";\n\n/** Shared in-memory caches for loaded assets and render resources. Persistent stores are managed separately. */\nexport class Caching {\n\n /** Cached in place of a missing asset. The caches drop `undefined` results, which would request the asset again. */\n public static readonly MISSING = false as const;\n\n private static _generation = 0;\n\n /** Changes when shared assets are cleared, so derived caches can discard their old values. */\n public static get generation(): number { return this._generation; }\n\n static readonly rawImageCache: AsyncLoadingCache<CacheKey, ImageInfo> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(5))\n .buildAsync<CacheKey, ImageInfo>();\n static readonly imageDataCache: AsyncLoadingCache<CacheKey, ImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ImageData>();\n static readonly canvasImageDataCache: AsyncLoadingCache<CacheKey, ExtractableImageData> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, ExtractableImageData>();\n static readonly wrappedImageCache: AsyncLoadingCache<CacheKey, WrappedImage> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(10))\n .buildAsync<CacheKey, WrappedImage>();\n\n static readonly boxGeometryCache: SimpleCache<CacheKey, BoxGeometry> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(20))\n .build<CacheKey, BoxGeometry>();\n\n static readonly textureCache: SimpleCache<CacheKey, Texture> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Texture>();\n\n static readonly materialCache: SimpleCache<CacheKey, Material> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Material>();\n\n static readonly boxMeshCache: SimpleCache<CacheKey, Mesh> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .build<CacheKey, Mesh>();\n\n static readonly textureAssetCache: AsyncLoadingCache<CacheKey, TextureAsset> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAsset>();\n static readonly textureMetaCache: AsyncLoadingCache<CacheKey, MinecraftTextureMeta | typeof Caching.MISSING> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, MinecraftTextureMeta | typeof Caching.MISSING>();\n\n static readonly rawModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly mergedModelCache: AsyncLoadingCache<CacheKey, Model> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, Model>();\n static readonly modelTextureAtlasCache: AsyncLoadingCache<CacheKey, TextureAtlas> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, TextureAtlas>();\n\n static readonly blockStateCache: AsyncLoadingCache<CacheKey, BlockState> = Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, BlockState>();\n\n static readonly listAssetCache: AsyncLoadingCache<CacheKey, ListAsset> = Caching.createAssetCache<ListAsset>();\n\n static readonly blockTintCache: AsyncLoadingCache<CacheKey, number> = Caching.createAssetCache<number>();\n\n static readonly entityModelCache: AsyncLoadingCache<CacheKey, EntityModelFile> = Caching.createAssetCache<EntityModelFile>();\n\n static readonly entityTextureCache: AsyncLoadingCache<CacheKey, AssetKey | typeof Caching.MISSING> = Caching.createAssetCache<AssetKey | typeof Caching.MISSING>();\n\n static readonly entityAnimationCache: AsyncLoadingCache<CacheKey, EntityAnimationFile> = Caching.createAssetCache<EntityAnimationFile>();\n static readonly blockEntityIndexCache: AsyncLoadingCache<CacheKey, BlockEntityIndex> = Caching.createAssetCache<BlockEntityIndex>();\n static readonly entityDatasetVersionCache: AsyncLoadingCache<CacheKey, string> = Caching.createAssetCache<string>();\n static readonly unihexCache: AsyncLoadingCache<CacheKey, UnihexFile> = Caching.createAssetCache<UnihexFile>();\n static readonly fontCache: AsyncLoadingCache<CacheKey, BitmapFont> = Caching.createAssetCache<BitmapFont>();\n static readonly bannerPatternCache: AsyncLoadingCache<CacheKey, BannerPattern> = Caching.createAssetCache<BannerPattern>();\n static readonly equipmentCache: AsyncLoadingCache<CacheKey, unknown> = Caching.createAssetCache<unknown>();\n static readonly trimCache: AsyncLoadingCache<CacheKey, unknown> = Caching.createAssetCache<unknown>();\n static readonly mineRenderDataCache: AsyncLoadingCache<CacheKey, unknown> = Caching.createAssetCache<unknown>();\n static readonly usernameUuidCache: AsyncLoadingCache<CacheKey, string> = Caches.builder()\n .expireAfterWrite(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, string>();\n static readonly biomeCache: AsyncLoadingCache<CacheKey, Biome> = Caching.createAssetCache<Biome>();\n\n private static createAssetCache<T>(): AsyncLoadingCache<CacheKey, T> {\n return Caches.builder()\n .expireAfterWrite(Time.minutes(10))\n .expireAfterAccess(Time.minutes(5))\n .expirationInterval(Time.seconds(30))\n .buildAsync<CacheKey, T>();\n }\n\n\n /** Every cache above, so clear()/end() can never fall out of sync with the field list again. */\n private static get all(): { invalidateAll(): void; end(): void }[] {\n return [\n this.rawImageCache,\n this.imageDataCache,\n this.canvasImageDataCache,\n this.wrappedImageCache,\n this.boxGeometryCache,\n this.textureCache,\n this.materialCache,\n this.boxMeshCache,\n this.textureAssetCache,\n this.textureMetaCache,\n this.rawModelCache,\n this.mergedModelCache,\n this.modelTextureAtlasCache,\n this.blockStateCache,\n this.listAssetCache,\n this.blockTintCache,\n this.entityModelCache,\n this.entityTextureCache,\n this.entityAnimationCache,\n this.blockEntityIndexCache,\n this.entityDatasetVersionCache,\n this.fontCache,\n this.unihexCache,\n this.bannerPatternCache,\n this.equipmentCache,\n this.trimCache,\n this.mineRenderDataCache,\n this.usernameUuidCache,\n this.biomeCache\n ];\n }\n\n /** Invalidates in-memory entries so later lookups reload them. Persisted entries are retained. */\n public static clear() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n }\n }\n\n /**\n * Clears every cache and stops its expiry timer.\n *\n * Expiry timers are unref'd in Node, so idle processes can exit without this cleanup.\n * Use {@link shutdown} to also stop requests and the shared Ticker.\n */\n public static end() {\n this._generation++;\n for (const cache of this.all) {\n cache.invalidateAll();\n cache.end();\n }\n }\n\n public static get cacheSizes() {\n return {\n //TODO\n }\n }\n\n}\n"],"mappings":"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","names":[]}
@@ -12,6 +12,8 @@ import { MinecraftCubeTexture } from "../../MinecraftCubeTexture.mjs";
12
12
  import { CUBE_FACES } from "../../CubeFace.mjs";
13
13
  import { isMesh } from "../../util/three.mjs";
14
14
  import { EntityAnimationPlayer, validateAnimationWeights } from "./EntityAnimationPlayer.mjs";
15
+ var ItemGlintClass;
16
+ var PalettedTexturesClass;
15
17
  var _EntityObject = class _EntityObject extends SceneObject {
16
18
  constructor(entity, options) {
17
19
  super();
@@ -27,8 +29,14 @@ var _EntityObject = class _EntityObject extends SceneObject {
27
29
  this.animationPlayers = [];
28
30
  this.partPoses = /* @__PURE__ */ new Map();
29
31
  this.options = merge({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
30
- this.addEventListener("added", () => this.updateScrollSubscription());
31
- this.addEventListener("removed", () => this.updateScrollSubscription());
32
+ this.addEventListener("added", () => {
33
+ this.updateScrollSubscription();
34
+ this.glint?.updateSubscription(!!this.parent);
35
+ });
36
+ this.addEventListener("removed", () => {
37
+ this.updateScrollSubscription();
38
+ this.glint?.updateSubscription(!!this.parent);
39
+ });
32
40
  }
33
41
  /** An optional shared material replaces texture loading for every selected draw; its owner retains disposal. */
34
42
  async init(material) {
@@ -39,12 +47,26 @@ var _EntityObject = class _EntityObject extends SceneObject {
39
47
  mesh.material = material;
40
48
  });
41
49
  this.notifyDirty();
42
- } else await this.applyTextures();
50
+ } else {
51
+ await this.applyTextures();
52
+ const layers = Object.entries(this.entityLayers).filter(([, layer]) => layer.glint);
53
+ const meshes = [];
54
+ for (const [name] of layers) this.getLayerGroup(name)?.traverse((object) => {
55
+ if (isMesh(object)) meshes.push(object);
56
+ });
57
+ if (meshes.length) {
58
+ const ItemGlint = ItemGlintClass ?? (ItemGlintClass = (await import("../../model/ItemGlint.mjs")).ItemGlint);
59
+ this.glint = await ItemGlint.create(this, void 0, this.getTextureKey(layers[0][1]).root, meshes.map((mesh) => ({ mesh })), "armor");
60
+ this.glint.updateSubscription(!!this.parent);
61
+ }
62
+ }
43
63
  }
44
64
  dispose() {
45
65
  super.dispose();
46
66
  }
47
67
  disposeAndRemoveAllChildren() {
68
+ this.glint?.dispose();
69
+ this.glint = void 0;
48
70
  this.clearScrollMaterials();
49
71
  for (const geometry of this.geometries) geometry.dispose();
50
72
  this.geometries.clear();
@@ -203,6 +225,10 @@ var _EntityObject = class _EntityObject extends SceneObject {
203
225
  );
204
226
  }
205
227
  async loadTextures(layer = this.entity) {
228
+ if (layer.palette) {
229
+ const PalettedTextures = PalettedTexturesClass ?? (PalettedTexturesClass = (await import("../../texture/PalettedTextures.mjs")).PalettedTextures);
230
+ return PalettedTextures.get(this.getTextureKey(layer), layer.palette.key, layer.palette.permutation);
231
+ }
206
232
  return ModelTextures.get(this.getTextureKey(layer));
207
233
  }
208
234
  createMeshes(force = false) {
@@ -275,10 +301,10 @@ var _EntityObject = class _EntityObject extends SceneObject {
275
301
  this.clearScrollMaterials();
276
302
  const results = await Promise.allSettled(Object.entries(this.entityLayers).map(async ([name, layer]) => {
277
303
  const mode = layer.render ?? layer.layer.render ?? "cutout";
278
- const tint = layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint];
304
+ const tint = (layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint]) ?? layer.color;
279
305
  const scroll = Materials.entityModeScroll(mode);
280
306
  const assetKeyStr = this.getTextureKey(layer).serialize();
281
- const keyStr = `entity:${mode}:${tint === void 0 ? "" : new Color(tint).getHexString()}:${assetKeyStr}`;
307
+ const keyStr = `entity:${mode}:${tint === void 0 ? "" : new Color(tint).getHexString()}:${assetKeyStr}` + (layer.palette ? `:${layer.palette.key.serialize()}:${layer.palette.permutation.serialize()}` : "");
282
308
  let mat = scroll ? void 0 : Caching.materialCache.getIfPresent(keyStr);
283
309
  if (!mat) {
284
310
  const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/entity/scene/EntityObject.ts"],"sourcesContent":["import { SceneObject } from \"../../renderer/SceneObject\";\nimport { SceneObjectOptions } from \"../../renderer/SceneObjectOptions\";\nimport { Caching } from \"../../cache/Caching\";\nimport { merge } from \"../../util/_internal/merge\";\nimport { Color, Object3D } from \"three\";\nimport type { BufferGeometry, ColorRepresentation, Material, Mesh, MeshBasicMaterial } from \"three\";\nimport { Ticker } from \"../../Ticker\";\nimport { addWireframeToMesh } from \"../../util/model\";\nimport { ModelTextures } from \"../../assets/ModelTextures\";\nimport { AssetKey, isAssetKey } from \"../../assets/AssetKey\";\nimport { ExtractableImageData } from \"../../ExtractableImageData\";\nimport { Materials } from \"../../Materials\";\nimport { MinecraftCubeTexture } from \"../../MinecraftCubeTexture\";\nimport { CUBE_FACES, CubeFace } from \"../../CubeFace\";\nimport { EntityLayer, EntityModel, EntityModelPart } from \"../EntityModel\";\nimport type { DoubleArray } from \"../../model/Model\";\nimport type { Maybe } from \"../../util/util\";\nimport { isMesh } from \"../../util/three\";\nimport type { EntityAnimation } from \"../EntityAnimation\";\nimport { EntityAnimationOptions, EntityAnimationPlayer, validateAnimationWeights } from \"./EntityAnimationPlayer\";\n\n/** Renders selected entity layers as named part groups. Create it through {@link MineRenderScene.addEntity}. */\nexport class EntityObject extends SceneObject {\n\n public readonly isEntityObject: true = true;\n\n public static readonly DEFAULT_OPTIONS: EntityObjectOptions = merge({}, SceneObject.DEFAULT_OPTIONS);\n public readonly options: EntityObjectOptions;\n\n private meshesCreated: boolean = false;\n private readonly geometries = new Set<BufferGeometry>();\n private readonly disposeWireframes: (() => void)[] = [];\n /** Scrolling materials are owned: their texture offset follows this entity's age. */\n private readonly scrollMaterials: { material: Material, offset: { set(x: number, y: number): unknown }, speed: [number, number] }[] = [];\n private scrollTicker: Maybe<number>;\n /** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */\n public age: number = 0;\n private readonly animationPlayers: { player: EntityAnimationPlayer, indices: number[] }[] = [];\n private readonly partPoses = new Map<Object3D, EntityModelPart[\"pose\"]>();\n\n constructor(readonly entity: EntityModel, options?: Partial<EntityObjectOptions>) {\n super();\n this.options = merge({}, EntityObject.DEFAULT_OPTIONS, options ?? {});\n this.addEventListener(\"added\", () => this.updateScrollSubscription());\n this.addEventListener(\"removed\", () => this.updateScrollSubscription());\n }\n\n /** An optional shared material replaces texture loading for every selected draw; its owner retains disposal. */\n async init(material?: Material): Promise<void> {\n this.createMeshes();\n if (material) {\n this.clearScrollMaterials();\n this.iterateAllMeshes(mesh => { mesh.material = material; });\n this.notifyDirty();\n } else await this.applyTextures();\n }\n\n dispose() {\n super.dispose();\n }\n\n public disposeAndRemoveAllChildren() {\n this.clearScrollMaterials();\n for (const geometry of this.geometries) geometry.dispose();\n this.geometries.clear();\n for (const dispose of this.disposeWireframes.splice(0)) dispose();\n // The animated part groups are removed with the children.\n for (const { player } of this.animationPlayers.splice(0)) player.clear();\n this.partPoses.clear();\n super.disposeAndRemoveAllChildren();\n }\n\n private clearScrollMaterials() {\n Ticker.remove(this.scrollTicker);\n this.scrollTicker = undefined;\n for (const { material } of this.scrollMaterials.splice(0)) {\n (material as { map?: { dispose(): void } }).map?.dispose();\n material.dispose();\n }\n }\n\n private updateScrollSubscription() {\n if (this.parent && this.scrollMaterials.length) {\n if (this.scrollTicker === undefined) {\n this.scrollTicker = Ticker.add(() => {\n this.age++;\n this.updateScroll();\n });\n }\n } else {\n Ticker.remove(this.scrollTicker);\n this.scrollTicker = undefined;\n }\n }\n\n /** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */\n private updateScroll() {\n for (const { offset, speed } of this.scrollMaterials) {\n // Texture V points up here and down in vanilla.\n offset.set((this.age * speed[0]) % 1, 0 - (this.age * speed[1]) % 1);\n }\n this.notifyDirty();\n }\n\n //<editor-fold desc=\"ANIMATION\">\n\n /** The first active clip, until playback is stopped or the object is disposed. */\n public get animation(): Maybe<EntityAnimation> {\n return this.animationPlayers[0]?.player.animation;\n }\n\n /** Clips playing together, in the order passed to {@link playAnimations}. */\n public get activeAnimations(): readonly EntityAnimation[] {\n const animations: EntityAnimation[] = [];\n for (const { player, indices } of this.animationPlayers) {\n player.animations.forEach((animation, i) => { animations[indices[i]] = animation; });\n }\n return animations;\n }\n\n /** Weights of the active clips, in the same order as {@link activeAnimations}. */\n public get animationWeights(): readonly number[] {\n const weights: number[] = [];\n for (const { player, indices } of this.animationPlayers) {\n player.weights.forEach((weight, i) => { weights[indices[i]] = weight; });\n }\n return weights;\n }\n\n /** Seconds since the animation started, before looping. */\n public get animationTime(): number {\n return this.animationPlayers[0]?.player.time ?? 0;\n }\n\n /**\n * Plays a clip from {@link Entities.getAnimations}, replacing all active clips.\n * Offsets apply to the baked pose in the clip's layer (`main` by default) and its repeated draws.\n * A `main` clip also poses every selected layer without a clip of its own.\n * The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.\n */\n public playAnimation(animation: EntityAnimation, options?: EntityAnimationOptions): void {\n this.playAnimations([animation], options);\n }\n\n /**\n * Plays clips with a shared clock, adding their weighted offsets within each geometry layer.\n * Weights default to 1 and are not normalized. Selected layers without their own clip follow `main`.\n */\n public playAnimations(animations: readonly EntityAnimation[], options?: EntityAnimationOptions): void {\n const weights = validateAnimationWeights(options?.weights ?? animations.map(() => 1), animations.length);\n const selections = new Map<string, { animations: EntityAnimation[], names: string[], indices: number[] }>();\n animations.forEach((animation, index) => {\n const layer = animation.layer ?? \"main\";\n const names = Object.keys(this.entityLayers).filter(name => name.split(\"#\")[0] === layer);\n if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer \"${layer}\"`);\n let selection = selections.get(layer);\n if (!selection) selections.set(layer, selection = { animations: [], names, indices: [] });\n selection.animations.push(animation);\n selection.indices.push(index);\n });\n const main = selections.get(\"main\");\n if (main) main.names.push(...Object.keys(this.entityLayers).filter(name => !selections.has(name.split(\"#\")[0])));\n this.createMeshes();\n this.stopAnimation();\n for (const { animations: clips, names, indices } of selections.values()) {\n const player = new EntityAnimationPlayer();\n player.playAnimations(names.map(name => this.getLayerGroup(name)!), clips,\n { ...options, weights: indices.map(index => weights[index]) }, this.partPoses);\n this.animationPlayers.push({ player, indices });\n }\n this.notifyDirty();\n }\n\n /** Changes weights in active clip order, notifying the scene without restarting the shared clock. Has no effect without an animation. */\n public setAnimationWeights(weights: readonly number[]): void {\n if (!this.animationPlayers.length) return;\n const values = validateAnimationWeights(weights, this.activeAnimations.length);\n for (const { player, indices } of this.animationPlayers) player.setWeights(indices.map(index => values[index]));\n this.notifyDirty();\n }\n\n /** Stops all clips and restores the poses from before playback. */\n public stopAnimation(): void {\n const players = this.animationPlayers.splice(0);\n for (const { player } of players) player.stop();\n if (players.length) this.notifyDirty();\n }\n\n /** Poses the object at an explicit time in seconds. Has no effect without an animation. */\n public setAnimationTime(seconds: number): void {\n for (const { player } of this.animationPlayers) player.setTime(seconds);\n if (this.animationPlayers.length) this.notifyDirty();\n }\n\n /** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */\n public advanceAnimation(deltaSeconds: number): void {\n for (const { player } of this.animationPlayers) player.advance(deltaSeconds);\n if (this.animationPlayers.length) this.notifyDirty();\n }\n\n //</editor-fold>\n\n /** Finds a selected draw by its layer key, such as `main` or `main#2`, or returns `undefined`. */\n public getLayerGroup(name: string): Maybe<Object3D> {\n return super.getGroupByName(`layer:${name}`);\n }\n\n /** Finds a part name without `group:`. Supply `layerName` to restrict the search to one draw. */\n public getGroupByName(name: string, layerName?: string): Maybe<Object3D> {\n return layerName === undefined ? super.getGroupByName(name)\n : this.getLayerGroup(layerName)?.getObjectByName(`group:${name}`);\n }\n\n /** Finds a mesh name without `mesh:`. Supply `layerName` to restrict the search to one draw. */\n public getMeshByName(name: string, layerName?: string): Maybe<Mesh> {\n return layerName === undefined ? super.getMeshByName(name)\n : this.getLayerGroup(layerName)?.getObjectByName(`mesh:${name}`) as Maybe<Mesh>;\n }\n\n private get entityLayers(): Record<string, EntityLayer> {\n return this.entity.layers ?? { main: this.entity };\n }\n\n private getTextureKey(layer: EntityLayer): AssetKey {\n if (layer.texture) return layer.texture;\n const key = layer.key;\n return new AssetKey(\n key.namespace,\n isAssetKey(key) ? key.getFullPath() : key.path,\n \"textures\",\n \"entity\",\n \"assets\",\n \".png\"\n );\n }\n\n protected async loadTextures(layer: EntityLayer = this.entity): Promise<Maybe<ExtractableImageData>> {\n return ModelTextures.get(this.getTextureKey(layer));\n }\n\n protected createMeshes(force: boolean = false) {\n if (this.meshesCreated && !force) return;\n\n const modelRoot = new Object3D();\n let transformNode = modelRoot;\n // Keep Minecraft's model coordinates separate from caller placement and scale.\n const transform = this.options.flip === undefined ? this.entity.transform : undefined;\n if (transform) {\n // One position, rotation and scale cannot express nonuniform scale followed by rotation.\n // Nested nodes preserve each operation and avoid manual matrices, which leave bounds stale.\n for (const [index, op] of transform.entries()) {\n if (index > 0) {\n const child = new Object3D();\n transformNode.add(child);\n transformNode = child;\n }\n if (\"scale\" in op) transformNode.scale.set(...op.scale);\n else if (\"translate\" in op) transformNode.position.set(...op.translate);\n else transformNode.rotation.set(...op.rotate, \"ZYX\");\n }\n } else if (this.options.flip ?? true) {\n modelRoot.scale.set(-1, -1, 1);\n }\n this.add(modelRoot);\n Object.entries(this.entityLayers).forEach(([name, layer], index) => {\n const group = this.createGroup(`layer:${name}`);\n transformNode.add(group);\n const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);\n this.createPart(\"root\", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward, this.options.faces?.[name]);\n });\n this.meshesCreated = true;\n }\n\n private createPart(name: string, part: EntityModelPart, parent: Object3D, textureSize: DoubleArray, material: Material, renderOrder: number, inward: boolean = true, faces?: CubeFace[]) {\n const anchor = this.createGroup(name);\n anchor.position.fromArray(part.pose.offset);\n anchor.rotation.set(...part.pose.rotation, \"ZYX\");\n anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);\n this.partPoses.set(anchor, part.pose);\n parent.add(anchor);\n const size = part.texture ?? textureSize;\n\n for (const cube of part.cubes) {\n const [width, height, depth] = cube.size;\n const [growX, growY, growZ] = cube.grow ?? [0, 0, 0];\n const texture = new MinecraftCubeTexture(...cube.uv, ...size);\n const uv = size[0] === 0 || size[1] === 0 ? new Array<number>(48).fill(0) : texture.toUvArray(width, height, depth, cube.mirror);\n const geometry = this._getBoxGeometryForDimensionsAndUv(\n width + growX * 2, height + growY * 2, depth + growZ * 2, uv\n ).clone();\n this.geometries.add(geometry);\n geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);\n if (faces) {\n geometry.setIndex(Array.from(geometry.getIndex()!.array).filter((_, index) => faces.includes(CUBE_FACES[Math.floor(index / 6)])));\n geometry.clearGroups();\n }\n // Vanilla draws most entity render types without backface culling, e.g. chicken legs are only painted on faces seen from inside.\n // Zero-thickness cubes keep one face per side, as their coplanar faces would z-fight.\n if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {\n const index = Array.from(geometry.getIndex()!.array);\n geometry.setIndex(index.concat(index.slice().reverse()));\n }\n const mesh = this.createMesh(name, geometry, material);\n mesh.renderOrder = renderOrder;\n anchor.add(mesh);\n if (this.options.wireframe) this.disposeWireframes.push(addWireframeToMesh(geometry, mesh));\n }\n for (const [childName, child] of Object.entries(part.children)) {\n this.createPart(childName, child, anchor, size, material, renderOrder, inward, faces);\n }\n }\n\n protected async applyTextures() {\n this.clearScrollMaterials();\n const results = await Promise.allSettled(Object.entries(this.entityLayers).map(async ([name, layer]) => {\n const mode = layer.render ?? layer.layer.render ?? \"cutout\";\n const tint = layer.tint === undefined ? undefined : this.options.tints?.[layer.tint];\n const scroll = Materials.entityModeScroll(mode);\n const assetKeyStr = this.getTextureKey(layer).serialize();\n const keyStr = `entity:${ mode }:${ tint === undefined ? \"\" : new Color(tint).getHexString() }:${ assetKeyStr }`;\n let mat = scroll ? undefined : Caching.materialCache.getIfPresent(keyStr);\n if (!mat) {\n const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);\n const imageData = await this.loadTextures(layer);\n if (!imageData) return;\n const canvas = (imageData.data as CanvasRenderingContext2D).canvas;\n const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);\n // A cache clear during decoding must not restore an older source's material.\n // Scrolling materials stay out of the cache, as their texture offset belongs to this entity.\n mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset\n ? Caching.materialCache.get(keyStr, createMaterial)\n : createMaterial();\n if (scroll) {\n this.scrollMaterials.push({ material: mat!, offset: (mat as MeshBasicMaterial).map!.offset, speed: scroll });\n }\n }\n this.getLayerGroup(name)?.traverse(object => {\n if (isMesh(object)) object.material = mat!;\n });\n }));\n if (!this.children.length) {\n // Disposed while the textures were loading: nothing is left to scroll.\n this.clearScrollMaterials();\n } else if (this.scrollMaterials.length) {\n this.updateScroll();\n }\n this.updateScrollSubscription();\n this.notifyDirty();\n const failure = results.find(result => result.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n }\n\n\n}\n\n/** Render settings passed to `scene.addEntity(entity, options)` or the EntityObject constructor. */\nexport interface EntityObjectOptions extends SceneObjectOptions {\n /**\n * `true` applies only vanilla's entity flip, scale (-1, -1, 1); `false` keeps raw model space.\n * By default the model's dataset transform is used, or the flip for models without one.\n */\n flip?: boolean;\n /** Colours for the dataset's tint labels, e.g. `{ wool_color: 0xf9801d }`; a pass whose label is absent stays untinted. */\n tints?: Record<string, ColorRepresentation>;\n /** Cube faces by layer key; omitted layers draw all six faces. */\n faces?: Record<string, CubeFace[]>;\n}\n\nexport function isEntityObject(obj: any): obj is EntityObject {\n return (<EntityObject>obj).isEntityObject;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../src/entity/scene/EntityObject.ts"],"sourcesContent":["import { SceneObject } from \"../../renderer/SceneObject\";\nimport { SceneObjectOptions } from \"../../renderer/SceneObjectOptions\";\nimport { Caching } from \"../../cache/Caching\";\nimport { merge } from \"../../util/_internal/merge\";\nimport { Color, Object3D } from \"three\";\nimport type { BufferGeometry, ColorRepresentation, Material, Mesh, MeshBasicMaterial } from \"three\";\nimport { Ticker } from \"../../Ticker\";\nimport { addWireframeToMesh } from \"../../util/model\";\nimport { ModelTextures } from \"../../assets/ModelTextures\";\nimport { AssetKey, isAssetKey } from \"../../assets/AssetKey\";\nimport { ExtractableImageData } from \"../../ExtractableImageData\";\nimport { Materials } from \"../../Materials\";\nimport { MinecraftCubeTexture } from \"../../MinecraftCubeTexture\";\nimport { CUBE_FACES, CubeFace } from \"../../CubeFace\";\nimport { EntityLayer, EntityModel, EntityModelPart } from \"../EntityModel\";\nimport type { DoubleArray } from \"../../model/Model\";\nimport type { Maybe } from \"../../util/util\";\nimport { isMesh } from \"../../util/three\";\nimport type { EntityAnimation } from \"../EntityAnimation\";\nimport { EntityAnimationOptions, EntityAnimationPlayer, validateAnimationWeights } from \"./EntityAnimationPlayer\";\nimport type { PalettedTextures } from \"../../texture/PalettedTextures\";\nimport type { ItemGlint } from \"../../model/ItemGlint\";\n\nlet ItemGlintClass: typeof ItemGlint | undefined;\nlet PalettedTexturesClass: typeof PalettedTextures | undefined;\n\n/** Renders selected entity layers as named part groups. Create it through {@link MineRenderScene.addEntity}. */\nexport class EntityObject extends SceneObject {\n\n public readonly isEntityObject: true = true;\n\n public static readonly DEFAULT_OPTIONS: EntityObjectOptions = merge({}, SceneObject.DEFAULT_OPTIONS);\n public readonly options: EntityObjectOptions;\n\n private meshesCreated: boolean = false;\n private readonly geometries = new Set<BufferGeometry>();\n private readonly disposeWireframes: (() => void)[] = [];\n /** Scrolling materials are owned: their texture offset follows this entity's age. */\n private readonly scrollMaterials: { material: Material, offset: { set(x: number, y: number): unknown }, speed: [number, number] }[] = [];\n private scrollTicker: Maybe<number>;\n /** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */\n public age: number = 0;\n private readonly animationPlayers: { player: EntityAnimationPlayer, indices: number[] }[] = [];\n private readonly partPoses = new Map<Object3D, EntityModelPart[\"pose\"]>();\n private glint?: ItemGlint;\n\n constructor(readonly entity: EntityModel, options?: Partial<EntityObjectOptions>) {\n super();\n this.options = merge({}, EntityObject.DEFAULT_OPTIONS, options ?? {});\n this.addEventListener(\"added\", () => { this.updateScrollSubscription(); this.glint?.updateSubscription(!!this.parent); });\n this.addEventListener(\"removed\", () => { this.updateScrollSubscription(); this.glint?.updateSubscription(!!this.parent); });\n }\n\n /** An optional shared material replaces texture loading for every selected draw; its owner retains disposal. */\n async init(material?: Material): Promise<void> {\n this.createMeshes();\n if (material) {\n this.clearScrollMaterials();\n this.iterateAllMeshes(mesh => { mesh.material = material; });\n this.notifyDirty();\n } else {\n await this.applyTextures();\n const layers = Object.entries(this.entityLayers).filter(([, layer]) => layer.glint);\n const meshes: Mesh[] = [];\n for (const [name] of layers) this.getLayerGroup(name)?.traverse(object => { if (isMesh(object)) meshes.push(object); });\n if (meshes.length) {\n const ItemGlint = ItemGlintClass ??= (await import(\"../../model/ItemGlint\")).ItemGlint;\n this.glint = await ItemGlint.create(this, undefined, this.getTextureKey(layers[0][1]).root, meshes.map(mesh => ({ mesh })), \"armor\");\n this.glint.updateSubscription(!!this.parent);\n }\n }\n }\n\n dispose() {\n super.dispose();\n }\n\n public disposeAndRemoveAllChildren() {\n this.glint?.dispose();\n this.glint = undefined;\n this.clearScrollMaterials();\n for (const geometry of this.geometries) geometry.dispose();\n this.geometries.clear();\n for (const dispose of this.disposeWireframes.splice(0)) dispose();\n // The animated part groups are removed with the children.\n for (const { player } of this.animationPlayers.splice(0)) player.clear();\n this.partPoses.clear();\n super.disposeAndRemoveAllChildren();\n }\n\n private clearScrollMaterials() {\n Ticker.remove(this.scrollTicker);\n this.scrollTicker = undefined;\n for (const { material } of this.scrollMaterials.splice(0)) {\n (material as { map?: { dispose(): void } }).map?.dispose();\n material.dispose();\n }\n }\n\n private updateScrollSubscription() {\n if (this.parent && this.scrollMaterials.length) {\n if (this.scrollTicker === undefined) {\n this.scrollTicker = Ticker.add(() => {\n this.age++;\n this.updateScroll();\n });\n }\n } else {\n Ticker.remove(this.scrollTicker);\n this.scrollTicker = undefined;\n }\n }\n\n /** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */\n private updateScroll() {\n for (const { offset, speed } of this.scrollMaterials) {\n // Texture V points up here and down in vanilla.\n offset.set((this.age * speed[0]) % 1, 0 - (this.age * speed[1]) % 1);\n }\n this.notifyDirty();\n }\n\n //<editor-fold desc=\"ANIMATION\">\n\n /** The first active clip, until playback is stopped or the object is disposed. */\n public get animation(): Maybe<EntityAnimation> {\n return this.animationPlayers[0]?.player.animation;\n }\n\n /** Clips playing together, in the order passed to {@link playAnimations}. */\n public get activeAnimations(): readonly EntityAnimation[] {\n const animations: EntityAnimation[] = [];\n for (const { player, indices } of this.animationPlayers) {\n player.animations.forEach((animation, i) => { animations[indices[i]] = animation; });\n }\n return animations;\n }\n\n /** Weights of the active clips, in the same order as {@link activeAnimations}. */\n public get animationWeights(): readonly number[] {\n const weights: number[] = [];\n for (const { player, indices } of this.animationPlayers) {\n player.weights.forEach((weight, i) => { weights[indices[i]] = weight; });\n }\n return weights;\n }\n\n /** Seconds since the animation started, before looping. */\n public get animationTime(): number {\n return this.animationPlayers[0]?.player.time ?? 0;\n }\n\n /**\n * Plays a clip from {@link Entities.getAnimations}, replacing all active clips.\n * Offsets apply to the baked pose in the clip's layer (`main` by default) and its repeated draws.\n * A `main` clip also poses every selected layer without a clip of its own.\n * The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.\n */\n public playAnimation(animation: EntityAnimation, options?: EntityAnimationOptions): void {\n this.playAnimations([animation], options);\n }\n\n /**\n * Plays clips with a shared clock, adding their weighted offsets within each geometry layer.\n * Weights default to 1 and are not normalized. Selected layers without their own clip follow `main`.\n */\n public playAnimations(animations: readonly EntityAnimation[], options?: EntityAnimationOptions): void {\n const weights = validateAnimationWeights(options?.weights ?? animations.map(() => 1), animations.length);\n const selections = new Map<string, { animations: EntityAnimation[], names: string[], indices: number[] }>();\n animations.forEach((animation, index) => {\n const layer = animation.layer ?? \"main\";\n const names = Object.keys(this.entityLayers).filter(name => name.split(\"#\")[0] === layer);\n if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer \"${layer}\"`);\n let selection = selections.get(layer);\n if (!selection) selections.set(layer, selection = { animations: [], names, indices: [] });\n selection.animations.push(animation);\n selection.indices.push(index);\n });\n const main = selections.get(\"main\");\n if (main) main.names.push(...Object.keys(this.entityLayers).filter(name => !selections.has(name.split(\"#\")[0])));\n this.createMeshes();\n this.stopAnimation();\n for (const { animations: clips, names, indices } of selections.values()) {\n const player = new EntityAnimationPlayer();\n player.playAnimations(names.map(name => this.getLayerGroup(name)!), clips,\n { ...options, weights: indices.map(index => weights[index]) }, this.partPoses);\n this.animationPlayers.push({ player, indices });\n }\n this.notifyDirty();\n }\n\n /** Changes weights in active clip order, notifying the scene without restarting the shared clock. Has no effect without an animation. */\n public setAnimationWeights(weights: readonly number[]): void {\n if (!this.animationPlayers.length) return;\n const values = validateAnimationWeights(weights, this.activeAnimations.length);\n for (const { player, indices } of this.animationPlayers) player.setWeights(indices.map(index => values[index]));\n this.notifyDirty();\n }\n\n /** Stops all clips and restores the poses from before playback. */\n public stopAnimation(): void {\n const players = this.animationPlayers.splice(0);\n for (const { player } of players) player.stop();\n if (players.length) this.notifyDirty();\n }\n\n /** Poses the object at an explicit time in seconds. Has no effect without an animation. */\n public setAnimationTime(seconds: number): void {\n for (const { player } of this.animationPlayers) player.setTime(seconds);\n if (this.animationPlayers.length) this.notifyDirty();\n }\n\n /** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */\n public advanceAnimation(deltaSeconds: number): void {\n for (const { player } of this.animationPlayers) player.advance(deltaSeconds);\n if (this.animationPlayers.length) this.notifyDirty();\n }\n\n //</editor-fold>\n\n /** Finds a selected draw by its layer key, such as `main` or `main#2`, or returns `undefined`. */\n public getLayerGroup(name: string): Maybe<Object3D> {\n return super.getGroupByName(`layer:${name}`);\n }\n\n /** Finds a part name without `group:`. Supply `layerName` to restrict the search to one draw. */\n public getGroupByName(name: string, layerName?: string): Maybe<Object3D> {\n return layerName === undefined ? super.getGroupByName(name)\n : this.getLayerGroup(layerName)?.getObjectByName(`group:${name}`);\n }\n\n /** Finds a mesh name without `mesh:`. Supply `layerName` to restrict the search to one draw. */\n public getMeshByName(name: string, layerName?: string): Maybe<Mesh> {\n return layerName === undefined ? super.getMeshByName(name)\n : this.getLayerGroup(layerName)?.getObjectByName(`mesh:${name}`) as Maybe<Mesh>;\n }\n\n private get entityLayers(): Record<string, EntityLayer> {\n return this.entity.layers ?? { main: this.entity };\n }\n\n private getTextureKey(layer: EntityLayer): AssetKey {\n if (layer.texture) return layer.texture;\n const key = layer.key;\n return new AssetKey(\n key.namespace,\n isAssetKey(key) ? key.getFullPath() : key.path,\n \"textures\",\n \"entity\",\n \"assets\",\n \".png\"\n );\n }\n\n protected async loadTextures(layer: EntityLayer = this.entity): Promise<Maybe<ExtractableImageData>> {\n if (layer.palette) {\n const PalettedTextures = PalettedTexturesClass ??= (await import(\"../../texture/PalettedTextures\")).PalettedTextures;\n return PalettedTextures.get(this.getTextureKey(layer), layer.palette.key, layer.palette.permutation);\n }\n return ModelTextures.get(this.getTextureKey(layer));\n }\n\n protected createMeshes(force: boolean = false) {\n if (this.meshesCreated && !force) return;\n\n const modelRoot = new Object3D();\n let transformNode = modelRoot;\n // Keep Minecraft's model coordinates separate from caller placement and scale.\n const transform = this.options.flip === undefined ? this.entity.transform : undefined;\n if (transform) {\n // One position, rotation and scale cannot express nonuniform scale followed by rotation.\n // Nested nodes preserve each operation and avoid manual matrices, which leave bounds stale.\n for (const [index, op] of transform.entries()) {\n if (index > 0) {\n const child = new Object3D();\n transformNode.add(child);\n transformNode = child;\n }\n if (\"scale\" in op) transformNode.scale.set(...op.scale);\n else if (\"translate\" in op) transformNode.position.set(...op.translate);\n else transformNode.rotation.set(...op.rotate, \"ZYX\");\n }\n } else if (this.options.flip ?? true) {\n modelRoot.scale.set(-1, -1, 1);\n }\n this.add(modelRoot);\n Object.entries(this.entityLayers).forEach(([name, layer], index) => {\n const group = this.createGroup(`layer:${name}`);\n transformNode.add(group);\n const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);\n this.createPart(\"root\", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward, this.options.faces?.[name]);\n });\n this.meshesCreated = true;\n }\n\n private createPart(name: string, part: EntityModelPart, parent: Object3D, textureSize: DoubleArray, material: Material, renderOrder: number, inward: boolean = true, faces?: CubeFace[]) {\n const anchor = this.createGroup(name);\n anchor.position.fromArray(part.pose.offset);\n anchor.rotation.set(...part.pose.rotation, \"ZYX\");\n anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);\n this.partPoses.set(anchor, part.pose);\n parent.add(anchor);\n const size = part.texture ?? textureSize;\n\n for (const cube of part.cubes) {\n const [width, height, depth] = cube.size;\n const [growX, growY, growZ] = cube.grow ?? [0, 0, 0];\n const texture = new MinecraftCubeTexture(...cube.uv, ...size);\n const uv = size[0] === 0 || size[1] === 0 ? new Array<number>(48).fill(0) : texture.toUvArray(width, height, depth, cube.mirror);\n const geometry = this._getBoxGeometryForDimensionsAndUv(\n width + growX * 2, height + growY * 2, depth + growZ * 2, uv\n ).clone();\n this.geometries.add(geometry);\n geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);\n if (faces) {\n geometry.setIndex(Array.from(geometry.getIndex()!.array).filter((_, index) => faces.includes(CUBE_FACES[Math.floor(index / 6)])));\n geometry.clearGroups();\n }\n // Vanilla draws most entity render types without backface culling, e.g. chicken legs are only painted on faces seen from inside.\n // Zero-thickness cubes keep one face per side, as their coplanar faces would z-fight.\n if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {\n const index = Array.from(geometry.getIndex()!.array);\n geometry.setIndex(index.concat(index.slice().reverse()));\n }\n const mesh = this.createMesh(name, geometry, material);\n mesh.renderOrder = renderOrder;\n anchor.add(mesh);\n if (this.options.wireframe) this.disposeWireframes.push(addWireframeToMesh(geometry, mesh));\n }\n for (const [childName, child] of Object.entries(part.children)) {\n this.createPart(childName, child, anchor, size, material, renderOrder, inward, faces);\n }\n }\n\n protected async applyTextures() {\n this.clearScrollMaterials();\n const results = await Promise.allSettled(Object.entries(this.entityLayers).map(async ([name, layer]) => {\n const mode = layer.render ?? layer.layer.render ?? \"cutout\";\n const tint = (layer.tint === undefined ? undefined : this.options.tints?.[layer.tint]) ?? layer.color;\n const scroll = Materials.entityModeScroll(mode);\n const assetKeyStr = this.getTextureKey(layer).serialize();\n const keyStr = `entity:${ mode }:${ tint === undefined ? \"\" : new Color(tint).getHexString() }:${ assetKeyStr }`\n + (layer.palette ? `:${layer.palette.key.serialize()}:${layer.palette.permutation.serialize()}` : \"\");\n let mat = scroll ? undefined : Caching.materialCache.getIfPresent(keyStr);\n if (!mat) {\n const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);\n const imageData = await this.loadTextures(layer);\n if (!imageData) return;\n const canvas = (imageData.data as CanvasRenderingContext2D).canvas;\n const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);\n // A cache clear during decoding must not restore an older source's material.\n // Scrolling materials stay out of the cache, as their texture offset belongs to this entity.\n mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset\n ? Caching.materialCache.get(keyStr, createMaterial)\n : createMaterial();\n if (scroll) {\n this.scrollMaterials.push({ material: mat!, offset: (mat as MeshBasicMaterial).map!.offset, speed: scroll });\n }\n }\n this.getLayerGroup(name)?.traverse(object => {\n if (isMesh(object)) object.material = mat!;\n });\n }));\n if (!this.children.length) {\n // Disposed while the textures were loading: nothing is left to scroll.\n this.clearScrollMaterials();\n } else if (this.scrollMaterials.length) {\n this.updateScroll();\n }\n this.updateScrollSubscription();\n this.notifyDirty();\n const failure = results.find(result => result.status === \"rejected\");\n if (failure?.status === \"rejected\") throw failure.reason;\n }\n\n\n}\n\n/** Render settings passed to `scene.addEntity(entity, options)` or the EntityObject constructor. */\nexport interface EntityObjectOptions extends SceneObjectOptions {\n /**\n * `true` applies only vanilla's entity flip, scale (-1, -1, 1); `false` keeps raw model space.\n * By default the model's dataset transform is used, or the flip for models without one.\n */\n flip?: boolean;\n /** Colours for the dataset's tint labels, e.g. `{ wool_color: 0xf9801d }`; an absent label uses the draw's fixed colour, if any. */\n tints?: Record<string, ColorRepresentation>;\n /** Cube faces by layer key; omitted layers draw all six faces. */\n faces?: Record<string, CubeFace[]>;\n}\n\nexport function isEntityObject(obj: any): obj is EntityObject {\n return (<EntityObject>obj).isEntityObject;\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,9 @@
1
1
  // src/env/browser/BrowserEnv.ts
2
2
  import { Env } from "../../Env.mjs";
3
+ import { logger } from "../../util/log.mjs";
3
4
  import { BrowserCache } from "./BrowserCache.mjs";
4
5
  import { probeImageSize } from "./probeImageSize.mjs";
6
+ var log = logger("BrowserEnv");
5
7
  function lazyLocalForage(options) {
6
8
  let instance;
7
9
  const store = () => instance ?? (instance = import("localforage").then((module) => module.default.createInstance(options)));
@@ -17,7 +19,8 @@ function lazyLocalForage(options) {
17
19
  };
18
20
  }
19
21
  var BrowserEnv = class {
20
- constructor() {
22
+ constructor(options = {}) {
23
+ this.options = options;
21
24
  this.name = "browser";
22
25
  }
23
26
  createCanvas(width, height) {
@@ -46,14 +49,18 @@ var BrowserEnv = class {
46
49
  createWorker(name) {
47
50
  if (name !== "section" || typeof Worker === "undefined") return void 0;
48
51
  try {
52
+ const sectionWorker = this.options.sectionWorker;
53
+ if (typeof sectionWorker === "function") return sectionWorker();
54
+ if (sectionWorker !== void 0) return new Worker(sectionWorker, { type: "module" });
49
55
  return new Worker(new URL("./section.worker.mjs", import.meta.url), { type: "module" });
50
- } catch {
56
+ } catch (error) {
57
+ log.warn("Could not start the section worker, so sections build on the main thread. Pass sectionWorker to registerBrowserEnv to load it from another URL.", error);
51
58
  return void 0;
52
59
  }
53
60
  }
54
61
  };
55
- function registerBrowserEnv() {
56
- const env = new BrowserEnv();
62
+ function registerBrowserEnv(options) {
63
+ const env = new BrowserEnv(options);
57
64
  Env.register(env);
58
65
  return env;
59
66
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/env/browser/BrowserEnv.ts"],"sourcesContent":["import { Env, EnvProvider, ImageSizeInfo } from \"../../Env\";\nimport type { CompatCanvas, CompatImage } from \"../../canvas/CanvasCompat\";\nimport type { PersistentCache } from \"../../cache/PersistentCache\";\nimport { BrowserCache } from \"./BrowserCache\";\nimport { probeImageSize } from \"./probeImageSize\";\n\n/** A LocalForage that imports the library and opens the store on the first call. */\nfunction lazyLocalForage(options: LocalForageOptions): LocalForage {\n let instance: Promise<LocalForage> | undefined;\n const store = () => instance ??= import(\"localforage\").then(module => module.default.createInstance(options));\n return {\n ready: (...args: Parameters<LocalForage[\"ready\"]>) => store().then(value => value.ready(...args)),\n getItem: (...args: Parameters<LocalForage[\"getItem\"]>) => store().then(value => value.getItem(...args)),\n setItem: (...args: Parameters<LocalForage[\"setItem\"]>) => store().then(value => value.setItem(...args)),\n removeItem: (...args: Parameters<LocalForage[\"removeItem\"]>) => store().then(value => value.removeItem(...args)),\n clear: (...args: Parameters<LocalForage[\"clear\"]>) => store().then(value => value.clear(...args)),\n length: (...args: Parameters<LocalForage[\"length\"]>) => store().then(value => value.length(...args)),\n keys: (...args: Parameters<LocalForage[\"keys\"]>) => store().then(value => value.keys(...args)),\n iterate: (...args: Parameters<LocalForage[\"iterate\"]>) => store().then(value => value.iterate(...args))\n } as LocalForage;\n}\n\n/**\n * {@link EnvProvider} backed by the DOM. Uses nothing outside of standard browser APIs and\n * localforage, so it stays free of Node polyfills.\n */\nexport class BrowserEnv implements EnvProvider {\n\n public readonly name = \"browser\";\n\n createCanvas(width: number, height: number): CompatCanvas {\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n return canvas;\n }\n\n createImage(width?: number, height?: number): CompatImage {\n const image = document.createElement(\"img\");\n image.crossOrigin = \"anonymous\";\n if (width) image.width = width;\n if (height) image.height = height;\n return image;\n }\n\n imageSize(data: Uint8Array): ImageSizeInfo {\n return probeImageSize(data);\n }\n\n openCache(name: string, version: number): PersistentCache {\n return new BrowserCache(lazyLocalForage({\n // IndexedDB schema upgrades retain records; each cache generation needs its own database.\n name: name + version,\n version: version\n }));\n }\n\n createWorker(name: \"section\"): Worker | undefined {\n if (name !== \"section\" || typeof Worker === \"undefined\") return undefined;\n try {\n // Keep the literal URL so bundlers emit the worker file next to the entry.\n return new Worker(new URL(\"./section.worker.mjs\", import.meta.url), { type: \"module\" });\n } catch {\n // No import.meta.url outside ESM, or a cross-origin module worker.\n return undefined;\n }\n }\n\n}\n\n/** Installs the browser provider. The browser package entry calls this automatically. */\nexport function registerBrowserEnv(): BrowserEnv {\n const env = new BrowserEnv();\n Env.register(env);\n return env;\n}\n"],"mappings":";AAAA,SAAS,WAAuC;AAGhD,SAAS,oBAAoB;AAC7B,SAAS,sBAAsB;AAG/B,SAAS,gBAAgB,SAA0C;AAC/D,MAAI;AACJ,QAAM,QAAQ,MAAM,wBAAa,OAAO,aAAa,EAAE,KAAK,YAAU,OAAO,QAAQ,eAAe,OAAO,CAAC;AAC5G,SAAO;AAAA,IACH,OAAO,IAAI,SAA2C,MAAM,EAAE,KAAK,WAAS,MAAM,MAAM,GAAG,IAAI,CAAC;AAAA,IAChG,SAAS,IAAI,SAA6C,MAAM,EAAE,KAAK,WAAS,MAAM,QAAQ,GAAG,IAAI,CAAC;AAAA,IACtG,SAAS,IAAI,SAA6C,MAAM,EAAE,KAAK,WAAS,MAAM,QAAQ,GAAG,IAAI,CAAC;AAAA,IACtG,YAAY,IAAI,SAAgD,MAAM,EAAE,KAAK,WAAS,MAAM,WAAW,GAAG,IAAI,CAAC;AAAA,IAC/G,OAAO,IAAI,SAA2C,MAAM,EAAE,KAAK,WAAS,MAAM,MAAM,GAAG,IAAI,CAAC;AAAA,IAChG,QAAQ,IAAI,SAA4C,MAAM,EAAE,KAAK,WAAS,MAAM,OAAO,GAAG,IAAI,CAAC;AAAA,IACnG,MAAM,IAAI,SAA0C,MAAM,EAAE,KAAK,WAAS,MAAM,KAAK,GAAG,IAAI,CAAC;AAAA,IAC7F,SAAS,IAAI,SAA6C,MAAM,EAAE,KAAK,WAAS,MAAM,QAAQ,GAAG,IAAI,CAAC;AAAA,EAC1G;AACJ;AAMO,IAAM,aAAN,MAAwC;AAAA,EAAxC;AAEH,SAAgB,OAAO;AAAA;AAAA,EAEvB,aAAa,OAAe,QAA8B;AACtD,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,QAAQ;AACf,WAAO,SAAS;AAChB,WAAO;AAAA,EACX;AAAA,EAEA,YAAY,OAAgB,QAA8B;AACtD,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,cAAc;AACpB,QAAI,MAAO,OAAM,QAAQ;AACzB,QAAI,OAAQ,OAAM,SAAS;AAC3B,WAAO;AAAA,EACX;AAAA,EAEA,UAAU,MAAiC;AACvC,WAAO,eAAe,IAAI;AAAA,EAC9B;AAAA,EAEA,UAAU,MAAc,SAAkC;AACtD,WAAO,IAAI,aAAa,gBAAgB;AAAA;AAAA,MAEpC,MAAM,OAAO;AAAA,MACb;AAAA,IACJ,CAAC,CAAC;AAAA,EACN;AAAA,EAEA,aAAa,MAAqC;AAC9C,QAAI,SAAS,aAAa,OAAO,WAAW,YAAa,QAAO;AAChE,QAAI;AAEA,aAAO,IAAI,OAAO,IAAI,IAAI,wBAAwB,YAAY,GAAG,GAAG,EAAE,MAAM,SAAS,CAAC;AAAA,IAC1F,QAAQ;AAEJ,aAAO;AAAA,IACX;AAAA,EACJ;AAEJ;AAGO,SAAS,qBAAiC;AAC7C,QAAM,MAAM,IAAI,WAAW;AAC3B,MAAI,SAAS,GAAG;AAChB,SAAO;AACX;","names":[]}
1
+ {"version":3,"sources":["../../../../../src/env/browser/BrowserEnv.ts"],"sourcesContent":["import { Env, EnvProvider, ImageSizeInfo } from \"../../Env\";\nimport type { CompatCanvas, CompatImage } from \"../../canvas/CanvasCompat\";\nimport type { PersistentCache } from \"../../cache/PersistentCache\";\nimport { logger } from \"../../util/log\";\nimport { BrowserCache } from \"./BrowserCache\";\nimport { probeImageSize } from \"./probeImageSize\";\n\nconst log = logger(\"BrowserEnv\");\n\n/** Settings for {@link BrowserEnv} and {@link registerBrowserEnv}. */\nexport interface BrowserEnvOptions {\n /**\n * Section worker script, as a URL, or a function that creates the worker.\n * Set it when the bundle has no `import.meta.url`, such as the script-tag build: serve\n * `minerender/section.worker` from the page's origin and pass its URL.\n * Register before creating a world; the worker starts on the first section build.\n */\n sectionWorker?: string | URL | (() => Worker);\n}\n\n/** A LocalForage that imports the library and opens the store on the first call. */\nfunction lazyLocalForage(options: LocalForageOptions): LocalForage {\n let instance: Promise<LocalForage> | undefined;\n const store = () => instance ??= import(\"localforage\").then(module => module.default.createInstance(options));\n return {\n ready: (...args: Parameters<LocalForage[\"ready\"]>) => store().then(value => value.ready(...args)),\n getItem: (...args: Parameters<LocalForage[\"getItem\"]>) => store().then(value => value.getItem(...args)),\n setItem: (...args: Parameters<LocalForage[\"setItem\"]>) => store().then(value => value.setItem(...args)),\n removeItem: (...args: Parameters<LocalForage[\"removeItem\"]>) => store().then(value => value.removeItem(...args)),\n clear: (...args: Parameters<LocalForage[\"clear\"]>) => store().then(value => value.clear(...args)),\n length: (...args: Parameters<LocalForage[\"length\"]>) => store().then(value => value.length(...args)),\n keys: (...args: Parameters<LocalForage[\"keys\"]>) => store().then(value => value.keys(...args)),\n iterate: (...args: Parameters<LocalForage[\"iterate\"]>) => store().then(value => value.iterate(...args))\n } as LocalForage;\n}\n\n/**\n * {@link EnvProvider} backed by the DOM. Uses nothing outside of standard browser APIs and\n * localforage, so it stays free of Node polyfills.\n */\nexport class BrowserEnv implements EnvProvider {\n\n public readonly name = \"browser\";\n\n constructor(public readonly options: BrowserEnvOptions = {}) {}\n\n createCanvas(width: number, height: number): CompatCanvas {\n const canvas = document.createElement(\"canvas\");\n canvas.width = width;\n canvas.height = height;\n return canvas;\n }\n\n createImage(width?: number, height?: number): CompatImage {\n const image = document.createElement(\"img\");\n image.crossOrigin = \"anonymous\";\n if (width) image.width = width;\n if (height) image.height = height;\n return image;\n }\n\n imageSize(data: Uint8Array): ImageSizeInfo {\n return probeImageSize(data);\n }\n\n openCache(name: string, version: number): PersistentCache {\n return new BrowserCache(lazyLocalForage({\n // IndexedDB schema upgrades retain records; each cache generation needs its own database.\n name: name + version,\n version: version\n }));\n }\n\n createWorker(name: \"section\"): Worker | undefined {\n if (name !== \"section\" || typeof Worker === \"undefined\") return undefined;\n try {\n const sectionWorker = this.options.sectionWorker;\n if (typeof sectionWorker === \"function\") return sectionWorker();\n if (sectionWorker !== undefined) return new Worker(sectionWorker, { type: \"module\" });\n // Keep the literal URL so bundlers emit the worker file next to the entry.\n return new Worker(new URL(\"./section.worker.mjs\", import.meta.url), { type: \"module\" });\n } catch (error) {\n log.warn(\"Could not start the section worker, so sections build on the main thread. Pass sectionWorker to registerBrowserEnv to load it from another URL.\", error);\n return undefined;\n }\n }\n\n}\n\n/** Installs the browser provider. The browser package entry calls this automatically. */\nexport function registerBrowserEnv(options?: BrowserEnvOptions): BrowserEnv {\n const env = new BrowserEnv(options);\n Env.register(env);\n return env;\n}\n"],"mappings":";AAAA,SAAS,WAAuC;AAGhD,SAAS,cAAc;AACvB,SAAS,oBAAoB;AAC7B,SAAS,sBAAsB;AAE/B,IAAM,MAAM,OAAO,YAAY;AAc/B,SAAS,gBAAgB,SAA0C;AAC/D,MAAI;AACJ,QAAM,QAAQ,MAAM,wBAAa,OAAO,aAAa,EAAE,KAAK,YAAU,OAAO,QAAQ,eAAe,OAAO,CAAC;AAC5G,SAAO;AAAA,IACH,OAAO,IAAI,SAA2C,MAAM,EAAE,KAAK,WAAS,MAAM,MAAM,GAAG,IAAI,CAAC;AAAA,IAChG,SAAS,IAAI,SAA6C,MAAM,EAAE,KAAK,WAAS,MAAM,QAAQ,GAAG,IAAI,CAAC;AAAA,IACtG,SAAS,IAAI,SAA6C,MAAM,EAAE,KAAK,WAAS,MAAM,QAAQ,GAAG,IAAI,CAAC;AAAA,IACtG,YAAY,IAAI,SAAgD,MAAM,EAAE,KAAK,WAAS,MAAM,WAAW,GAAG,IAAI,CAAC;AAAA,IAC/G,OAAO,IAAI,SAA2C,MAAM,EAAE,KAAK,WAAS,MAAM,MAAM,GAAG,IAAI,CAAC;AAAA,IAChG,QAAQ,IAAI,SAA4C,MAAM,EAAE,KAAK,WAAS,MAAM,OAAO,GAAG,IAAI,CAAC;AAAA,IACnG,MAAM,IAAI,SAA0C,MAAM,EAAE,KAAK,WAAS,MAAM,KAAK,GAAG,IAAI,CAAC;AAAA,IAC7F,SAAS,IAAI,SAA6C,MAAM,EAAE,KAAK,WAAS,MAAM,QAAQ,GAAG,IAAI,CAAC;AAAA,EAC1G;AACJ;AAMO,IAAM,aAAN,MAAwC;AAAA,EAI3C,YAA4B,UAA6B,CAAC,GAAG;AAAjC;AAF5B,SAAgB,OAAO;AAAA,EAEuC;AAAA,EAE9D,aAAa,OAAe,QAA8B;AACtD,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,WAAO,QAAQ;AACf,WAAO,SAAS;AAChB,WAAO;AAAA,EACX;AAAA,EAEA,YAAY,OAAgB,QAA8B;AACtD,UAAM,QAAQ,SAAS,cAAc,KAAK;AAC1C,UAAM,cAAc;AACpB,QAAI,MAAO,OAAM,QAAQ;AACzB,QAAI,OAAQ,OAAM,SAAS;AAC3B,WAAO;AAAA,EACX;AAAA,EAEA,UAAU,MAAiC;AACvC,WAAO,eAAe,IAAI;AAAA,EAC9B;AAAA,EAEA,UAAU,MAAc,SAAkC;AACtD,WAAO,IAAI,aAAa,gBAAgB;AAAA;AAAA,MAEpC,MAAM,OAAO;AAAA,MACb;AAAA,IACJ,CAAC,CAAC;AAAA,EACN;AAAA,EAEA,aAAa,MAAqC;AAC9C,QAAI,SAAS,aAAa,OAAO,WAAW,YAAa,QAAO;AAChE,QAAI;AACA,YAAM,gBAAgB,KAAK,QAAQ;AACnC,UAAI,OAAO,kBAAkB,WAAY,QAAO,cAAc;AAC9D,UAAI,kBAAkB,OAAW,QAAO,IAAI,OAAO,eAAe,EAAE,MAAM,SAAS,CAAC;AAEpF,aAAO,IAAI,OAAO,IAAI,IAAI,wBAAwB,YAAY,GAAG,GAAG,EAAE,MAAM,SAAS,CAAC;AAAA,IAC1F,SAAS,OAAO;AACZ,UAAI,KAAK,mJAAmJ,KAAK;AACjK,aAAO;AAAA,IACX;AAAA,EACJ;AAEJ;AAGO,SAAS,mBAAmB,SAAyC;AACxE,QAAM,MAAM,IAAI,WAAW,OAAO;AAClC,MAAI,SAAS,GAAG;AAChB,SAAO;AACX;","names":[]}