@nodecraft/rendermite 1.0.5 → 1.0.6

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 (110) hide show
  1. package/README.md +5 -0
  2. package/dist/atlas/registry.d.ts +3 -3
  3. package/dist/atlas/sources.d.ts +1 -1
  4. package/dist/{blend-Qvrn6YgK.d.ts → blend-CyDIxCne.d.ts} +1 -1
  5. package/dist/cache-Cr2ON3RQ.js +66 -0
  6. package/dist/cli.js +12 -6
  7. package/dist/compose-CQCb2LVv.js +104 -0
  8. package/dist/descriptor-DWebtkI1.js +26 -0
  9. package/dist/{discovery-D89pVVJA.d.ts → discovery-wiJBGryo.d.ts} +1 -1
  10. package/dist/dynamic/generators.d.ts +1 -1
  11. package/dist/dynamic/generators.js +1 -1
  12. package/dist/{encode-3u49i-eD.js → encode-D6dQu2dJ.js} +16 -4
  13. package/dist/{encode-C5kdAm45.d.ts → encode-DaNQF28M.d.ts} +1 -1
  14. package/dist/{entity-fallback-DfL0_eyf.js → entity-fallback-BRCeGKBT.js} +1 -1
  15. package/dist/{face-CpVdnf-w.d.ts → face-BIYg14TE.d.ts} +10 -4
  16. package/dist/{face-D-N1amV4.js → face-DmCiHUd5.js} +23 -10
  17. package/dist/{generators-CcVRG30y.js → generators-BlG4KmtP.js} +1 -1
  18. package/dist/{generators-CCB8h0mP.d.ts → generators-DhRov4RB.d.ts} +1 -1
  19. package/dist/{geo-Dq2zve09.js → geo-Diky41Tw.js} +6 -3
  20. package/dist/index.d.ts +14 -14
  21. package/dist/index.js +11 -11
  22. package/dist/{item-styles-DJ3LWZS2.js → item-styles-upgEO1yP.js} +1 -1
  23. package/dist/items/discovery.d.ts +1 -1
  24. package/dist/{jar-6T3xdgaL.d.ts → jar-CFkA-VgT.d.ts} +2 -1
  25. package/dist/{jar-Bt3i0ls4.js → jar-D9z-X7tA.js} +12 -12
  26. package/dist/{legacy-reshape-CewShfF3.js → legacy-reshape-C05SfAPR.js} +1 -1
  27. package/dist/{loader-A-BZa8J4.js → loader-B8NJO7pR.js} +12 -3
  28. package/dist/{loader-CBzn3Koc.js → loader-CfXMxcEV.js} +37 -7
  29. package/dist/{loader-C-6QN3xv.d.ts → loader-D22zZME7.d.ts} +2 -2
  30. package/dist/{loader-TFFNV4Jl.d.ts → loader-Myy22TDL.d.ts} +8 -2
  31. package/dist/{manager-dfI7b9N4.js → manager-CkletR5K.js} +29 -2
  32. package/dist/{manager-CoZaeQTu.d.ts → manager-Cv1NeFyF.d.ts} +28 -1
  33. package/dist/models/loader.d.ts +1 -1
  34. package/dist/models/loader.js +1 -1
  35. package/dist/mods/prepare.d.ts +1 -1
  36. package/dist/mods/prepare.js +1 -1
  37. package/dist/mods/synthesize.d.ts +2 -2
  38. package/dist/mods/synthesize.js +1 -1
  39. package/dist/mods/tints.d.ts +2 -2
  40. package/dist/mods/tints.js +1 -1
  41. package/dist/output/encode.d.ts +1 -1
  42. package/dist/output/encode.js +1 -1
  43. package/dist/output/item-styles.js +1 -1
  44. package/dist/pipeline-BIk1RRIp.js +221 -0
  45. package/dist/pipeline-zq-yU3Te.d.ts +58 -0
  46. package/dist/pool-CKGp1qup.js +131 -0
  47. package/dist/{prepare-BeUpXwaP.js → prepare-BESRrh6K.js} +4 -4
  48. package/dist/{prepare-gfR1aIjt.d.ts → prepare-CPxO0kKz.d.ts} +1 -1
  49. package/dist/{prepare-C8wRjAXP.js → prepare-Cc8QZ3j0.js} +4 -4
  50. package/dist/{prepare-wfWtaz_X.d.ts → prepare-Cs6QDqie.d.ts} +1 -1
  51. package/dist/{rasterizer-BHWDrmGz.js → rasterizer-76qO8TDh.js} +42 -4
  52. package/dist/{rasterizer-Dh35qXbn.d.ts → rasterizer-yqJkicm1.d.ts} +21 -2
  53. package/dist/render/blend.d.ts +1 -1
  54. package/dist/render/compose.d.ts +2 -2
  55. package/dist/render/compose.js +1 -1
  56. package/dist/render/entity-fallback.d.ts +6 -6
  57. package/dist/render/entity-fallback.js +1 -1
  58. package/dist/render/face.d.ts +2 -2
  59. package/dist/render/face.js +1 -1
  60. package/dist/render/fluid-bucket.d.ts +2 -2
  61. package/dist/render/geo.d.ts +4 -4
  62. package/dist/render/geo.js +1 -1
  63. package/dist/render/legacy-tints.d.ts +2 -2
  64. package/dist/render/obj.d.ts +5 -5
  65. package/dist/render/obj.js +1 -1
  66. package/dist/render/pipeline.d.ts +2 -0
  67. package/dist/render/pipeline.js +2 -0
  68. package/dist/render/rasterizer.d.ts +2 -2
  69. package/dist/render/rasterizer.js +2 -2
  70. package/dist/render/renderer.d.ts +2 -2
  71. package/dist/render/renderer.js +1 -1
  72. package/dist/render/tints.d.ts +1 -1
  73. package/dist/{renderer-LDhBNHcl.js → renderer-CjT19tHd.js} +130 -53
  74. package/dist/{renderer-nbMCw1Pl.d.ts → renderer-DVsZHAvf.d.ts} +23 -6
  75. package/dist/resources/cache.d.ts +30 -0
  76. package/dist/resources/cache.js +2 -0
  77. package/dist/resources/descriptor.d.ts +2 -0
  78. package/dist/resources/descriptor.js +2 -0
  79. package/dist/resources/jar.d.ts +1 -1
  80. package/dist/resources/jar.js +1 -1
  81. package/dist/resources/manager.d.ts +1 -1
  82. package/dist/resources/manager.js +1 -1
  83. package/dist/resources/synthetic.d.ts +1 -1
  84. package/dist/resources/synthetic.js +1 -1
  85. package/dist/resources/zip-reader.d.ts +5 -0
  86. package/dist/resources/zip-reader.js +2 -0
  87. package/dist/run-BnICOF4I.js +209 -0
  88. package/dist/{run-BlSZw9Qk.d.ts → run-CKUtynTy.d.ts} +12 -2
  89. package/dist/run.d.ts +1 -1
  90. package/dist/run.js +1 -1
  91. package/dist/{sources-DH9dk3KF.d.ts → sources-B9X9w3qP.d.ts} +1 -1
  92. package/dist/{synthesize-CRgSEmEp.js → synthesize-3Q0aaOnK.js} +1 -1
  93. package/dist/{synthetic-CDsj--li.d.ts → synthetic-Qk-BSUXO.d.ts} +5 -1
  94. package/dist/{synthetic-DC2bSnGe.js → synthetic-ZAUjXT7E.js} +0 -0
  95. package/dist/textures/loader.d.ts +1 -1
  96. package/dist/textures/loader.js +1 -1
  97. package/dist/{tints-CuG6GwQJ.js → tints-B8UJmZMu.js} +2 -2
  98. package/dist/{tints-txt-8xI5.d.ts → tints-DLBExVWN.d.ts} +2 -2
  99. package/dist/versions/legacy-reshape.d.ts +1 -1
  100. package/dist/versions/legacy-reshape.js +1 -1
  101. package/dist/versions/prepare.d.ts +1 -1
  102. package/dist/versions/prepare.js +1 -1
  103. package/dist/workers/pool.d.ts +36 -5
  104. package/dist/workers/pool.js +2 -67
  105. package/dist/workers/render-worker.d.ts +15 -0
  106. package/dist/workers/render-worker.js +40 -0
  107. package/dist/zip-reader-BSbJKUT1.js +156 -0
  108. package/package.json +4 -2
  109. package/dist/compose-qjhyBvnS.js +0 -41
  110. package/dist/run-CfnWIRY4.js +0 -316
