@nodecraft/rendermite 1.6.0 → 1.6.1

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 (37) hide show
  1. package/dist/blocks/cli.js +1 -1
  2. package/dist/blocks/entity-models.d.ts +45 -2
  3. package/dist/blocks/entity-models.js +1 -1
  4. package/dist/blocks/export.d.ts +1 -1
  5. package/dist/blocks/export.js +1 -1
  6. package/dist/{classfile-BwaQjnUM.d.ts → classfile-BdLIk4Pe.d.ts} +16 -0
  7. package/dist/{classfile-CAhS5qNf.js → classfile-Bo7FUrrD.js} +42 -10
  8. package/dist/{cli-BSKnXBPr.js → cli-D2KJc_yl.js} +6 -2
  9. package/dist/cli.js +1 -1
  10. package/dist/entities/classfile.d.ts +1 -1
  11. package/dist/entities/classfile.js +1 -1
  12. package/dist/entities/inherit.d.ts +2 -2
  13. package/dist/entities/inherit.js +1 -1
  14. package/dist/entities/jar-classes.d.ts +2 -26
  15. package/dist/entities/jar-classes.js +2 -2
  16. package/dist/entities/link.d.ts +2 -2
  17. package/dist/entities/link.js +1 -1
  18. package/dist/entities/merge.js +1 -1
  19. package/dist/entities/model-bytecode.d.ts +1 -1
  20. package/dist/entities/model-bytecode.js +1 -1
  21. package/dist/entities/model-code.d.ts +1 -1
  22. package/dist/entities/model-code.js +1 -1
  23. package/dist/{entity-models-B6-0r2gR.js → entity-models-_EZ3PVtN.js} +9 -5
  24. package/dist/{export-D8fLC1wS.d.ts → export-B8tPsf4K.d.ts} +1 -1
  25. package/dist/{export-DT_drDoI.js → export-BfEIwSxY.js} +1 -1
  26. package/dist/index.d.ts +1 -1
  27. package/dist/index.js +1 -1
  28. package/dist/{inherit-KkDsM2N_.js → inherit-ByHjOJX3.js} +3 -3
  29. package/dist/jar-classes-CSRrPAUy.d.ts +41 -0
  30. package/dist/{jar-classes-Bj15hjdr.js → jar-classes-DCtELr1i.js} +28 -1
  31. package/dist/{link-Bm5oQYh6.js → link-5GmBLTzk.js} +25 -1
  32. package/dist/{merge-3HkeQ_6A.js → merge-NDYxpmL8.js} +7 -5
  33. package/dist/{model-bytecode-C1nw2G8O.js → model-bytecode-gWy5_uCj.js} +13 -3
  34. package/dist/{model-code-BKMEMXxF.js → model-code-1Vuk-zj_.js} +1 -1
  35. package/dist/{model-code-B7jSFQqd.d.ts → model-code-BY44ao27.d.ts} +1 -1
  36. package/package.json +1 -1
  37. package/dist/entity-models-c2HpfdWV.d.ts +0 -49
@@ -1,2 +1,2 @@
1
- import { t as runBlocksCli } from "../cli-BSKnXBPr.js";
1
+ import { t as runBlocksCli } from "../cli-D2KJc_yl.js";
2
2
  export { runBlocksCli };
@@ -1,2 +1,45 @@
1
- import { i as collectEntityGeometry, n as CollectEntityGeometryOptions, r as EntityGeometryResult, t as ClassSource } from "../entity-models-c2HpfdWV.js";
2
- export { ClassSource, CollectEntityGeometryOptions, EntityGeometryResult, collectEntityGeometry };
1
+ import { a as ResourceManager } from "../manager-exOIcdyx.js";
2
+ import { S as EntityPackModel } from "../pack-format-QcVFxG_b.js";
3
+ import { t as ClassSource } from "../jar-classes-CSRrPAUy.js";
4
+ //#region src/blocks/entity-models.d.ts
5
+ interface EntityGeometryResult {
6
+ /** Model id (the class it came from) → geometry. */
7
+ models: Record<string, EntityPackModel>;
8
+ /** Entity id → model id, for the entity table to point with. */
9
+ modelOf: Map<string, string>;
10
+ /** Entity sheets the models address, to be stitched into the pack's own atlas. */
11
+ spriteIds: Set<string>;
12
+ failures: Array<{
13
+ id: string;
14
+ reason: string;
15
+ }>;
16
+ }
17
+ interface CollectEntityGeometryOptions {
18
+ version: string;
19
+ /** Where mappings cache; the same directory the jars do. */
20
+ cacheDir: string;
21
+ classes: ClassSource;
22
+ /** Entity ids to look for, as the registry named them. */
23
+ entityIds: readonly string[];
24
+ /** The sheet each entity resolved to, from the entity registry, keyed by entity id. */
25
+ textureOf: ReadonlyMap<string, string>;
26
+ /**
27
+ * The assets, for the mods whose geometry is not in code at all.
28
+ *
29
+ * A GeckoLib mob ships Blockbench's bedrock format and registers it by resource location, so there
30
+ * is nothing for the interpreter to read; `entity-geo.ts` finds and converts it instead.
31
+ */
32
+ resources?: ResourceManager;
33
+ onProgress?: (done: number, total: number) => void;
34
+ }
35
+ /**
36
+ * Recovers geometry for as many of `entityIds` as the code describes.
37
+ *
38
+ * Mappings are resolved once: downloaded for an obfuscated jar, and the identity for one that is not
39
+ * (from the 26 line the client ships in the clear, and a mod jar never was obfuscated). A version that
40
+ * is obfuscated *and* unmapped — 1.13.x — yields nothing, with the reason recorded once rather than
41
+ * per entity.
42
+ */
43
+ declare function collectEntityGeometry(options: CollectEntityGeometryOptions): Promise<EntityGeometryResult>;
44
+ //#endregion
45
+ export { CollectEntityGeometryOptions, EntityGeometryResult, collectEntityGeometry };
@@ -1,2 +1,2 @@
1
- import { t as collectEntityGeometry } from "../entity-models-B6-0r2gR.js";
1
+ import { t as collectEntityGeometry } from "../entity-models-_EZ3PVtN.js";
2
2
  export { collectEntityGeometry };
