@nodecraft/rendermite 1.6.0 → 1.6.2

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 (53) hide show
  1. package/dist/{block-entities-xv3bQpEX.js → block-entities-XAynAVUE.js} +1 -1
  2. package/dist/blocks/block-entities.js +1 -1
  3. package/dist/blocks/cli.js +1 -1
  4. package/dist/blocks/entities.js +1 -1
  5. package/dist/blocks/entity-models.d.ts +45 -2
  6. package/dist/blocks/entity-models.js +1 -1
  7. package/dist/blocks/export.d.ts +1 -1
  8. package/dist/blocks/export.js +1 -1
  9. package/dist/{classfile-BwaQjnUM.d.ts → classfile-BdLIk4Pe.d.ts} +16 -0
  10. package/dist/{classfile-CAhS5qNf.js → classfile-Bo7FUrrD.js} +42 -10
  11. package/dist/{cli-BSKnXBPr.js → cli-Br0mY0LV.js} +6 -2
  12. package/dist/cli.js +2 -2
  13. package/dist/entities/classfile.d.ts +1 -1
  14. package/dist/entities/classfile.js +1 -1
  15. package/dist/entities/inherit.d.ts +2 -2
  16. package/dist/entities/inherit.js +1 -1
  17. package/dist/entities/jar-classes.d.ts +2 -26
  18. package/dist/entities/jar-classes.js +2 -2
  19. package/dist/entities/link.d.ts +2 -2
  20. package/dist/entities/link.js +1 -1
  21. package/dist/entities/merge.d.ts +16 -1
  22. package/dist/entities/merge.js +2 -2
  23. package/dist/entities/model-bytecode.d.ts +1 -1
  24. package/dist/entities/model-bytecode.js +1 -1
  25. package/dist/entities/model-code.d.ts +1 -1
  26. package/dist/entities/model-code.js +1 -1
  27. package/dist/{entities-DvmA9fEV.js → entities-DubtdM11.js} +6 -2
  28. package/dist/{entity-fallback-Bth0fa7m.js → entity-fallback-BcJWh91-.js} +1 -1
  29. package/dist/{entity-models-B6-0r2gR.js → entity-models-D_QGok9j.js} +9 -5
  30. package/dist/{entity-textures-DFRIVdF1.js → entity-textures-4XXT8jVI.js} +25 -2
  31. package/dist/{export-D8fLC1wS.d.ts → export-B8tPsf4K.d.ts} +1 -1
  32. package/dist/{export-DT_drDoI.js → export-CTKEwro6.js} +3 -3
  33. package/dist/index.d.ts +1 -1
  34. package/dist/index.js +2 -2
  35. package/dist/{inherit-KkDsM2N_.js → inherit-C5Ifg3SM.js} +4 -4
  36. package/dist/{jar-classes-Bj15hjdr.js → jar-classes-3GVCJZT7.js} +38 -1
  37. package/dist/jar-classes-CSRrPAUy.d.ts +41 -0
  38. package/dist/{link-Bm5oQYh6.js → link-5GmBLTzk.js} +25 -1
  39. package/dist/merge-DeHruviG.js +109 -0
  40. package/dist/{model-bytecode-C1nw2G8O.js → model-bytecode-BQKCLPze.js} +151 -39
  41. package/dist/{model-code-BKMEMXxF.js → model-code-1Vuk-zj_.js} +1 -1
  42. package/dist/{model-code-B7jSFQqd.d.ts → model-code-BY44ao27.d.ts} +1 -1
  43. package/dist/{pipeline-BUIMzMzg.js → pipeline-7rvL6vx1.js} +1 -1
  44. package/dist/render/entity-fallback.js +1 -1
  45. package/dist/render/pipeline.js +1 -1
  46. package/dist/resources/entity-textures.d.ts +13 -1
  47. package/dist/resources/entity-textures.js +2 -2
  48. package/dist/{run-BQJkqc5f.js → run-BXAqZ5qY.js} +1 -1
  49. package/dist/run.js +1 -1
  50. package/dist/workers/render-worker.js +1 -1
  51. package/package.json +1 -1
  52. package/dist/entity-models-c2HpfdWV.d.ts +0 -49
  53. package/dist/merge-3HkeQ_6A.js +0 -46
@@ -1,5 +1,5 @@
1
1
  import { n as ResourceLocator } from "./locator-COMEtEn9.js";
2
- import { a as findChestTexture, c as findFluidStill, i as findBedTexture, l as findMobTexture, n as HEAD_LAYOUTS, o as findEntityTexture, r as coversSheet, s as findFluidSibling, t as DYE_COLORS } from "./entity-textures-DFRIVdF1.js";
2
+ import { a as findBedTexture, c as findFluidSibling, i as coversSheet, l as findFluidStill, n as HEAD_LAYOUTS, o as findChestTexture, s as findEntityTexture, t as DYE_COLORS, u as findMobTexture } from "./entity-textures-4XXT8jVI.js";
3
3
  //#region src/blocks/block-entities.ts