@@ -1,6 +1,6 @@
1
1
  import { n as ResourceLocator } from "./locator-ycZzh_6z.js";
2
- import { r as ResourceKind } from "./manager-dfI7b9N4.js";
3
- import { open } from "yauzl";
2
+ import { r as ResourceKind } from "./manager-CkletR5K.js";
3
+ import { t as openZip } from "./zip-reader-BSbJKUT1.js";
4
4
  //#region src/resources/jar.ts
5
5
  /**
6
6
  * Reads resources directly out of a jar/zip — no extraction step, unlike the
@@ -19,15 +19,9 @@ var JarResourceManager = class {
19
19
  this.jarPath = jarPath;
20
20
  }
21
21
  getIndex() {
22
- this.index ??= new Promise((resolve, reject) => {
23
- open(this.jarPath, {
24
- lazyEntries: true,
25
- autoClose: false
26
- }, (err, zip) => {
27
- if (err) {
28
- reject(err);
29
- return;
30
- }
22
+ this.index ??= (async () => {
23
+ const zip = await openZip(this.jarPath);
24
+ return new Promise((resolve, reject) => {
31
25
  const entries = /* @__PURE__ */ new Map();
32
26
  const entriesLower = /* @__PURE__ */ new Map();
33
27
  const namespaces = /* @__PURE__ */ new Set();
@@ -55,7 +49,7 @@ var JarResourceManager = class {
55
49
  zip.on("error", reject);
56
50
  zip.readEntry();
57
51
  });
58
- });
52
+ })();
59
53
  return this.index;
60
54
  }