@@ -1,2 +1,2 @@
1
- import { i as exportBlockPack, n as BlockPackResult, r as ExportBlockPackOptions, t as BlockPackFailure } from "../export-D8fLC1wS.js";
1
+ import { i as exportBlockPack, n as BlockPackResult, r as ExportBlockPackOptions, t as BlockPackFailure } from "../export-B8tPsf4K.js";
2
2
  export { BlockPackFailure, BlockPackResult, ExportBlockPackOptions, exportBlockPack };
@@ -1,2 +1,2 @@
1
- import { t as exportBlockPack } from "../export-DT_drDoI.js";
1
+ import { t as exportBlockPack } from "../export-BfEIwSxY.js";
2
2
  export { exportBlockPack };
@@ -22,6 +22,10 @@ interface Constant {
22
22
  nameAndTypeIndex?: number;
23
23
  descriptorIndex?: number;
24
24
  stringIndex?: number;
25
+ /** A `methodHandle`'s target: an index of a `methodref`, not of a `nameAndType`. */
26
+ referenceIndex?: number;
27
+ /** An `invokeDynamic`'s row in the `BootstrapMethods` attribute. */
28
+ bootstrapIndex?: number;
25
29
  }
26
30
  interface MethodInfo {
27
31
  name: string;
@@ -45,6 +49,18 @@ interface ClassFile {
45
49
  } | null;
46
50
  /** The value an `ldc` of this index pushes: a number for numeric constants, a string for `string`. */
47
51
  literal: (index: number) => string | number | bigint | null;
52
+ /**
53
+ * The method a lambda actually runs, for an `invokedynamic`'s pool index.
54
+ *
55
+ * A lambda compiles to a call through `LambdaMetafactory` with the real body in a synthetic method,
56
+ * so this is two hops: the pool entry names a row of the `BootstrapMethods` attribute, and that
57
+ * row's second argument is a method handle pointing at the body.
58
+ */
59
+ lambdaTarget: (index: number) => {
60
+ owner: string;
61
+ name: string;
62
+ descriptor: string;
63
+ } | null;
48
64
  }
49
65
  declare function parseClassFile(bytes: Uint8Array): ClassFile;
50
66
  //#endregion
@@ -150,7 +150,7 @@ function readConstantPool(reader) {
150
150
  reader.skip(1);
151
151
  constants.push({
152
152
  tag,
153
- nameAndTypeIndex: reader.u2()
153
+ referenceIndex: reader.u2()
154
154
  });
155
155
  break;
156
156
  case "methodType":
@@ -160,23 +160,39 @@ function readConstantPool(reader) {
160
160
  });
161
161
  break;
162
162
  case "dynamic":
163
- case "invokeDynamic":
164
- reader.skip(2);
165
- constants.push({
166
- tag,
167
- nameAndTypeIndex: reader.u2()
168
- });
163
+ case "invokeDynamic": constants.push({
164
+ tag,
165
+ bootstrapIndex: reader.u2(),
166
+ nameAndTypeIndex: reader.u2()
167
+ });
169
168
  }
170
169
  }
171
170
  return constants;
172
171
  }