4
4
  /**
5
5
  * Geometry for blocks the game draws from Java rather than from a model.
@@ -1,2 +1,2 @@
1
- import { n as blockEntityGeometry, r as synthesizeVariants, t as INVISIBLE_BLOCKS } from "../block-entities-xv3bQpEX.js";
1
+ import { n as blockEntityGeometry, r as synthesizeVariants, t as INVISIBLE_BLOCKS } from "../block-entities-XAynAVUE.js";
2
2
  export { INVISIBLE_BLOCKS, blockEntityGeometry, synthesizeVariants };
@@ -1,2 +1,2 @@
1
- import { t as runBlocksCli } from "../cli-BSKnXBPr.js";
1
+ import { t as runBlocksCli } from "../cli-Br0mY0LV.js";
2
2
  export { runBlocksCli };
@@ -1,2 +1,2 @@
1
- import { n as entityTypesOf, t as collectEntities } from "../entities-DvmA9fEV.js";
1
+ import { n as entityTypesOf, t as collectEntities } from "../entities-DubtdM11.js";
2
2
  export { collectEntities, entityTypesOf };
@@ -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-D_QGok9j.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-CTKEwro6.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-CTKEwro6.js";
4
+ import { n as layeredClasses, t as JarClassReader } from "./jar-classes-3GVCJZT7.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,8 +6,8 @@ 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";
10
- import { t as run } from "./run-BQJkqc5f.js";
9
+ import { t as runBlocksCli } from "./cli-Br0mY0LV.js";
10
+ import { t as run } from "./run-BXAqZ5qY.js";
11
11
  import path from "node:path";
12
12
  import os from "node:os";
13
13
  import { parseArgs } from "node:util";
@@ -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-C5Ifg3SM.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-3GVCJZT7.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 };
@@ -12,7 +12,22 @@ declare function slotsOf(parts: Part[]): {
12
12
  declare function buildsOwnMesh(model: ExtractedModel): boolean;
13
13
  /** `base` plus the parts of `extra` that `base` does not name. */
14
14
  declare function mergeModels(base: ExtractedModel, extra: ExtractedModel): ExtractedModel;
15
+ /**
16
+ * Drops boxes that land exactly where one already is.
17
+ *
18
+ * A model builder's branches are all taken, because they turn on a constructor argument this cannot
19
+ * know — a `CubeDeformation`, a baby-variant flag — so a model that builds one shape *or* another
20
+ * emits both. Where the two arms differ, that is the honest answer and the model says so in a note.
21
+ * Where they agree, it is four legs drawn twice in the same place: `HorseModel` builds
22
+ * `left_hind_leg` and `left_hind_baby_leg` at identical coordinates, and two coplanar boxes are
23
+ * exactly what z-fighting is.
24
+ *
25
+ * Keyed on the accumulated pivot and rotation rather than on evaluated corners, since duplicates come
26
+ * from one builder running twice and land on identical frames. The first is kept: a builder states the
27
+ * ordinary shape before the variant.
28
+ */
29
+ declare function dedupeCubes(model: ExtractedModel): ExtractedModel;
15
30
  declare function countCubes(part: Part): number;
16
31
  declare function cubesOf(model: ExtractedModel): number;
17
32
  //#endregion