61
55
  entryPath(kind, locator) {
@@ -108,6 +102,12 @@ var JarResourceManager = class {
108
102
  async listNamespaces() {
109
103
  return [...(await this.getIndex()).namespaces].toSorted((left, right) => left.localeCompare(right));
110
104
  }
105
+ describe() {
106
+ return {
107
+ kind: "jar",
108
+ path: this.jarPath
109
+ };
110
+ }
111
111
  async close() {
112
112
  if (this.index) {
113
113
  (await this.index).zip.close();
@@ -1,4 +1,4 @@
1
- import { n as MapResourceManager } from "./synthetic-DC2bSnGe.js";
1
+ import { n as MapResourceManager } from "./synthetic-ZAUjXT7E.js";
2
2
  import { open } from "yauzl";
3
3
  import sharp from "sharp";
4
4
  //#region src/versions/legacy-reshape.ts
@@ -1,4 +1,5 @@
1
1
  import { n as ResourceLocator } from "./locator-ycZzh_6z.js";
2
+ import { t as LruCache } from "./cache-Cr2ON3RQ.js";
2
3
  //#region src/models/loader.ts
3
4
  var ModelResolutionError = class extends Error {};
4
5
  const MAX_PARENT_DEPTH = 64;
@@ -248,12 +249,20 @@ function salvageJson(text) {
248
249
  }
249
250
  return null;
250
251
  }
252
+ /**
253
+ * Resolved models and their source JSON are small but there are a lot of them:
254
+ * a full modded run walks thousands of namespaces in one process, so the caches
255
+ * are bounded rather than kept for the life of the run.
256
+ */
257
+ const MAX_CACHED_MODELS = 4096;
251
258
  var ModelLoader = class {
252
259
  resources;
253
- cache = /* @__PURE__ */ new Map();
254
- jsonCache = /* @__PURE__ */ new Map();
255
- constructor(resources) {
260
+ cache;
261
+ jsonCache;
262
+ constructor(resources, maxCachedModels = MAX_CACHED_MODELS) {
256
263
  this.resources = resources;
264
+ this.cache = new LruCache(maxCachedModels);
265
+ this.jsonCache = new LruCache(maxCachedModels);
257
266
  }
258
267
  readModelJson(locator) {
259
268
  const key = locator.toString();
@@ -1,6 +1,10 @@
1
+ import { t as LruCache } from "./cache-Cr2ON3RQ.js";
1
2
  import sharp from "sharp";
2
3
  //#region src/textures/loader.ts
3
4
  var TextureResolutionError = class extends Error {};
5
+ /** Decoded-pixel budget and hard entry cap for one loader's texture cache. */
6
+ const MAX_TEXTURE_CACHE_BYTES = 134217728;
7
+ const MAX_TEXTURE_CACHE_ENTRIES = 8192;
4
8
  /**
5
9
  * Animation-aware texture access: frame extraction over strips and grids with
6
10
  * mcmeta frame lists, per-frame times, and interpolation (upstream semantics:
@@ -42,6 +46,25 @@ var AnimatedTexture = class {
42
46
  }
43
47
  return this.frameCount * frameTime;
44
48
  }
49
+ /**
50
+ * Ticks within one cycle at which the displayed frame changes. Used to emit
51
+ * exactly the frames an animation actually has instead of walking every tick
52
+ * of a combined timeline that can run to tens of thousands.
53
+ */
54
+ frameStartTicks() {
55
+ const animation = this.meta?.animation;
56
+ if (!animation || this.frameCount <= 1) return [0];
57
+ const frameTime = animation.frametime ?? 1;
58
+ const frames = animation.frames;
59
+ if (!frames?.length) return Array.from({ length: this.frameCount }, (_, index) => index * frameTime);
60
+ const starts = [];
61
+ let tick = 0;
62
+ for (const entry of frames) {
63
+ starts.push(tick);
64
+ tick += typeof entry === "number" ? frameTime : entry.time ?? frameTime;
65
+ }
66
+ return starts;
67
+ }
45
68
  /** Which physical frame index shows at a tick, and the interpolation factor. */
46
69
  resolveFrame(tick) {
47
70
  const animation = this.meta?.animation;
@@ -107,10 +130,14 @@ var AnimatedTexture = class {
107
130
  };
108
131
  var TextureLoader = class {
109
132
  resources;
110
- cache = /* @__PURE__ */ new Map();
133
+ cache;
111
134
  atlas = null;
112
- constructor(resources) {
135
+ constructor(resources, maxCacheBytes = MAX_TEXTURE_CACHE_BYTES) {
113
136
  this.resources = resources;
137
+ this.cache = new LruCache(MAX_TEXTURE_CACHE_ENTRIES, {
138
+ maxWeight: maxCacheBytes,
139
+ weigh: (pending) => pending.bytes ?? 0
140
+ });
114
141
  }
115
142
  async decode(locator) {
116
143
  let raw = await this.resources.getResource("texture", locator);
@@ -183,11 +210,14 @@ var TextureLoader = class {
183
210
  */
184
211
  async load(locator) {
185
212
  const key = locator.toString();
186
- let pending = this.cache.get(key);
187
- if (!pending) {
188
- pending = this.decode(locator);
189
- this.cache.set(key, pending);
190
- }
213
+ const cached = this.cache.get(key);
214
+ if (cached) return cached;
215
+ const pending = this.decode(locator);
216
+ this.cache.set(key, pending);
217
+ pending.then((texture) => {
218
+ Object.assign(pending, { bytes: texture ? texture.data.length : 0 });
219
+ this.cache.settle(key, pending);
220
+ }).catch(() => {});
191
221
  return pending;
192
222
  }
193
223
  };
@@ -1,5 +1,5 @@
1
1
  import { n as ResourceLocator } from "./locator-jDbdUeTd.js";
2
- import { a as ResourceManager } from "./manager-CoZaeQTu.js";
2
+ import { a as ResourceManager } from "./manager-Cv1NeFyF.js";
3
3
  import { c as ModelJson, n as DisplayTransformJson, o as ModelElementJson, t as DisplayPosition } from "./types-COGbtA1t.js";
4
4
  //#region src/models/loader.d.ts
5
5
  /**
@@ -54,7 +54,7 @@ declare class ModelLoader {
54
54
  private readonly resources;
55
55
  private readonly cache;
56
56
  private readonly jsonCache;
57
- constructor(resources: ResourceManager);
57
+ constructor(resources: ResourceManager, maxCachedModels?: number);
58
58
  private readModelJson;
59
59
  private loadModelJson;
60
60
  private resolve;
@@ -1,5 +1,5 @@
1
1
  import { n as ResourceLocator } from "./locator-jDbdUeTd.js";
2
- import { a as ResourceManager } from "./manager-CoZaeQTu.js";
2
+ import { a as ResourceManager } from "./manager-Cv1NeFyF.js";
3
3
  //#region src/textures/loader.d.ts
4
4
  /** Structural interface for atlas resolvers (avoids a circular module edge). */
5
5
  interface AtlasResolverLike {
@@ -48,6 +48,12 @@ declare class AnimatedTexture {
48
48
  get interpolated(): boolean;
49
49
  /** Total animation length in game ticks (1 for unanimated). */
50
50
  get tickLength(): number;
51
+ /**
52
+ * Ticks within one cycle at which the displayed frame changes. Used to emit
53
+ * exactly the frames an animation actually has instead of walking every tick
54
+ * of a combined timeline that can run to tens of thousands.
55
+ */
56
+ frameStartTicks(): number[];
51
57
  /** Which physical frame index shows at a tick, and the interpolation factor. */
52
58
  resolveFrame(tick: number): {
53
59
  frame: number;
@@ -62,7 +68,7 @@ declare class TextureLoader {
62
68
  private readonly resources;
63
69
  private readonly cache;
64
70
  private atlas;
65
- constructor(resources: ResourceManager);
71
+ constructor(resources: ResourceManager, maxCacheBytes?: number);
66
72
  private decode;
67
73
  private readMeta;
68
74
  /**
@@ -1,7 +1,7 @@
1
1
  import { n as ResourceLocator } from "./locator-ycZzh_6z.js";
2
2
  import path from "node:path";
3
3
  import { existsSync } from "node:fs";
4
- import { readFile, readdir } from "node:fs/promises";
4
+ import { readFile, readdir, stat } from "node:fs/promises";
5
5
  //#region src/resources/manager.ts
6
6
  /**
7
7
  * A category of resource inside a pack, mapping to a directory under
@@ -65,7 +65,11 @@ var FolderResourceManager = class {
65
65
  }
66
66
  }
67
67
  async hasResource(kind, locator) {
68
- return await this.getResource(kind, locator) !== null;
68
+ try {
69
+ return (await stat(this.resolve(kind, locator))).isFile();
70
+ } catch {
71
+ return false;
72
+ }
69
73
  }
70
74
  async getAllResources(kind, locator) {
71
75
  const resource = await this.getResource(kind, locator);
@@ -102,6 +106,12 @@ var FolderResourceManager = class {
102
106
  throw err;
103
107
  }
104
108
  }
109
+ describe() {
110
+ return {
111
+ kind: "folder",
112
+ root: this.root
113
+ };
114
+ }
105
115
  };
106
116
  /**
107
117
  * Layers several managers; earlier managers win, matching resource-pack precedence.
@@ -145,6 +155,23 @@ var LayeredResourceManager = class {
145
155
  for (const layer of this.layers) for (const namespace of await layer.listNamespaces()) namespaces.add(namespace);
146
156
  return [...namespaces].toSorted((left, right) => left.localeCompare(right));
147
157
  }
158
+ describe() {
159
+ const layers = [];
160
+ for (const layer of this.layers) {
161
+ const described = describeLayer(layer);
162
+ if (!described) return null;
163
+ layers.push(described);
164
+ }
165
+ return {
166
+ kind: "layered",
167
+ layers
168
+ };
169
+ }
148
170
  };
171
+ /** Local copy of describeResources, avoiding an import cycle with descriptor.ts. */
172
+ function describeLayer(manager) {
173
+ const describable = manager;
174
+ return typeof describable.describe === "function" ? describable.describe() : null;
175
+ }
149
176
  //#endregion
150
177
  export { LayeredResourceManager as n, ResourceKind as r, FolderResourceManager as t };
@@ -1,4 +1,29 @@
1
1
  import { n as ResourceLocator } from "./locator-jDbdUeTd.js";
2
+ //#region src/resources/descriptor.d.ts
3
+ type ResourceDescriptor = {
4
+ kind: 'folder';
5
+ root: string;
6
+ } | {
7
+ kind: 'jar';
8
+ path: string;
9
+ } | {
10
+ kind: 'map';
11
+ entries: Array<[string, Uint8Array]>;
12
+ } | {
13
+ kind: 'layered';
14
+ layers: ResourceDescriptor[];
15
+ } | {
16
+ kind: 'kindFiltered';
17
+ inner: ResourceDescriptor;
18
+ kinds: ResourceKindName[];
19
+ };
20
+ /** Managers that can cross a worker boundary implement this. */
21
+ interface DescribableResourceManager extends ResourceManager {
22
+ describe(): ResourceDescriptor | null;
23
+ }
24
+ declare function describeResources(manager: ResourceManager): ResourceDescriptor | null;
25
+ declare function restoreResources(descriptor: ResourceDescriptor): ResourceManager;
26
+ //#endregion
2
27
  //#region src/resources/manager.d.ts
3
28
  /**
4
29
  * A category of resource inside a pack, mapping to a directory under
@@ -70,6 +95,7 @@ declare class FolderResourceManager implements ResourceManager {
70
95
  getAllResources(kind: ResourceKindName, locator: ResourceLocator): Promise<Buffer[]>;
71
96
  listResources(kind: ResourceKindName, namespace: string): Promise<ResourceLocator[]>;
72
97
  listNamespaces(): Promise<string[]>;
98
+ describe(): ResourceDescriptor;
73
99
  }
74
100
  /**
75
101
  * Layers several managers; earlier managers win, matching resource-pack precedence.
@@ -83,6 +109,7 @@ declare class LayeredResourceManager implements ResourceManager {
83
109
  getAllResources(kind: ResourceKindName, locator: ResourceLocator): Promise<Buffer[]>;
84
110
  listResources(kind: ResourceKindName, namespace: string): Promise<ResourceLocator[]>;
85
111
  listNamespaces(): Promise<string[]>;
112
+ describe(): ResourceDescriptor | null;
86
113
  }
87
114
  //#endregion
88
- export { ResourceManager as a, ResourceKindName as i, LayeredResourceManager as n, ResourceKind as r, FolderResourceManager as t };
115
+ export { ResourceManager as a, describeResources as c, ResourceKindName as i, restoreResources as l, LayeredResourceManager as n, DescribableResourceManager as o, ResourceKind as r, ResourceDescriptor as s, FolderResourceManager as t };
@@ -1,2 +1,2 @@
1
- import { a as resolveTexture, i as flattenLoaderModel, n as ModelResolutionError, o as salvageJson, r as ResolvedModel, t as ModelLoader } from "../loader-C-6QN3xv.js";
1
+ import { a as resolveTexture, i as flattenLoaderModel, n as ModelResolutionError, o as salvageJson, r as ResolvedModel, t as ModelLoader } from "../loader-D22zZME7.js";
2
2
  export { ModelLoader, ModelResolutionError, ResolvedModel, flattenLoaderModel, resolveTexture, salvageJson };
@@ -1,2 +1,2 @@
1
- import { a as salvageJson, i as resolveTexture, n as ModelResolutionError, r as flattenLoaderModel, t as ModelLoader } from "../loader-A-BZa8J4.js";
1
+ import { a as salvageJson, i as resolveTexture, n as ModelResolutionError, r as flattenLoaderModel, t as ModelLoader } from "../loader-B8NJO7pR.js";
2
2
  export { ModelLoader, ModelResolutionError, flattenLoaderModel, resolveTexture, salvageJson };
@@ -1,2 +1,2 @@
1
- import { i as prepareModResources, n as ModPreparation, r as PrepareModsOptions, t as LOADER_NAMESPACES } from "../prepare-gfR1aIjt.js";
1
+ import { i as prepareModResources, n as ModPreparation, r as PrepareModsOptions, t as LOADER_NAMESPACES } from "../prepare-CPxO0kKz.js";
2
2
  export { LOADER_NAMESPACES, ModPreparation, PrepareModsOptions, prepareModResources };
@@ -1,2 +1,2 @@
1
- import { n as prepareModResources, t as LOADER_NAMESPACES } from "../prepare-BeUpXwaP.js";
1
+ import { n as prepareModResources, t as LOADER_NAMESPACES } from "../prepare-BESRrh6K.js";
2
2
  export { LOADER_NAMESPACES, prepareModResources };
@@ -1,5 +1,5 @@
1
- import { a as ResourceManager } from "../manager-CoZaeQTu.js";
2
- import { n as MapResourceManager } from "../synthetic-CDsj--li.js";
1
+ import { a as ResourceManager } from "../manager-Cv1NeFyF.js";
2
+ import { n as MapResourceManager } from "../synthetic-Qk-BSUXO.js";
3
3
  //#region src/mods/synthesize.d.ts
4
4
  interface SynthesisResult {
5
5
  models: MapResourceManager;
@@ -1,2 +1,2 @@
1
- import { t as synthesizeItemModels } from "../synthesize-CRgSEmEp.js";
1
+ import { t as synthesizeItemModels } from "../synthesize-3Q0aaOnK.js";
2
2
  export { synthesizeItemModels };
@@ -1,5 +1,5 @@
1
- import { a as ResourceManager } from "../manager-CoZaeQTu.js";
2
- import { n as MapResourceManager } from "../synthetic-CDsj--li.js";
1
+ import { a as ResourceManager } from "../manager-Cv1NeFyF.js";
2
+ import { n as MapResourceManager } from "../synthetic-Qk-BSUXO.js";
3
3
  //#region src/mods/tints.d.ts
4
4
  interface HarvestTintsOptions {
5
5
  /** Assets from 1.21.4+ releases of the same mods, read only for their tints. */
@@ -1,2 +1,2 @@
1
- import { n as harvestTintOverrides, t as curatedTintOverrides } from "../tints-CuG6GwQJ.js";
1
+ import { n as harvestTintOverrides, t as curatedTintOverrides } from "../tints-B8UJmZMu.js";
2
2
  export { curatedTintOverrides, harvestTintOverrides };
@@ -1,2 +1,2 @@
1
- import { a as RasterAssetFormat, c as encodeRasterAsset, i as EncodedIcon, n as EncodeOptions, o as encodeAnimatedIcon, r as EncodedAnimatedIcon, s as encodeIcon, t as AnimatedEncodeOptions } from "../encode-C5kdAm45.js";
1
+ import { a as RasterAssetFormat, c as encodeRasterAsset, i as EncodedIcon, n as EncodeOptions, o as encodeAnimatedIcon, r as EncodedAnimatedIcon, s as encodeIcon, t as AnimatedEncodeOptions } from "../encode-DaNQF28M.js";
2
2
  export { AnimatedEncodeOptions, EncodeOptions, EncodedAnimatedIcon, EncodedIcon, RasterAssetFormat, encodeAnimatedIcon, encodeIcon, encodeRasterAsset };
@@ -1,2 +1,2 @@
1
- import { n as encodeIcon, r as encodeRasterAsset, t as encodeAnimatedIcon } from "../encode-3u49i-eD.js";
1
+ import { n as encodeIcon, r as encodeRasterAsset, t as encodeAnimatedIcon } from "../encode-D6dQu2dJ.js";
2
2
  export { encodeAnimatedIcon, encodeIcon, encodeRasterAsset };
@@ -1,2 +1,2 @@
1
- import { t as classifyItemStyle } from "../item-styles-DJ3LWZS2.js";
1
+ import { t as classifyItemStyle } from "../item-styles-upgEO1yP.js";
2
2
  export { classifyItemStyle };
@@ -0,0 +1,221 @@
1
+ import { a as defaultProperties } from "./definition-3MBm8ar_.js";
2
+ import { n as ResourceLocator } from "./locator-ycZzh_6z.js";
3
+ import { n as LayeredResourceManager, t as FolderResourceManager } from "./manager-CkletR5K.js";
4
+ import { r as resolveItem } from "./discovery-0SM0cTLw.js";
5
+ import { s as toFloatTexture, t as blendPixel } from "./blend-CHP2-j9U.js";
6
+ import { t as encodeAnimatedIcon } from "./encode-D6dQu2dJ.js";
7
+ import { a as builtinDynamicResources } from "./generators-BlG4KmtP.js";
8
+ import { t as ModelLoader } from "./loader-B8NJO7pR.js";
9
+ import { a as renderModelFrames, i as renderModel, n as boxDownscale, r as pointResize } from "./renderer-CjT19tHd.js";
10
+ import { n as renderEntityFallback, r as spawnEggTints, t as renderDyedVariantFallback } from "./entity-fallback-BRCeGKBT.js";
11
+ import { i as renderGeo, t as findGeoForItem } from "./geo-Diky41Tw.js";
12
+ import { t as legacyTintsForChain } from "./legacy-tints-B09J0Rxh.js";
13
+ import { a as resolveTints } from "./tints-BtbHegpI.js";
14
+ import { t as loadAtlasResolver } from "./registry-B9TcjVbs.js";
15
+ import { n as TextureLoader } from "./loader-CfXMxcEV.js";
16
+ import path from "node:path";
17
+ import { mkdir, writeFile } from "node:fs/promises";
18
+ //#region src/render/pipeline.ts
19
+ /**
20
+ * The per-item pipeline: asset layering, model/texture loading, the render
21
+ * fallback chain, encoding, and file output. Extracted from run() so a worker
22
+ * thread renders items exactly the way the main thread does — a second
23
+ * implementation would drift, and the failure taxonomy depends on the fallback
24
+ * order being identical everywhere.
25
+ */
26
+ var ItemPipeline = class ItemPipeline {
27
+ static async create(base, settings) {
28
+ const dynamic = settings.builtin ? builtinDynamicResources() : null;
29
+ const resources = settings.builtin && dynamic ? new LayeredResourceManager([
30
+ new FolderResourceManager(settings.builtin),
31
+ dynamic.layer,
32
+ base
33
+ ]) : base;
34
+ const pipeline = new ItemPipeline(resources, dynamic?.items.map((item) => item.id) ?? null, settings);
35
+ pipeline.textures.setAtlasResolver(await loadAtlasResolver(resources, (locator) => pipeline.textures.load(locator)));
36
+ return pipeline;
37
+ }
38
+ settings;
39
+ models;
40
+ textures;
41
+ createdDirectories = /* @__PURE__ */ new Set();
42
+ /** The layered tree actually rendered (builtin + dynamic above the input). */
43
+ resources;
44
+ /** Dynamic vanilla items (trims, pots, crossbows), or null without a builtin pack. */
45
+ dynamicItems;
46
+ constructor(resources, dynamicItems, settings) {
47
+ this.resources = resources;
48
+ this.dynamicItems = dynamicItems;
49
+ this.settings = settings;
50
+ this.models = new ModelLoader(resources);
51
+ this.textures = new TextureLoader(resources);
52
+ }
53
+ /**
54
+ * Code-rendered models often still ship a flat item sprite (the old
55
+ * pipeline's black-icon audit checked exactly this). A real sprite beats
56
+ * no icon; the fallback is recorded so it is never a silent substitution.
57
+ */
58
+ async spriteFallback(id) {
59
+ const { size, quality } = this.settings;
60
+ const locator = ResourceLocator.parse(id);
61
+ for (const directory of ["item", "items"]) {
62
+ const texture = await this.textures.load(new ResourceLocator(locator.namespace, `${directory}/${locator.path}`));
63
+ if (texture) {
64
+ const upscaled = pointResize(toFloatTexture(texture), size * quality, size * quality);
65
+ return quality === 1 ? upscaled : boxDownscale(upscaled, quality);
66
+ }
67
+ }
68
+ return null;
69
+ }
70
+ /** Render an item's frames from its own model, without any fallback. */
71
+ async renderFrames(id) {
72
+ const { size, quality, lightingProfile, animation } = this.settings;
73
+ const { resources, models, textures } = this;
74
+ const instructions = await resolveItem(resources, id, defaultProperties());
75
+ let frames;
76
+ let delaysMs;
77
+ if (instructions.length === 1) {
78
+ const model = await models.load(instructions[0].model);
79
+ let tints = instructions[0].tints.length > 0 ? await resolveTints(instructions[0].tints, { textures }) : await legacyTintsForChain(model.chain, textures);
80
+ if (!tints && model.chain.some((entry) => entry.endsWith("item/template_spawn_egg"))) tints = await spawnEggTints(id, resources, textures).catch(() => null);
81
+ tints ??= [];
82
+ const result = await renderModelFrames(model, textures, {
83
+ size,
84
+ quality,
85
+ lightingProfile,
86
+ itemTransform: instructions[0].transform,
87
+ tints,
88
+ resources,
89
+ animation
90
+ });
91
+ frames = result.frames;
92
+ delaysMs = result.delaysMs;
93
+ } else {
94
+ let combined = null;
95
+ for (const instruction of instructions) {
96
+ const model = await models.load(instruction.model);
97
+ const tints = instruction.tints.length > 0 ? await resolveTints(instruction.tints, { textures }) : await legacyTintsForChain(model.chain, textures) ?? [];
98
+ const renderedModel = await renderModel(model, textures, {
99
+ size,
100
+ quality,
101
+ lightingProfile,
102
+ itemTransform: instruction.transform,
103
+ tints,
104
+ resources
105
+ });
106
+ combined = combined === null ? renderedModel : blendOver(combined, renderedModel);
107
+ }
108
+ frames = [combined ?? blankFrame(size)];
109
+ delaysMs = [50];
110
+ }
111
+ if (frames.length === 0) {
112
+ frames = [blankFrame(size)];
113
+ delaysMs = [50];
114
+ }
115
+ return {
116
+ frames,
117
+ delaysMs
118
+ };
119
+ }
120
+ /**
121
+ * Frames for an item, falling back through the same-name block model,
122
+ * GeckoLib geometry, builtin entity geometry, dyed variants, and finally the
123
+ * flat sprite. Rethrows the item's own error when nothing draws it.
124
+ */
125
+ async renderFramesWithFallback(id) {
126
+ try {
127
+ return {
128
+ ...await this.renderFrames(id),
129
+ usedFallback: false
130
+ };
131
+ } catch (err) {
132
+ const { size, quality, lightingProfile, builtin } = this.settings;
133
+ const { resources, models, textures } = this;
134
+ const blockLocator = ResourceLocator.parse(id);
135
+ const blockRender = await models.load(new ResourceLocator(blockLocator.namespace, `block/${blockLocator.path}`)).then((model) => renderModel(model, textures, {
136
+ size,
137
+ quality,
138
+ lightingProfile,
139
+ resources
140
+ })).catch(() => null);
141
+ const geo = blockRender ? null : await findGeoForItem(resources, id).catch(() => null);
142
+ const geoRender = geo ? await renderGeo(geo.geo, geo.texture, textures, {
143
+ size,
144
+ quality,
145
+ lightingProfile
146
+ }).catch(() => null) : null;
147
+ let fallbackRender = blockRender ?? (geoRender && quality !== 1 ? boxDownscale(geoRender, quality) : geoRender);
148
+ fallbackRender ??= builtin ? await renderEntityFallback(id, models, textures, resources, {
149
+ size,
150
+ quality,
151
+ lightingProfile,
152
+ resources
153
+ }).catch(() => null) : null;
154
+ fallbackRender ??= await renderDyedVariantFallback(id, models, textures, {
155
+ size,
156
+ quality,
157
+ lightingProfile,
158
+ resources
159
+ }).catch(() => null);
160
+ if (fallbackRender) return {
161
+ frames: [fallbackRender],
162
+ delaysMs: [50],
163
+ usedFallback: false
164
+ };
165
+ const sprite = await this.spriteFallback(id).catch(() => null);
166
+ if (!sprite) throw err;
167
+ return {
168
+ frames: [sprite],
169
+ delaysMs: [50],
170
+ usedFallback: true
171
+ };
172
+ }
173
+ }
174
+ /** Render, encode and write one item. Throws when the item cannot be drawn. */
175
+ async renderItem(id) {
176
+ const { frames, delaysMs, usedFallback } = await this.renderFramesWithFallback(id);
177
+ const encoded = await encodeAnimatedIcon(frames, delaysMs, {
178
+ webp: true,
179
+ gif: this.settings.gif,
180
+ avif: this.settings.avif || this.settings.format === "avif"
181
+ });
182
+ const [namespace, itemPath] = id.split(":", 2);
183
+ const imageBase = path.join(this.settings.output, "items", namespace, itemPath);
184
+ const directory = path.dirname(imageBase);
185
+ if (!this.createdDirectories.has(directory)) {
186
+ await mkdir(directory, { recursive: true });
187
+ this.createdDirectories.add(directory);
188
+ }
189
+ await writeFile(`${imageBase}.png`, encoded.png);
190
+ let written = 1;
191
+ for (const [extension, buffer] of [
192
+ ["webp", encoded.webp],
193
+ ["gif", encoded.gif],
194
+ ["avif", encoded.avif]
195
+ ]) {
196
+ if (!buffer) continue;
197
+ await writeFile(`${imageBase}.${extension}`, buffer);
198
+ written++;
199
+ }
200
+ return {
201
+ written,
202
+ usedFallback
203
+ };
204
+ }
205
+ };
206
+ function blankFrame(size) {
207
+ return {
208
+ width: size,
209
+ height: size,
210
+ data: new Float64Array(size * size * 4)
211
+ };
212
+ }
213
+ function blendOver(base, layer) {
214
+ for (let offset = 0; offset < base.data.length; offset += 4) {
215
+ const alpha = layer.data[offset + 3];
216
+ if (alpha > 0) blendPixel(base.data, offset, layer.data[offset], layer.data[offset + 1], layer.data[offset + 2], alpha);
217
+ }
218
+ return base;
219
+ }
220
+ //#endregion
221
+ export { ItemPipeline as t };
@@ -0,0 +1,58 @@
1
+ import { a as ResourceManager } from "./manager-Cv1NeFyF.js";
2
+ import { t as FloatTexture } from "./blend-CyDIxCne.js";
3
+ import { a as LightingProfileName } from "./lighting-3FGRC3Af.js";
4
+ import { n as AnimationLimits } from "./renderer-DVsZHAvf.js";
5
+ //#region src/render/pipeline.d.ts
6
+ interface PipelineSettings {
7
+ builtin?: string;
8
+ output: string;
9
+ size: number;
10
+ quality: number;
11
+ format: 'webp' | 'avif';
12
+ gif?: boolean;
13
+ avif?: boolean;
14
+ lightingProfile: LightingProfileName;
15
+ animation?: AnimationLimits;
16
+ }
17
+ interface ItemRenderOutcome {
18
+ /** Image files written for the item. */
19
+ written: number;
20
+ /** Whether the item fell back to its flat sprite instead of its model. */
21
+ usedFallback: boolean;
22
+ }
23
+ interface RenderedFrames {
24
+ frames: FloatTexture[];
25
+ delaysMs: number[];
26
+ }
27
+ declare class ItemPipeline {
28
+ static create(base: ResourceManager, settings: PipelineSettings): Promise<ItemPipeline>;
29
+ private readonly settings;
30
+ private readonly models;
31
+ private readonly textures;
32
+ private readonly createdDirectories;
33
+ /** The layered tree actually rendered (builtin + dynamic above the input). */
34
+ readonly resources: ResourceManager;
35
+ /** Dynamic vanilla items (trims, pots, crossbows), or null without a builtin pack. */
36
+ readonly dynamicItems: string[] | null;
37
+ private constructor();
38
+ /**
39
+ * Code-rendered models often still ship a flat item sprite (the old
40
+ * pipeline's black-icon audit checked exactly this). A real sprite beats
41
+ * no icon; the fallback is recorded so it is never a silent substitution.
42
+ */
43
+ private spriteFallback;
44
+ /** Render an item's frames from its own model, without any fallback. */
45
+ renderFrames(id: string): Promise<RenderedFrames>;
46
+ /**
47
+ * Frames for an item, falling back through the same-name block model,
48
+ * GeckoLib geometry, builtin entity geometry, dyed variants, and finally the
49
+ * flat sprite. Rethrows the item's own error when nothing draws it.
50
+ */
51
+ renderFramesWithFallback(id: string): Promise<RenderedFrames & {
52
+ usedFallback: boolean;
53
+ }>;
54
+ /** Render, encode and write one item. Throws when the item cannot be drawn. */
55
+ renderItem(id: string): Promise<ItemRenderOutcome>;
56
+ }
57
+ //#endregion
58
+ export { RenderedFrames as i, ItemRenderOutcome as n, PipelineSettings as r, ItemPipeline as t };