173
- /** Skips an attribute table, returning the `Code` bytes if one of them is a Code attribute. */
174
- function readAttributes(reader, utf8) {
172
+ /**
173
+ * Skips an attribute table, keeping the two that say what a method does: `Code`, and the class-level
174
+ * `BootstrapMethods` that a lambda's real body is reachable through.
175
+ */
176
+ function readAttributes(reader, utf8, bootstraps) {
175
177
  let code;
176
178
  const count = reader.u2();
177
179
  for (let index = 0; index < count; index++) {
178
180
  const name = utf8(reader.u2());
179
181
  const length = reader.u4();
182
+ if (name === "BootstrapMethods" && bootstraps) {
183
+ const rows = reader.u2();
184
+ for (let row = 0; row < rows; row++) {
185
+ const handleIndex = reader.u2();
186
+ const argumentCount = reader.u2();
187
+ const argumentIndexes = [];
188
+ for (let argument = 0; argument < argumentCount; argument++) argumentIndexes.push(reader.u2());
189
+ bootstraps.push({
190
+ handleIndex,
191
+ argumentIndexes
192
+ });
193
+ }
194
+ continue;
195
+ }
180
196
  if (name !== "Code") {
181
197
  reader.skip(length);
182
198
  continue;
@@ -224,6 +240,8 @@ function parseClassFile(bytes) {
224
240
  code
225
241
  });
226
242
  }
243
+ const bootstraps = [];
244
+ readAttributes(reader, utf8, bootstraps);
227
245
  const reference = (index) => {
228
246
  const entry = constants[index];
229
247
  if (!entry || entry.classIndex === void 0 || entry.nameAndTypeIndex === void 0) return null;
@@ -241,6 +259,19 @@ function parseClassFile(bytes) {
241
259
  if (entry.tag === "string") return utf8(index);
242
260
  return entry.value ?? null;
243
261
  };
262
+ const lambdaTarget = (index) => {
263
+ const entry = constants[index];
264
+ const row = entry?.bootstrapIndex === void 0 ? void 0 : bootstraps[entry.bootstrapIndex];
265
+ if (!row) return null;
266
+ for (const argument of row.argumentIndexes) {
267
+ const handle = constants[argument];
268
+ if (handle?.tag === "methodHandle" && handle.referenceIndex !== void 0) {
269
+ const target = reference(handle.referenceIndex);
270
+ if (target) return target;
271
+ }
272
+ }
273
+ return null;
274
+ };
244
275
  return {
245
276
  thisClass,
246
277
  superClass,
@@ -248,7 +279,8 @@ function parseClassFile(bytes) {
248
279
  methods,
249
280
  utf8,
250
281
  reference,
251
- literal
282
+ literal,
283
+ lambdaTarget
252
284
  };
253
285
  }
254
286
  //#endregion
@@ -1,7 +1,7 @@
1
1
  import { n as builtinPackPath } from "./builtin-WkWjATeh.js";
2
2
  import { n as LayeredResourceManager, t as FolderResourceManager } from "./manager-BNibYkmI.js";
3
- import { t as exportBlockPack } from "./export-DT_drDoI.js";
4
- import { t as JarClassReader } from "./jar-classes-Bj15hjdr.js";
3
+ import { t as exportBlockPack } from "./export-BfEIwSxY.js";
4
+ import { n as layeredClasses, t as JarClassReader } from "./jar-classes-DCtELr1i.js";
5
5
  import { n as prepareModResources } from "./prepare-Myd_ec4v.js";
6
6
  import { t as downloadClientJar } from "./download-1wAfrGKx.js";
7
7
  import { a as prepareVersionResources, r as compareVersions } from "./prepare-D49Gu4Lv.js";
@@ -155,6 +155,10 @@ async function runBlocksCli(argv) {
155
155
  closeMods = () => prepared.close();
156
156
  for (const { jar, reason } of prepared.rejected) console.error(`Rejected mod jar ${jar}: ${reason}`);
157
157
  namespaces = values.namespace?.length ? values.namespace : prepared.namespaces;
158
+ if (!values["no-entity-geometry"]) {
159
+ const modClasses = values.mod.map((jar) => new JarClassReader(jar));
160
+ classes = layeredClasses(classes ? [classes, ...modClasses] : modClasses);
161
+ }
158
162
  }
159
163
  try {
160
164
  const result = await exportBlockPack({
package/dist/cli.js CHANGED
@@ -6,7 +6,7 @@ import { t as curatedModelOverrides } from "./models-CZjCOjs4.js";
6
6
  import { n as harvestTintOverrides, t as curatedTintOverrides } from "./tints-BspVCz2G.js";
7
7
  import { t as downloadClientJar } from "./download-1wAfrGKx.js";
8
8
  import { a as prepareVersionResources, i as eraForVersion, n as GEOMETRY_DONOR_VERSIONS } from "./prepare-D49Gu4Lv.js";
9
- import { t as runBlocksCli } from "./cli-BSKnXBPr.js";
9
+ import { t as runBlocksCli } from "./cli-D2KJc_yl.js";
10
10
  import { t as run } from "./run-BQJkqc5f.js";
11
11
  import path from "node:path";
12
12
  import os from "node:os";
@@ -1,2 +1,2 @@
1
- import { a as parseClassFile, i as MethodInfo, n as Constant, r as ConstantTag, t as ClassFile } from "../classfile-BwaQjnUM.js";
1
+ import { a as parseClassFile, i as MethodInfo, n as Constant, r as ConstantTag, t as ClassFile } from "../classfile-BdLIk4Pe.js";
2
2
  export { ClassFile, Constant, ConstantTag, MethodInfo, parseClassFile };
@@ -1,2 +1,2 @@
1
- import { t as parseClassFile } from "../classfile-CAhS5qNf.js";
1
+ import { t as parseClassFile } from "../classfile-Bo7FUrrD.js";
2
2
  export { parseClassFile };
@@ -1,6 +1,6 @@
1
1
  import { r as ExtractedModel } from "../model-PnQ4gV0-.js";
2
- import { t as ClassFile } from "../classfile-BwaQjnUM.js";
3
- import { t as ModelCode } from "../model-code-B7jSFQqd.js";
2
+ import { t as ClassFile } from "../classfile-BdLIk4Pe.js";
3
+ import { t as ModelCode } from "../model-code-BY44ao27.js";
4
4
  //#region src/entities/inherit.d.ts
5
5
  interface Ancestry {
6
6
  /** The class and its ancestors by internal name, parsed. */
@@ -1,2 +1,2 @@
1
- import { n as extractInheritedModel, t as ancestryOf } from "../inherit-KkDsM2N_.js";
1
+ import { n as extractInheritedModel, t as ancestryOf } from "../inherit-ByHjOJX3.js";
2
2
  export { ancestryOf, extractInheritedModel };
@@ -1,26 +1,2 @@
1
- //#region src/entities/jar-classes.d.ts
2
- /**
3
- * Reading `.class` entries out of a jar.
4
- *
5
- * `JarResourceManager` deliberately indexes only `assets/` and `data/` — it is a *resource* manager,
6
- * and a class file is not a resource. But entity geometry lives in the code (see
7
- * `docs/entity-geometry.md`), so the extractor needs the other half of the archive, and it needs it
8
- * by internal class name rather than by resource locator.
9
- *
10
- * Same shape as the resource manager for the same reason: index the central directory once, then read
11
- * entries on demand. A client jar holds around eight thousand classes and the extractor touches a
12
- * hundred of them.
13
- */
14
- /** Reads class files out of one jar, by internal name. */
15
- declare class JarClassReader {
16
- private readonly jarPath;
17
- private index;
18
- constructor(jarPath: string);
19
- private getIndex;
20
- /** Every class in the jar, for a sweep that does not know what it is looking for. */
21
- list(): Promise<string[]>;
22
- read(internalName: string): Promise<Uint8Array | null>;
23
- close(): Promise<void>;
24
- }
25
- //#endregion
26
- export { JarClassReader };
1
+ import { n as JarClassReader, r as layeredClasses, t as ClassSource } from "../jar-classes-CSRrPAUy.js";
2
+ export { ClassSource, JarClassReader, layeredClasses };
@@ -1,2 +1,2 @@
1
- import { t as JarClassReader } from "../jar-classes-Bj15hjdr.js";
2
- export { JarClassReader };
1
+ import { n as layeredClasses, t as JarClassReader } from "../jar-classes-DCtELr1i.js";
2
+ export { JarClassReader, layeredClasses };
@@ -1,4 +1,4 @@
1
- import { t as ClassFile } from "../classfile-BwaQjnUM.js";
1
+ import { t as ClassFile } from "../classfile-BdLIk4Pe.js";
2
2
  import { t as Mappings } from "../mappings-DxX4KoZl.js";
3
3
  //#region src/entities/link.d.ts
4
4
  /**
@@ -38,7 +38,7 @@ interface EntityModelLink {
38
38
  /** The class to actually read the bytecode of. */
39
39
  obfuscated: string;
40
40
  /** How it was found, so a report can say how much rests on the curated table. */
41
- route: 'model-name' | 'renderer' | 'alias' | 'mod-name';
41
+ route: 'model-name' | 'renderer' | 'alias' | 'mod-name' | 'vanilla-name';
42
42
  }
43
43
  /**
44
44
  * A class's simple name reduced to the entity it is about.
@@ -1,2 +1,2 @@
1
- import { a as linkEntityModel, i as classReader, n as RENDERER_ALIASES, o as normaliseModelName, r as buildModelNameIndex, t as NO_MODEL } from "../link-Bm5oQYh6.js";
1
+ import { a as linkEntityModel, i as classReader, n as RENDERER_ALIASES, o as normaliseModelName, r as buildModelNameIndex, t as NO_MODEL } from "../link-5GmBLTzk.js";
2
2
  export { NO_MODEL, RENDERER_ALIASES, buildModelNameIndex, classReader, linkEntityModel, normaliseModelName };
@@ -1,2 +1,2 @@
1
- import { a as slotsOf, i as mergeModels, n as countCubes, r as cubesOf, t as buildsOwnMesh } from "../merge-3HkeQ_6A.js";
1
+ import { a as slotsOf, i as mergeModels, n as countCubes, r as cubesOf, t as buildsOwnMesh } from "../merge-NDYxpmL8.js";
2
2
  export { buildsOwnMesh, countCubes, cubesOf, mergeModels, slotsOf };
@@ -1,5 +1,5 @@
1
1
  import { r as ExtractedModel } from "../model-PnQ4gV0-.js";
2
- import { t as ClassFile } from "../classfile-BwaQjnUM.js";
2
+ import { t as ClassFile } from "../classfile-BdLIk4Pe.js";
3
3
  //#region src/entities/model-bytecode.d.ts
4
4
  /**
5
5
  * Extracts whatever geometry a class's methods build.
@@ -1,2 +1,2 @@
1
- import { t as extractModel } from "../model-bytecode-C1nw2G8O.js";
1
+ import { t as extractModel } from "../model-bytecode-gWy5_uCj.js";
2
2
  export { extractModel };
@@ -1,2 +1,2 @@
1
- import { n as isModelCode, r as loadModelCode, t as ModelCode } from "../model-code-B7jSFQqd.js";
1
+ import { n as isModelCode, r as loadModelCode, t as ModelCode } from "../model-code-BY44ao27.js";
2
2
  export { ModelCode, isModelCode, loadModelCode };
@@ -1,2 +1,2 @@
1
- import { n as loadModelCode, t as isModelCode } from "../model-code-BKMEMXxF.js";
1
+ import { n as loadModelCode, t as isModelCode } from "../model-code-1Vuk-zj_.js";
2
2
  export { isModelCode, loadModelCode };
@@ -1,8 +1,8 @@
1
1
  import { t as findGeoForEntity } from "./entity-geo-B2CkuMWx.js";
2
- import { n as extractInheritedModel } from "./inherit-KkDsM2N_.js";
3
- import { a as linkEntityModel, i as classReader, r as buildModelNameIndex } from "./link-Bm5oQYh6.js";
2
+ import { n as extractInheritedModel } from "./inherit-ByHjOJX3.js";
3
+ import { a as linkEntityModel, i as classReader, r as buildModelNameIndex } from "./link-5GmBLTzk.js";
4
4
  import { s as resolveMappings, t as MappingsUnavailableError } from "./mappings-BEPVaiwE.js";
5
- import { n as loadModelCode } from "./model-code-BKMEMXxF.js";
5
+ import { n as loadModelCode } from "./model-code-1Vuk-zj_.js";
6
6
  //#region src/blocks/entity-models.ts
7
7
  /**
8
8
  * Entity geometry for the pack: link each entity to the class that builds it, read that class's
@@ -93,10 +93,14 @@ async function collectEntityGeometry(options) {
93
93
  for (const entityId of [...entityIds].toSorted((left, right) => left.localeCompare(right))) {
94
94
  options.onProgress?.(++done, entityIds.length);
95
95
  const link = await linkEntityModel(entityId, context);
96
- const found = link ? {
96
+ const guessed = link?.route === "vanilla-name";
97
+ const found = link && !guessed ? {
97
98
  id: link.className,
98
99
  model: await geometryOf(link.obfuscated)
99
- } : await geoFor(entityId);
100
+ } : await geoFor(entityId) ?? (link ? {
101
+ id: link.className,
102
+ model: await geometryOf(link.obfuscated)
103
+ } : null);
100
104
  if (!found?.model) continue;
101
105
  const { id: modelId, model } = found;
102
106
  if (!models[modelId]) models[modelId] = {
@@ -1,5 +1,5 @@
1
1
  import { a as ResourceManager } from "./manager-exOIcdyx.js";
2
- import { t as ClassSource } from "./entity-models-c2HpfdWV.js";
2
+ import { t as ClassSource } from "./jar-classes-CSRrPAUy.js";
3
3
  //#region src/blocks/export.d.ts
4
4
  interface ExportBlockPackOptions {
5
5
  resources: ResourceManager;
@@ -3,7 +3,7 @@ import { n as ResourceLocator } from "./locator-COMEtEn9.js";
3
3
  import { n as blockEntityGeometry, r as synthesizeVariants, t as INVISIBLE_BLOCKS } from "./block-entities-xv3bQpEX.js";
4
4
  import { a as parseBlockState, n as collectModels } from "./blockstate-eval-BRQ3NWY2.js";
5
5
  import { t as collectEntities } from "./entities-DvmA9fEV.js";
6
- import { t as collectEntityGeometry } from "./entity-models-B6-0r2gR.js";
6
+ import { t as collectEntityGeometry } from "./entity-models-_EZ3PVtN.js";
7
7
  import { n as discoverItems } from "./discovery-CD0QqxSF.js";
8
8
  import { a as salvageJson, i as resolveTexture, t as ModelLoader } from "./loader-C-NuJaEi.js";
9
9
  import { t as collectItemSprites } from "./item-sprites-G-yikdfV.js";
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ import { a as resolveTexture, n as ModelResolutionError, o as salvageJson, r as
8
8
  import { a as BlockStateMultipartCase, d as matchesCondition, f as parseBlockState, i as BlockStateError, l as collectModels, n as BlockProperties, o as BlockStateVariantCase, p as weightedVariantIndex, r as BlockStateDefinition, s as MultipartCondition, t as BlockModelVariant, u as evaluateBlockState } from "./blockstate-eval-BzznRcVY.js";
9
9
  import { i as buildObjMesh, n as ObjMesh, r as ObjMeshError, t as MeshGroup } from "./obj-mesh-ydhVfLKs.js";
10
10
  import { a as buildBlockTints, i as UNREGISTERED_TINTS, n as BlockTintPack, t as BlockTint } from "./tints-DoBv5S9v.js";
11
- import { i as exportBlockPack, n as BlockPackResult, r as ExportBlockPackOptions, t as BlockPackFailure } from "./export-D8fLC1wS.js";
11
+ import { i as exportBlockPack, n as BlockPackResult, r as ExportBlockPackOptions, t as BlockPackFailure } from "./export-B8tPsf4K.js";
12
12
  import { s as builtinDynamicResources } from "./generators-BnIzAftW.js";
13
13
  import { d as toFloatTexture, n as FloatTexture, u as toByteTexture } from "./blend-eT64Z6qm.js";
14
14
  import { a as LightingProfileName, i as LightingProfile, r as LightSource, u as lightsForProfile } from "./lighting-3FGRC3Af.js";
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import { n as buildBlockTints, t as UNREGISTERED_TINTS } from "./tints-Cl0r-Ol3.
14
14
  import { o as createAtlasResolver, s as parseAtlasSources, t as AtlasSourceError } from "./sources-BlUriDCs.js";
15
15
  import { n as LayeredResourceManager, r as ResourceKind, t as FolderResourceManager } from "./manager-BNibYkmI.js";
16
16
  import { n as TextureLoader, r as TextureResolutionError, t as AnimatedTexture } from "./loader-C18GpurU.js";
17
- import { t as exportBlockPack } from "./export-DT_drDoI.js";
17
+ import { t as exportBlockPack } from "./export-BfEIwSxY.js";
18
18
  import { n as UnsafeJarError, r as isUnsafeEntryPath, t as JarResourceManager } from "./jar-W2cV2ZVO.js";
19
19
  import { n as prepareModResources } from "./prepare-Myd_ec4v.js";
20
20
  import { a as prepareVersionResources, i as eraForVersion, r as compareVersions } from "./prepare-D49Gu4Lv.js";
@@ -1,6 +1,6 @@
1
- import { t as parseClassFile } from "./classfile-CAhS5qNf.js";
2
- import { i as mergeModels } from "./merge-3HkeQ_6A.js";
3
- import { t as extractModel } from "./model-bytecode-C1nw2G8O.js";
1
+ import { t as parseClassFile } from "./classfile-Bo7FUrrD.js";
2
+ import { i as mergeModels } from "./merge-NDYxpmL8.js";
3
+ import { t as extractModel } from "./model-bytecode-gWy5_uCj.js";
4
4
  //#region src/entities/inherit.ts
5
5
  /**
6
6
  * A model class read together with its ancestors.
@@ -0,0 +1,41 @@
1
+ //#region src/entities/jar-classes.d.ts
2
+ /**
3
+ * Reading `.class` entries out of a jar.
4
+ *
5
+ * `JarResourceManager` deliberately indexes only `assets/` and `data/` — it is a *resource* manager,
6
+ * and a class file is not a resource. But entity geometry lives in the code (see
7
+ * `docs/entity-geometry.md`), so the extractor needs the other half of the archive, and it needs it
8
+ * by internal class name rather than by resource locator.
9
+ *
10
+ * Same shape as the resource manager for the same reason: index the central directory once, then read
11
+ * entries on demand. A client jar holds around eight thousand classes and the extractor touches a
12
+ * hundred of them.
13
+ */
14
+ /** What the extractor reads code out of: one jar, or several layered into one view. */
15
+ interface ClassSource {
16
+ list: () => Promise<string[]>;
17
+ read: (internalName: string) => Promise<Uint8Array | null>;
18
+ close: () => Promise<void>;
19
+ }
20
+ /**
21
+ * Several jars as one class view, first match winning — the same layering the resource managers use.
22
+ *
23
+ * A modded export needs this, and needed it before cross-jar linking did: the class source used to be
24
+ * the client jar alone, so a mod's own model classes were never read and its mobs came out as boxes
25
+ * however good the interpreter was. Layered, one view holds both, which is also what lets a mod entity
26
+ * link to a *vanilla* model — `ars_nouveau:summon_horse` is the game's own horse.
27
+ */
28
+ declare function layeredClasses(sources: readonly ClassSource[]): ClassSource;
29
+ /** Reads class files out of one jar, by internal name. */
30
+ declare class JarClassReader {
31
+ private readonly jarPath;
32
+ private index;
33
+ constructor(jarPath: string);
34
+ private getIndex;
35
+ /** Every class in the jar, for a sweep that does not know what it is looking for. */
36
+ list(): Promise<string[]>;
37
+ read(internalName: string): Promise<Uint8Array | null>;
38
+ close(): Promise<void>;
39
+ }
40
+ //#endregion
41
+ export { JarClassReader as n, layeredClasses as r, ClassSource as t };
@@ -13,6 +13,33 @@ import { n as UnsafeJarError, r as isUnsafeEntryPath } from "./jar-W2cV2ZVO.js";
13
13
  * entries on demand. A client jar holds around eight thousand classes and the extractor touches a
14
14
  * hundred of them.
15
15
  */
16
+ /**
17
+ * Several jars as one class view, first match winning — the same layering the resource managers use.
18
+ *
19
+ * A modded export needs this, and needed it before cross-jar linking did: the class source used to be
20
+ * the client jar alone, so a mod's own model classes were never read and its mobs came out as boxes
21
+ * however good the interpreter was. Layered, one view holds both, which is also what lets a mod entity
22
+ * link to a *vanilla* model — `ars_nouveau:summon_horse` is the game's own horse.
23
+ */
24
+ function layeredClasses(sources) {
25
+ return {
26
+ list: async () => {
27
+ const names = /* @__PURE__ */ new Set();
28
+ for (const source of sources) for (const name of await source.list()) names.add(name);
29
+ return [...names];
30
+ },
31
+ read: async (internalName) => {
32
+ for (const source of sources) {
33
+ const bytes = await source.read(internalName);
34
+ if (bytes) return bytes;
35
+ }
36
+ return null;
37
+ },
38
+ close: async () => {
39
+ for (const source of sources) await source.close();
40
+ }
41
+ };
42
+ }
16
43
  /** Reads class files out of one jar, by internal name. */
17
44
  var JarClassReader = class {
18
45
  jarPath;
@@ -72,4 +99,4 @@ var JarClassReader = class {
72
99
  }
73
100
  };
74
101
  //#endregion
75
- export { JarClassReader as t };
102
+ export { layeredClasses as n, JarClassReader as t };
@@ -1,4 +1,4 @@
1
- import { t as parseClassFile } from "./classfile-CAhS5qNf.js";
1
+ import { t as parseClassFile } from "./classfile-Bo7FUrrD.js";
2
2
  //#region src/entities/link.ts
3
3
  /**
4
4
  * Which class holds a given entity's geometry.
@@ -257,6 +257,7 @@ function buildModelNameIndex(internalNames) {
257
257
  */
258
258
  async function linkEntityModel(entityId, context) {
259
259
  const name = entityId.includes(":") ? entityId.slice(entityId.indexOf(":") + 1) : entityId;
260
+ const modded = entityId.includes(":") && !entityId.startsWith("minecraft:");
260
261
  const { mappings } = context;
261
262
  const accept = async (className, route) => {
262
263
  const obfuscated = mappings.obfuscatedOf.get(className);
@@ -309,8 +310,31 @@ async function linkEntityModel(entityId, context) {
309
310
  route: "mod-name"
310
311
  };
311
312
  }
313
+ if (modded) for (const shorter of withTokensDropped(name)) {
314
+ const found = await linkEntityModel(shorter, context);
315
+ if (found) return {
316
+ ...found,
317
+ route: "vanilla-name"
318
+ };
319
+ }
312
320
  return null;
313
321
  }
322
+ /**
323
+ * The name with some of its tokens dropped, longest first: `summon_horse` gives `summon` and `horse`.
324
+ *
325
+ * Capped at five tokens, because the subsets double with each one and no id is longer than that for a
326
+ * reason this would help with.
327
+ */
328
+ function withTokensDropped(name) {
329
+ const tokens = name.split("_").filter((token) => token.length > 0);
330
+ if (tokens.length < 2 || tokens.length > 5) return [];
331
+ const found = [];
332
+ for (let size = tokens.length - 1; size >= 1; size--) for (let mask = 0; mask < 2 ** tokens.length; mask++) {
333
+ const kept = tokens.filter((token, index) => (mask & 1 << index) !== 0);
334
+ if (kept.length === size) found.push(kept.join("_"));
335
+ }
336
+ return [...new Set(found)];
337
+ }
314
338
  /** Reads and caches classes out of an extracted jar directory or a jar reader. */
315
339
  function classReader(load) {
316
340
  const cache = /* @__PURE__ */ new Map();
@@ -27,13 +27,15 @@ function mergeModels(base, extra) {
27
27
  const named = new Set(target.slots.map((part) => part.name));
28
28
  const missing = source.slots.filter((part) => !named.has(part.name));
29
29
  if (missing.length === 0) return base;
30
+ const parts = target.container ? [{
31
+ ...target.container,
32
+ children: [...target.container.children, ...missing]
33
+ }] : [...target.slots, ...missing];
34
+ const notes = [.../* @__PURE__ */ new Set([...base.notes, ...extra.notes])].filter((note) => parts.length > 1 || !note.includes("disconnected roots"));
30
35
  return {
31
36
  textureSize: base.textureSize[0] === 64 && base.textureSize[1] === 32 ? extra.textureSize : base.textureSize,
32
- parts: target.container ? [{
33
- ...target.container,
34
- children: [...target.container.children, ...missing]
35
- }] : [...target.slots, ...missing],
36
- notes: [.../* @__PURE__ */ new Set([...base.notes, ...extra.notes])]
37
+ parts,
38
+ notes
37
39
  };
38
40
  }
39
41
  function countCubes(part) {
@@ -1,5 +1,5 @@
1
- import { t as parseClassFile } from "./classfile-CAhS5qNf.js";
2
- import { i as mergeModels, r as cubesOf, t as buildsOwnMesh } from "./merge-3HkeQ_6A.js";
1
+ import { t as parseClassFile } from "./classfile-Bo7FUrrD.js";
2
+ import { i as mergeModels, r as cubesOf, t as buildsOwnMesh } from "./merge-NDYxpmL8.js";
3
3
  //#region src/entities/model-bytecode.ts
4
4
  /**
5
5
  * Abstract interpretation of a boxy-model builder, enough to recover the geometry.
@@ -308,6 +308,12 @@ var Interpreter = class Interpreter {
308
308
  });
309
309
  return;
310
310
  }
311
+ const lambda = taken.find((value) => value.kind === "lambda");
312
+ if (lambda?.kind === "lambda" && receiver?.kind === "object" && taken.length === 1) {
313
+ const applied = this.inline(lambda.owner, lambda.name, lambda.descriptor, null, [receiver]);
314
+ this.push(returns === "V" ? null : applied ?? receiver);
315
+ return;
316
+ }
311
317
  if (args.length === 1 && args[0] === "Ljava/lang/String;" && returns.startsWith("L") && target) {
312
318
  const name_ = taken[0].kind === "string" ? taken[0].value : "";
313
319
  const found = target.children.find((child) => child.name === name_);
@@ -619,7 +625,11 @@ var Interpreter = class Interpreter {
619
625
  returns: "V"
620
626
  };
621
627
  for (let count = 0; count < args.length; count++) this.pop();
622
- this.push(returns === "V" ? null : { kind: "unknown" });
628
+ const target = constants.lambdaTarget(index);
629
+ this.push(returns === "V" ? null : target ? {
630
+ kind: "lambda",
631
+ ...target
632
+ } : { kind: "unknown" });
623
633
  break;
624
634
  }
625
635
  case op >= 153 && op <= 166: {
@@ -1,4 +1,4 @@
1
- import { t as parseClassFile } from "./classfile-CAhS5qNf.js";
1
+ import { t as parseClassFile } from "./classfile-Bo7FUrrD.js";
2
2
  //#region src/entities/model-code.ts
3
3
  /**
4
4
  * Which classes in a jar count as model code, and their parsed form.
@@ -1,4 +1,4 @@
1
- import { t as ClassFile } from "./classfile-BwaQjnUM.js";
1
+ import { t as ClassFile } from "./classfile-BdLIk4Pe.js";
2
2
  //#region src/entities/model-code.d.ts
3
3
  interface ModelCode {
4
4
  /** The parsed class, when it is model code a call may be followed into. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodecraft/rendermite",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "Minecraft item icon renderer: renders inventory-identical item icons from vanilla and modded assets across game versions, outputting optimized PNG/WebP/AVIF plus CSS and a JSON item library.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,49 +0,0 @@
1
- import { a as ResourceManager } from "./manager-exOIcdyx.js";
2
- import { S as EntityPackModel } from "./pack-format-QcVFxG_b.js";
3
- //#region src/blocks/entity-models.d.ts
4
- /** What the exporter needs to read code out of; a jar, in practice. */
5
- interface ClassSource {
6
- list: () => Promise<string[]>;
7
- read: (internalName: string) => Promise<Uint8Array | null>;
8
- }
9
- interface EntityGeometryResult {
10
- /** Model id (the class it came from) → geometry. */
11
- models: Record<string, EntityPackModel>;
12
- /** Entity id → model id, for the entity table to point with. */
13
- modelOf: Map<string, string>;
14
- /** Entity sheets the models address, to be stitched into the pack's own atlas. */
15
- spriteIds: Set<string>;
16
- failures: Array<{
17
- id: string;
18
- reason: string;
19
- }>;
20
- }
21
- interface CollectEntityGeometryOptions {
22
- version: string;
23
- /** Where mappings cache; the same directory the jars do. */
24
- cacheDir: string;
25
- classes: ClassSource;
26
- /** Entity ids to look for, as the registry named them. */
27
- entityIds: readonly string[];
28
- /** The sheet each entity resolved to, from the entity registry, keyed by entity id. */
29
- textureOf: ReadonlyMap<string, string>;
30
- /**
31
- * The assets, for the mods whose geometry is not in code at all.
32
- *
33
- * A GeckoLib mob ships Blockbench's bedrock format and registers it by resource location, so there
34
- * is nothing for the interpreter to read; `entity-geo.ts` finds and converts it instead.
35
- */
36
- resources?: ResourceManager;
37
- onProgress?: (done: number, total: number) => void;
38
- }
39
- /**
40
- * Recovers geometry for as many of `entityIds` as the code describes.
41
- *
42
- * Mappings are resolved once: downloaded for an obfuscated jar, and the identity for one that is not
43
- * (from the 26 line the client ships in the clear, and a mod jar never was obfuscated). A version that
44
- * is obfuscated *and* unmapped — 1.13.x — yields nothing, with the reason recorded once rather than
45
- * per entity.
46
- */
47
- declare function collectEntityGeometry(options: CollectEntityGeometryOptions): Promise<EntityGeometryResult>;
48
- //#endregion
49
- export { collectEntityGeometry as i, CollectEntityGeometryOptions as n, EntityGeometryResult as r, ClassSource as t };