18
- export { buildsOwnMesh, countCubes, cubesOf, mergeModels, slotsOf };
33
+ export { buildsOwnMesh, countCubes, cubesOf, dedupeCubes, mergeModels, slotsOf };
@@ -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";
2
- export { buildsOwnMesh, countCubes, cubesOf, mergeModels, slotsOf };
1
+ import { a as mergeModels, i as dedupeCubes, n as countCubes, o as slotsOf, r as cubesOf, t as buildsOwnMesh } from "../merge-DeHruviG.js";
2
+ export { buildsOwnMesh, countCubes, cubesOf, dedupeCubes, 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-BQKCLPze.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,5 +1,5 @@
1
1
  import { n as ResourceLocator } from "./locator-COMEtEn9.js";
2
- import { l as findMobTexture, u as tokens } from "./entity-textures-DFRIVdF1.js";
2
+ import { d as isOverlayPath, f as tokens, u as findMobTexture } from "./entity-textures-4XXT8jVI.js";
3
3
  //#region src/blocks/entities.ts
4
4
  /**
5
5
  * The entity registry, and one colour per entity.
@@ -125,13 +125,17 @@ async function findVariantTexture(resources, namespace, name) {
125
125
  if (!locator.path.startsWith("entity/")) continue;
126
126
  const leaf = locator.path.split("/").at(-1) ?? "";
127
127
  if (tokens(leaf).some((token) => NOT_THE_MOB.has(token))) continue;
128
+ if (isOverlayPath(locator.path)) continue;
128
129
  const candidate = tokens(locator.path);
129
130
  let score = 0;
130
131
  for (const token of wanted) if (candidate.includes(token)) score += 2;
131
132
  if (squashed !== name && candidate.includes(squashed)) score += wanted.length * 2;
132
133
  if (score === 0) continue;
134
+ const folder = locator.path.split("/").slice(1, -1);
135
+ const inFamily = folder.length > 0 && folder.flatMap((segment) => tokens(segment)).every((token) => wanted.includes(token));
136
+ const named = tokens(leaf).some((token) => wanted.includes(token));
133
137
  const depth = locator.path.split("/").length;
134
- score = score * 10 - depth - candidate.length;
138
+ score = (inFamily ? 1e3 : 0) + score * 10 + (named ? 5 : 0) - depth - candidate.length;
135
139
  if (score > bestScore) {
136
140
  best = locator;
137
141
  bestScore = score;
@@ -1,5 +1,5 @@
1
1
  import { n as ResourceLocator } from "./locator-COMEtEn9.js";
2
- import { a as findChestTexture, i as findBedTexture, l as findMobTexture, n as HEAD_LAYOUTS, o as findEntityTexture, r as coversSheet, t as DYE_COLORS, u as tokens } from "./entity-textures-DFRIVdF1.js";
2
+ import { a as findBedTexture, f as tokens, i as coversSheet, n as HEAD_LAYOUTS, o as findChestTexture, s as findEntityTexture, t as DYE_COLORS, u as findMobTexture } from "./entity-textures-4XXT8jVI.js";
3
3
  import { c as renderModel } from "./obj-CJHEHpki.js";
4
4
  //#region src/render/entity-fallback.ts
5
5
  /**
@@ -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-C5Ifg3SM.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] = {
@@ -68,6 +68,29 @@ const HEAD_LAYOUTS = {
68
68
  * live at entity/<mob>.png or entity/<mob>/<mob>.png depending on the mod, and a
69
69
  * head only ever wants the base skin — never a blink or armour overlay.
70
70
  */
71
+ /**
72
+ * Directories that hold an *overlay* rather than a mob.
73
+ *
74
+ * Matched as whole path segments rather than as tokens, because a token would take `chest_boat` out
75
+ * along with `chest`. A trader llama is the case that needed it: its sheet is filed as
76
+ * `entity/llama/decor/trader_llama`, whose leaf is exactly the mob's name — so a search by name found
77
+ * the carpet it wears, which is a few opaque pixels on a transparent sheet, and the llama underneath
78
+ * came out invisible on most of its faces.
79
+ */
80
+ const OVERLAY_DIRECTORIES = /* @__PURE__ */ new Set([
81
+ "decor",
82
+ "armor",
83
+ "markings",
84
+ "glow",
85
+ "eyes",
86
+ "overlay",
87
+ "saddle",
88
+ "harness"
89
+ ]);
90
+ /** Whether a texture is filed inside one of those, whatever the file itself is called. */
91
+ function isOverlayPath(path) {
92
+ return path.split("/").slice(0, -1).some((segment) => OVERLAY_DIRECTORIES.has(segment));
93
+ }
71
94
  async function findMobTexture(resources, namespace, mob) {
72
95
  for (const source of [namespace, "minecraft"]) {
73
96
  for (const candidate of [`entity/${mob}`, `entity/${mob}/${mob}`]) {
@@ -77,7 +100,7 @@ async function findMobTexture(resources, namespace, mob) {
77
100
  let best = null;
78
101
  for (const locator of await resources.listResources("texture", source)) {
79
102
  const leaf = locator.path.split("/").pop();
80
- if (!locator.path.startsWith("entity/") || leaf !== mob) continue;
103
+ if (!locator.path.startsWith("entity/") || leaf !== mob || isOverlayPath(locator.path)) continue;
81
104
  if (best === null || locator.path.length < best.path.length) best = locator;
82
105
  }
83
106
  if (best) return best;
@@ -206,4 +229,4 @@ async function findFluidSibling(resources, still, suffixes) {
206
229
  return null;
207
230
  }
208
231
  //#endregion
209
- export { findChestTexture as a, findFluidStill as c, findBedTexture as i, findMobTexture as l, HEAD_LAYOUTS as n, findEntityTexture as o, coversSheet as r, findFluidSibling as s, DYE_COLORS as t, tokens as u };
232
+ export { findBedTexture as a, findFluidSibling as c, isOverlayPath as d, tokens as f, coversSheet as i, findFluidStill as l, HEAD_LAYOUTS as n, findChestTexture as o, OVERLAY_DIRECTORIES as r, findEntityTexture as s, DYE_COLORS as t, findMobTexture as u };
@@ -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;
@@ -1,9 +1,9 @@
1
1
  import { r as buildBiomeClimates } from "./biomes-5ZwYxMYe.js";
2
2
  import { n as ResourceLocator } from "./locator-COMEtEn9.js";
3
- import { n as blockEntityGeometry, r as synthesizeVariants, t as INVISIBLE_BLOCKS } from "./block-entities-xv3bQpEX.js";
3
+ import { n as blockEntityGeometry, r as synthesizeVariants, t as INVISIBLE_BLOCKS } from "./block-entities-XAynAVUE.js";
4
4
  import { a as parseBlockState, n as collectModels } from "./blockstate-eval-BRQ3NWY2.js";
5
- import { t as collectEntities } from "./entities-DvmA9fEV.js";
6
- import { t as collectEntityGeometry } from "./entity-models-B6-0r2gR.js";
5
+ import { t as collectEntities } from "./entities-DubtdM11.js";
6
+ import { t as collectEntityGeometry } from "./entity-models-D_QGok9j.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-CTKEwro6.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";
@@ -22,5 +22,5 @@ import { n as encodeIcon, t as encodeAnimatedIcon } from "./encode-LR9wxigC.js";
22
22
  import { a as builtinDynamicResources } from "./generators-BCZVlWig.js";
23
23
  import { t as minifyStylesheet } from "./minify-bjMRmr5J.js";
24
24
  import { n as itemClass, t as generateStylesheet } from "./stylesheet-CovT3B2S.js";
25
- import { t as run } from "./run-BQJkqc5f.js";
25
+ import { t as run } from "./run-BXAqZ5qY.js";
26
26
  export { AnimatedTexture, AtlasSourceError, BlockStateError, DEFAULT_WATER_COLOR, DYE_COLORS, FolderResourceManager, InvalidItemDefinitionError, InvalidResourceLocatorError, InvalidTinterDefinitionError, ItemRenderError, ItemResolutionError, JarResourceManager, LayeredResourceManager, LightingProfile, ModelLoader, ModelResolutionError, ObjMeshError, ResourceKind, ResourceLocator, TextureLoader, TextureResolutionError, UNKNOWN_MODEL, UNREGISTERED_TINTS, UnsafeJarError, VANILLA_BIOME_CLIMATES, boxDownscale, buildBiomeClimates, buildBlockTints, buildObjMesh, builtinDynamicResources, collectModels, compareVersions, createAtlasResolver, defaultProperties, discoverItems, encodeAnimatedIcon, encodeIcon, eraForVersion, evaluateBlockState, evaluateItemModel, exportBlockPack, generateStylesheet, isUnsafeEntryPath, itemClass, lightsForProfile, matchesCondition, minifyStylesheet, packAtlas, parseAtlasSources, parseBiomeClimate, parseBlockState, parseTintValue, pointResize, prepareModResources, prepareVersionResources, renderModel, renderModelFrames, resolveItem, resolveTexture, resolveTint, resolveTints, run, salvageJson, toByteTexture, toFloatTexture, weightedVariantIndex };
@@ -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 { a as mergeModels, i as dedupeCubes } from "./merge-DeHruviG.js";
3
+ import { t as extractModel } from "./model-bytecode-BQKCLPze.js";
4
4
  //#region src/entities/inherit.ts
5
5
  /**
6
6
  * A model class read together with its ancestors.
@@ -71,7 +71,7 @@ async function extractInheritedModel(internalName, read, code) {
71
71
  });
72
72
  model = mergeModels(model, inheritedModel);
73
73
  }
74
- return model;
74
+ return dedupeCubes(model);
75
75
  }
76
76
  //#endregion
77
77
  export { extractInheritedModel as n, ancestryOf as t };
@@ -13,6 +13,43 @@ 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) try {
29
+ for (const name of await source.list()) names.add(name);
30
+ } catch {
31
+ continue;
32
+ }
33
+ return [...names];
34
+ },
35
+ read: async (internalName) => {
36
+ for (const source of sources) try {
37
+ const bytes = await source.read(internalName);
38
+ if (bytes) return bytes;
39
+ } catch {
40
+ continue;
41
+ }
42
+ return null;
43
+ },
44
+ close: async () => {
45
+ for (const source of sources) try {
46
+ await source.close();
47
+ } catch {
48
+ continue;
49
+ }
50
+ }
51
+ };
52
+ }
16
53
  /** Reads class files out of one jar, by internal name. */
17
54
  var JarClassReader = class {
18
55
  jarPath;
@@ -72,4 +109,4 @@ var JarClassReader = class {
72
109
  }
73
110
  };
74
111
  //#endregion
75
- export { JarClassReader as t };
112
+ export { layeredClasses as n, JarClassReader as t };