@nodecraft/rendermite 1.5.0 → 1.6.0

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 (83) hide show
  1. package/README.md +2 -0
  2. package/dist/blocks/cli.js +1 -1
  3. package/dist/blocks/entities.d.ts +30 -0
  4. package/dist/blocks/entities.js +2 -0
  5. package/dist/blocks/entity-geo.d.ts +18 -0
  6. package/dist/blocks/entity-geo.js +2 -0
  7. package/dist/blocks/entity-models.d.ts +2 -0
  8. package/dist/blocks/entity-models.js +2 -0
  9. package/dist/blocks/export.d.ts +1 -1
  10. package/dist/blocks/export.js +1 -1
  11. package/dist/blocks/item-sprites.d.ts +1 -1
  12. package/dist/blocks/obj-mesh.js +1 -1
  13. package/dist/blocks/pack-format.d.ts +2 -2
  14. package/dist/blocks/sprite-sheet.d.ts +1 -1
  15. package/dist/classfile-BwaQjnUM.d.ts +51 -0
  16. package/dist/classfile-CAhS5qNf.js +255 -0
  17. package/dist/{cli-DMTaIbDI.js → cli-BSKnXBPr.js} +24 -4
  18. package/dist/cli.js +4 -4
  19. package/dist/entities/classfile.d.ts +2 -0
  20. package/dist/entities/classfile.js +2 -0
  21. package/dist/entities/geo-model.d.ts +13 -0
  22. package/dist/entities/geo-model.js +2 -0
  23. package/dist/entities/inherit.d.ts +29 -0
  24. package/dist/entities/inherit.js +2 -0
  25. package/dist/entities/jar-classes.d.ts +26 -0
  26. package/dist/entities/jar-classes.js +2 -0
  27. package/dist/entities/link.d.ts +71 -0
  28. package/dist/entities/link.js +2 -0
  29. package/dist/entities/mappings.d.ts +2 -0
  30. package/dist/entities/mappings.js +2 -0
  31. package/dist/entities/merge.d.ts +18 -0
  32. package/dist/entities/merge.js +2 -0
  33. package/dist/entities/model-bytecode.d.ts +31 -0
  34. package/dist/entities/model-bytecode.js +2 -0
  35. package/dist/entities/model-code.d.ts +2 -0
  36. package/dist/entities/model-code.js +2 -0
  37. package/dist/entities/model.d.ts +2 -0
  38. package/dist/entities/model.js +1 -0
  39. package/dist/entities-DvmA9fEV.js +175 -0
  40. package/dist/{entity-fallback-DutR9Hdz.js → entity-fallback-Bth0fa7m.js} +1 -1
  41. package/dist/entity-geo-B2CkuMWx.js +100 -0
  42. package/dist/entity-models-B6-0r2gR.js +123 -0
  43. package/dist/entity-models-c2HpfdWV.d.ts +49 -0
  44. package/dist/{export-wvt0Fryo.d.ts → export-D8fLC1wS.d.ts} +22 -1
  45. package/dist/{export-sadR0pWp.js → export-DT_drDoI.js} +93 -1
  46. package/dist/geo-CmjrXu0G.d.ts +59 -0
  47. package/dist/{geo-BC8jtG5Q.js → geo-Desq-gRC.js} +6 -5
  48. package/dist/geo-model-Bo1gpEwX.js +163 -0
  49. package/dist/index.d.ts +1 -1
  50. package/dist/index.js +8 -8
  51. package/dist/inherit-KkDsM2N_.js +77 -0
  52. package/dist/jar-classes-Bj15hjdr.js +75 -0
  53. package/dist/link-Bm5oQYh6.js +331 -0
  54. package/dist/mappings-BEPVaiwE.js +139 -0
  55. package/dist/mappings-DxX4KoZl.d.ts +75 -0
  56. package/dist/merge-3HkeQ_6A.js +46 -0
  57. package/dist/model-PnQ4gV0-.d.ts +49 -0
  58. package/dist/model-bytecode-C1nw2G8O.js +732 -0
  59. package/dist/model-code-B7jSFQqd.d.ts +16 -0
  60. package/dist/model-code-BKMEMXxF.js +49 -0
  61. package/dist/mods/prepare.js +1 -1
  62. package/dist/{obj-BaGvPUbb.js → obj-CJHEHpki.js} +5 -5
  63. package/dist/{obj-mesh-CazmV8ya.js → obj-mesh-JwPkZEWL.js} +1 -1
  64. package/dist/{pack-format-oRExIeD3.d.ts → pack-format-QcVFxG_b.d.ts} +100 -1
  65. package/dist/pack.d.ts +1 -1
  66. package/dist/{pipeline-AAfohoHU.js → pipeline-BUIMzMzg.js} +4 -4
  67. package/dist/render/entity-fallback.js +1 -1
  68. package/dist/render/face.js +1 -1
  69. package/dist/render/geo.d.ts +2 -54
  70. package/dist/render/geo.js +2 -2
  71. package/dist/render/obj.js +1 -1
  72. package/dist/render/pipeline.js +1 -1
  73. package/dist/render/renderer.js +1 -1
  74. package/dist/resources/descriptor.js +1 -1
  75. package/dist/{run-UKgVb-kW.js → run-BQJkqc5f.js} +2 -2
  76. package/dist/run.js +1 -1
  77. package/dist/versions/prepare.js +1 -1
  78. package/dist/workers/render-worker.js +2 -2
  79. package/package.json +1 -1
  80. package/dist/{descriptor-D7VKgeGT.js → descriptor-JyXhfd-c.js} +1 -1
  81. package/dist/{face-CMJ3b3Ae.js → face-B2JjWT46.js} +1 -1
  82. package/dist/{prepare-8LswFoS-.js → prepare-D49Gu4Lv.js} +1 -1
  83. package/dist/{prepare-B_tRy9lB.js → prepare-Myd_ec4v.js} +1 -1
package/README.md CHANGED
@@ -76,6 +76,8 @@ blocks/1.21.8/
76
76
  tints.json # plains tints, colormaps, ramps, per-block tint semantics
77
77
  colormap/*.png # the version's own grass/foliage/dry_foliage maps
78
78
  items.json # flat item sprite stacks + their own atlas, for drawing dropped stacks
79
+ entities.json # entity names, marker colours, and which model each uses
80
+ entity-models.json # entity geometry recovered from the client's own bytecode + its atlas
79
81
  failures.json # anything not fully handled, with reasons, never silent
80
82
  meta.json # version, counts, sha256 of every other file
81
83
  ```
@@ -1,2 +1,2 @@
1
- import { t as runBlocksCli } from "../cli-DMTaIbDI.js";
1
+ import { t as runBlocksCli } from "../cli-BSKnXBPr.js";
2
2
  export { runBlocksCli };
@@ -0,0 +1,30 @@
1
+ import { a as ResourceManager } from "../manager-exOIcdyx.js";
2
+ import { i as TextureLoader } from "../loader-DUlx29PC.js";
3
+ import { x as EntityPackEntry } from "../pack-format-QcVFxG_b.js";
4
+ //#region src/blocks/entities.d.ts
5
+ interface EntityPackResult {
6
+ entities: Record<string, EntityPackEntry>;
7
+ failures: Array<{
8
+ id: string;
9
+ reason: string;
10
+ }>;
11
+ }
12
+ /**
13
+ * Every entity type a namespace registers, by its lang keys.
14
+ *
15
+ * Keys with more segments than `<prefix>.<ns>.<name>` are dropped: those are a variant's own label
16
+ * (`entity.minecraft.villager.farmer`) or a death message, never a type.
17
+ */
18
+ declare function entityTypesOf(resources: ResourceManager, namespace: string): Promise<Array<{
19
+ id: string;
20
+ name: string;
21
+ }>>;
22
+ interface CollectEntitiesOptions {
23
+ resources: ResourceManager;
24
+ textures: TextureLoader;
25
+ namespaces: readonly string[];
26
+ onProgress?: (done: number, total: number) => void;
27
+ }
28
+ declare function collectEntities(options: CollectEntitiesOptions): Promise<EntityPackResult>;
29
+ //#endregion
30
+ export { CollectEntitiesOptions, EntityPackResult, collectEntities, entityTypesOf };
@@ -0,0 +1,2 @@
1
+ import { n as entityTypesOf, t as collectEntities } from "../entities-DvmA9fEV.js";
2
+ export { collectEntities, entityTypesOf };
@@ -0,0 +1,18 @@
1
+ import { a as ResourceManager } from "../manager-exOIcdyx.js";
2
+ import { r as ExtractedModel } from "../model-PnQ4gV0-.js";
3
+ //#region src/blocks/entity-geo.d.ts
4
+ interface GeoEntityModel {
5
+ /** Model id: the resource that produced it, which is also what makes it unique in the pack. */
6
+ id: string;
7
+ model: ExtractedModel;
8
+ }
9
+ /**
10
+ * The geometry for one entity, or null when the mod does not ship any under that name.
11
+ *
12
+ * `namespace` and `name` come from the entity id, so `occultism:afrit` looks for
13
+ * `assets/occultism/geo/entity/afrit.geo.json` and its neighbours. Nothing is inferred from the
14
+ * *class* here: a GeckoLib mob has no model class to inspect.
15
+ */
16
+ declare function findGeoForEntity(resources: ResourceManager, namespace: string, name: string): Promise<GeoEntityModel | null>;
17
+ //#endregion
18
+ export { GeoEntityModel, findGeoForEntity };
@@ -0,0 +1,2 @@
1
+ import { t as findGeoForEntity } from "../entity-geo-B2CkuMWx.js";
2
+ export { findGeoForEntity };
@@ -0,0 +1,2 @@
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 };
@@ -0,0 +1,2 @@
1
+ import { t as collectEntityGeometry } from "../entity-models-B6-0r2gR.js";
2
+ export { collectEntityGeometry };
@@ -1,2 +1,2 @@
1
- import { i as exportBlockPack, n as BlockPackResult, r as ExportBlockPackOptions, t as BlockPackFailure } from "../export-wvt0Fryo.js";
1
+ import { i as exportBlockPack, n as BlockPackResult, r as ExportBlockPackOptions, t as BlockPackFailure } from "../export-D8fLC1wS.js";
2
2
  export { BlockPackFailure, BlockPackResult, ExportBlockPackOptions, exportBlockPack };
@@ -1,2 +1,2 @@
1
- import { t as exportBlockPack } from "../export-sadR0pWp.js";
1
+ import { t as exportBlockPack } from "../export-DT_drDoI.js";
2
2
  export { exportBlockPack };
@@ -1,7 +1,7 @@
1
1
  import { a as ResourceManager } from "../manager-exOIcdyx.js";
2
2
  import { i as TextureLoader } from "../loader-DUlx29PC.js";
3
3
  import { t as ModelLoader } from "../loader-DSir1-P0.js";
4
- import { _ as ItemPackEntry } from "../pack-format-oRExIeD3.js";
4
+ import { w as ItemPackEntry } from "../pack-format-QcVFxG_b.js";
5
5
  //#region src/blocks/item-sprites.d.ts
6
6
  interface ItemSpriteFailure {
7
7
  id: string;
@@ -1,2 +1,2 @@
1
- import { n as buildObjMesh, t as ObjMeshError } from "../obj-mesh-CazmV8ya.js";
1
+ import { n as buildObjMesh, t as ObjMeshError } from "../obj-mesh-JwPkZEWL.js";
2
2
  export { ObjMeshError, buildObjMesh };
@@ -1,2 +1,2 @@
1
- import { _ as ItemPackEntry, a as BlockPackBlockStatesFile, c as BlockPackItemsFile, d as BlockPackModelsFile, f as BlockPackRenderLayer, g as BlockPackVariant, h as BlockPackTintsFile, i as BlockPackBlockState, l as BlockPackMetaFile, m as BlockPackSpriteFrame, n as BlockPackAtlasPage, o as BlockPackElement, p as BlockPackSprite, r as BlockPackBiomesFile, s as BlockPackFace, t as BlockPackAtlasFile, u as BlockPackModel, v as ItemPackLayer } from "../pack-format-oRExIeD3.js";
2
- export { BlockPackAtlasFile, BlockPackAtlasPage, BlockPackBiomesFile, BlockPackBlockState, BlockPackBlockStatesFile, BlockPackElement, BlockPackFace, BlockPackItemsFile, BlockPackMetaFile, BlockPackModel, BlockPackModelsFile, BlockPackRenderLayer, BlockPackSprite, BlockPackSpriteFrame, BlockPackTintsFile, BlockPackVariant, ItemPackEntry, ItemPackLayer };
1
+ import { C as EntityPackPart, S as EntityPackModel, T as ItemPackLayer, _ as BlockPackTintsFile, a as BlockPackBlockStatesFile, b as EntityPackCubeFace, c as BlockPackEntityModelsFile, d as BlockPackMetaFile, f as BlockPackModel, g as BlockPackSpriteFrame, h as BlockPackSprite, i as BlockPackBlockState, l as BlockPackFace, m as BlockPackRenderLayer, n as BlockPackAtlasPage, o as BlockPackElement, p as BlockPackModelsFile, r as BlockPackBiomesFile, s as BlockPackEntitiesFile, t as BlockPackAtlasFile, u as BlockPackItemsFile, v as BlockPackVariant, w as ItemPackEntry, x as EntityPackEntry, y as EntityPackCube } from "../pack-format-QcVFxG_b.js";
2
+ export { BlockPackAtlasFile, BlockPackAtlasPage, BlockPackBiomesFile, BlockPackBlockState, BlockPackBlockStatesFile, BlockPackElement, BlockPackEntitiesFile, BlockPackEntityModelsFile, BlockPackFace, BlockPackItemsFile, BlockPackMetaFile, BlockPackModel, BlockPackModelsFile, BlockPackRenderLayer, BlockPackSprite, BlockPackSpriteFrame, BlockPackTintsFile, BlockPackVariant, EntityPackCube, EntityPackCubeFace, EntityPackEntry, EntityPackModel, EntityPackPart, ItemPackEntry, ItemPackLayer };
@@ -1,6 +1,6 @@
1
1
  import { i as TextureLoader, r as Texture } from "../loader-DUlx29PC.js";
2
2
  import { i as PackedPage } from "../atlas-pack-D8745_wo.js";
3
- import { f as BlockPackRenderLayer, p as BlockPackSprite } from "../pack-format-oRExIeD3.js";
3
+ import { h as BlockPackSprite, m as BlockPackRenderLayer } from "../pack-format-QcVFxG_b.js";
4
4
  //#region src/blocks/sprite-sheet.d.ts
5
5
  /**
6
6
  * Vanilla's own id for the missing-texture sprite. A face whose texture does
@@ -0,0 +1,51 @@
1
+ //#region src/entities/classfile.d.ts
2
+ /**
3
+ * A minimal JVM class-file reader: constant pool, methods, and each method's `Code`.
4
+ *
5
+ * Written rather than taken from npm because the whole of what is needed is the constant pool and one
6
+ * attribute — every published class-file library is an order of magnitude more than that, and this
7
+ * runs in a package whose entire dependency list is three entries.
8
+ *
9
+ * It exists because entity models are Java code at every version (see docs/entity-geometry.md), so
10
+ * the only automatic way to recover their geometry is to read the code.
11
+ *
12
+ * Spec: https://docs.oracle.com/javase/specs/jvms/se21/html/jvms-4.html
13
+ */
14
+ type ConstantTag = 'utf8' | 'integer' | 'float' | 'long' | 'double' | 'class' | 'string' | 'fieldref' | 'methodref' | 'interfaceMethodref' | 'nameAndType' | 'methodHandle' | 'methodType' | 'dynamic' | 'invokeDynamic' | 'module' | 'package';
15
+ interface Constant {
16
+ tag: ConstantTag;
17
+ /** Utf8 text, or the numeric value of an integer/float/long/double. */
18
+ value?: string | number | bigint;
19
+ /** Indexes into the pool, by whatever the tag needs. */
20
+ nameIndex?: number;
21
+ classIndex?: number;
22
+ nameAndTypeIndex?: number;
23
+ descriptorIndex?: number;
24
+ stringIndex?: number;
25
+ }
26
+ interface MethodInfo {
27
+ name: string;
28
+ descriptor: string;
29
+ accessFlags: number;
30
+ /** Raw bytecode of the `Code` attribute, absent on an abstract or native method. */
31
+ code?: Uint8Array;
32
+ }
33
+ interface ClassFile {
34
+ thisClass: string;
35
+ superClass: string | null;
36
+ constants: Array<Constant | null>;
37
+ methods: MethodInfo[];
38
+ /** A pool entry as text, for a `utf8` or anything that resolves to one. */
39
+ utf8: (index: number) => string;
40
+ /** `owner.name:descriptor` for a field or method reference. */
41
+ reference: (index: number) => {
42
+ owner: string;
43
+ name: string;
44
+ descriptor: string;
45
+ } | null;
46
+ /** The value an `ldc` of this index pushes: a number for numeric constants, a string for `string`. */
47
+ literal: (index: number) => string | number | bigint | null;
48
+ }
49
+ declare function parseClassFile(bytes: Uint8Array): ClassFile;
50
+ //#endregion
51
+ export { parseClassFile as a, MethodInfo as i, Constant as n, ConstantTag as r, ClassFile as t };
@@ -0,0 +1,255 @@
1
+ //#region src/entities/classfile.ts
2
+ var Reader = class {
3
+ at = 0;
4
+ bytes;
5
+ view;
6
+ constructor(bytes) {
7
+ this.bytes = bytes;
8
+ this.view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
9
+ }
10
+ u1() {
11
+ return this.view.getUint8(this.at++);
12
+ }
13
+ u2() {
14
+ const value = this.view.getUint16(this.at);
15
+ this.at += 2;
16
+ return value;
17
+ }
18
+ u4() {
19
+ const value = this.view.getUint32(this.at);
20
+ this.at += 4;
21
+ return value;
22
+ }
23
+ i4() {
24
+ const value = this.view.getInt32(this.at);
25
+ this.at += 4;
26
+ return value;
27
+ }
28
+ f4() {
29
+ const value = this.view.getFloat32(this.at);
30
+ this.at += 4;
31
+ return value;
32
+ }
33
+ f8() {
34
+ const value = this.view.getFloat64(this.at);
35
+ this.at += 8;
36
+ return value;
37
+ }
38
+ i8() {
39
+ const value = this.view.getBigInt64(this.at);
40
+ this.at += 8;
41
+ return value;
42
+ }
43
+ utf8(length) {
44
+ const text = new TextDecoder("utf-8").decode(this.bytes.subarray(this.at, this.at + length));
45
+ this.at += length;
46
+ return text;
47
+ }
48
+ skip(count) {
49
+ this.at += count;
50
+ }
51
+ take(count) {
52
+ const slice = this.bytes.subarray(this.at, this.at + count);
53
+ this.at += count;
54
+ return slice;
55
+ }
56
+ };
57
+ /** Pool tags, by their spec number. `null` marks the two that take two slots. */
58
+ const TAGS = {
59
+ 1: "utf8",
60
+ 3: "integer",
61
+ 4: "float",
62
+ 5: "long",
63
+ 6: "double",
64
+ 7: "class",
65
+ 8: "string",
66
+ 9: "fieldref",
67
+ 10: "methodref",
68
+ 11: "interfaceMethodref",
69
+ 12: "nameAndType",
70
+ 15: "methodHandle",
71
+ 16: "methodType",
72
+ 17: "dynamic",
73
+ 18: "invokeDynamic",
74
+ 19: "module",
75
+ 20: "package"
76
+ };
77
+ function readConstantPool(reader) {
78
+ const count = reader.u2();
79
+ const constants = [null];
80
+ for (let index = 1; index < count; index++) {
81
+ const raw = reader.u1();
82
+ const tag = TAGS[raw];
83
+ if (!tag) throw new Error(`Unknown constant pool tag ${raw} at ${index}`);
84
+ switch (tag) {
85
+ case "utf8":
86
+ constants.push({
87
+ tag,
88
+ value: reader.utf8(reader.u2())
89
+ });
90
+ break;
91
+ case "integer":
92
+ constants.push({
93
+ tag,
94
+ value: reader.i4()
95
+ });
96
+ break;
97
+ case "float":
98
+ constants.push({
99
+ tag,
100
+ value: reader.f4()
101
+ });
102
+ break;
103
+ case "long":
104
+ constants.push({
105
+ tag,
106
+ value: reader.i8()
107
+ });
108
+ constants.push(null);
109
+ index++;
110
+ break;
111
+ case "double":
112
+ constants.push({
113
+ tag,
114
+ value: reader.f8()
115
+ });
116
+ constants.push(null);
117
+ index++;
118
+ break;
119
+ case "class":
120
+ case "module":
121
+ case "package":
122
+ constants.push({
123
+ tag,
124
+ nameIndex: reader.u2()
125
+ });
126
+ break;
127
+ case "string":
128
+ constants.push({
129
+ tag,
130
+ stringIndex: reader.u2()
131
+ });
132
+ break;
133
+ case "fieldref":
134
+ case "methodref":
135
+ case "interfaceMethodref":
136
+ constants.push({
137
+ tag,
138
+ classIndex: reader.u2(),
139
+ nameAndTypeIndex: reader.u2()
140
+ });
141
+ break;
142
+ case "nameAndType":
143
+ constants.push({
144
+ tag,
145
+ nameIndex: reader.u2(),
146
+ descriptorIndex: reader.u2()
147
+ });
148
+ break;
149
+ case "methodHandle":
150
+ reader.skip(1);
151
+ constants.push({
152
+ tag,
153
+ nameAndTypeIndex: reader.u2()
154
+ });
155
+ break;
156
+ case "methodType":
157
+ constants.push({
158
+ tag,
159
+ descriptorIndex: reader.u2()
160
+ });
161
+ break;
162
+ case "dynamic":
163
+ case "invokeDynamic":
164
+ reader.skip(2);
165
+ constants.push({
166
+ tag,
167
+ nameAndTypeIndex: reader.u2()
168
+ });
169
+ }
170
+ }
171
+ return constants;
172
+ }
173
+ /** Skips an attribute table, returning the `Code` bytes if one of them is a Code attribute. */
174
+ function readAttributes(reader, utf8) {
175
+ let code;
176
+ const count = reader.u2();
177
+ for (let index = 0; index < count; index++) {
178
+ const name = utf8(reader.u2());
179
+ const length = reader.u4();
180
+ if (name !== "Code") {
181
+ reader.skip(length);
182
+ continue;
183
+ }
184
+ reader.skip(4);
185
+ code = reader.take(reader.u4());
186
+ reader.skip(reader.u2() * 8);
187
+ readAttributes(reader, utf8);
188
+ }
189
+ return code;
190
+ }
191
+ function parseClassFile(bytes) {
192
+ const reader = new Reader(bytes);
193
+ if (reader.u4() !== 3405691582) throw new Error("Not a class file: bad magic");
194
+ reader.skip(4);
195
+ const constants = readConstantPool(reader);
196
+ const utf8 = (index) => {
197
+ const entry = constants[index];
198
+ if (!entry) return "";
199
+ if (entry.tag === "utf8") return String(entry.value);
200
+ const next = entry.nameIndex ?? entry.stringIndex ?? entry.descriptorIndex;
201
+ return next === void 0 ? "" : utf8(next);
202
+ };
203
+ reader.skip(2);
204
+ const thisClass = utf8(reader.u2());
205
+ const superIndex = reader.u2();
206
+ const superClass = superIndex === 0 ? null : utf8(superIndex);
207
+ reader.skip(reader.u2() * 2);
208
+ const fieldCount = reader.u2();
209
+ for (let index = 0; index < fieldCount; index++) {
210
+ reader.skip(6);
211
+ readAttributes(reader, utf8);
212
+ }
213
+ const methods = [];
214
+ const methodCount = reader.u2();
215
+ for (let index = 0; index < methodCount; index++) {
216
+ const accessFlags = reader.u2();
217
+ const name = utf8(reader.u2());
218
+ const descriptor = utf8(reader.u2());
219
+ const code = readAttributes(reader, utf8);
220
+ methods.push({
221
+ name,
222
+ descriptor,
223
+ accessFlags,
224
+ code
225
+ });
226
+ }
227
+ const reference = (index) => {
228
+ const entry = constants[index];
229
+ if (!entry || entry.classIndex === void 0 || entry.nameAndTypeIndex === void 0) return null;
230
+ const nameAndType = constants[entry.nameAndTypeIndex];
231
+ if (!nameAndType?.nameIndex || !nameAndType.descriptorIndex) return null;
232
+ return {
233
+ owner: utf8(entry.classIndex),
234
+ name: utf8(nameAndType.nameIndex),
235
+ descriptor: utf8(nameAndType.descriptorIndex)
236
+ };
237
+ };
238
+ const literal = (index) => {
239
+ const entry = constants[index];
240
+ if (!entry) return null;
241
+ if (entry.tag === "string") return utf8(index);
242
+ return entry.value ?? null;
243
+ };
244
+ return {
245
+ thisClass,
246
+ superClass,
247
+ constants,
248
+ methods,
249
+ utf8,
250
+ reference,
251
+ literal
252
+ };
253
+ }
254
+ //#endregion
255
+ export { parseClassFile as t };
@@ -1,9 +1,10 @@
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-sadR0pWp.js";
4
- import { n as prepareModResources } from "./prepare-B_tRy9lB.js";
3
+ import { t as exportBlockPack } from "./export-DT_drDoI.js";
4
+ import { t as JarClassReader } from "./jar-classes-Bj15hjdr.js";
5
+ import { n as prepareModResources } from "./prepare-Myd_ec4v.js";
5
6
  import { t as downloadClientJar } from "./download-1wAfrGKx.js";
6
- import { a as prepareVersionResources, r as compareVersions } from "./prepare-8LswFoS-.js";
7
+ import { a as prepareVersionResources, r as compareVersions } from "./prepare-D49Gu4Lv.js";
7
8
  import path from "node:path";
8
9
  import os from "node:os";
9
10
  import { parseArgs } from "node:util";
@@ -35,6 +36,8 @@ Options:
35
36
  --builtin <dir> override the vendored geometry pack
36
37
  --no-builtin do not substitute geometry for code-drawn blocks
37
38
  --no-items do not export items.json (flat sprites for non-block items)
39
+ --no-entities do not export entities.json (entity names and marker colours)
40
+ --no-entity-geometry do not read the jar's code for entity model geometry
38
41
  --cache-dir <dir> jar download cache (default ~/.rendermite)
39
42
  `;
40
43
  /**
@@ -98,6 +101,14 @@ async function runBlocksCli(argv) {
98
101
  type: "boolean",
99
102
  default: false
100
103
  },
104
+ "no-entities": {
105
+ type: "boolean",
106
+ default: false
107
+ },
108
+ "no-entity-geometry": {
109
+ type: "boolean",
110
+ default: false
111
+ },
101
112
  "help": {
102
113
  type: "boolean",
103
114
  short: "h",
@@ -120,12 +131,15 @@ async function runBlocksCli(argv) {
120
131
  }
121
132
  const cacheDir = values["cache-dir"] ?? path.join(os.homedir(), ".rendermite");
122
133
  let resources;
134
+ let classes = null;
123
135
  if (values.version) {
124
136
  console.log(`Fetching client jar for ${values.version}…`);
137
+ const jar = await downloadClientJar(values.version, cacheDir);
125
138
  resources = await prepareVersionResources({
126
139
  version: values.version,
127
- jar: await downloadClientJar(values.version, cacheDir)
140
+ jar
128
141
  });
142
+ if (!values["no-entity-geometry"]) classes = new JarClassReader(jar);
129
143
  } else {
130
144
  const managers = (values.assets ?? []).map((root) => new FolderResourceManager(root));
131
145
  resources = managers.length === 1 ? managers[0] : new LayeredResourceManager(managers);
@@ -152,17 +166,23 @@ async function runBlocksCli(argv) {
152
166
  padding: sizes.padding,
153
167
  maxPageSize: sizes.maxPageSize,
154
168
  items: !values["no-items"],
169
+ entities: !values["no-entities"],
170
+ classes: classes ?? void 0,
171
+ cacheDir,
155
172
  onProgress: (stage, done, total) => {
156
173
  if (done === total || done % 250 === 0) console.log(`${stage}: ${done}/${total}`);
157
174
  }
158
175
  });
159
176
  console.log(`\n${result.blocks} blocks, ${result.models} models, ${result.sprites} sprites across ${result.pages} atlas page(s); ${result.writtenFiles} files written.`);
160
177
  console.log(result.items > 0 ? `${result.items} flat items described in items.json.` : "No flat item sprites exported.");
178
+ console.log(result.entities > 0 ? `${result.entities} entity types described in entities.json.` : "No entity types exported.");
179
+ console.log(result.entityModels > 0 ? `${result.entityModels} entity models recovered from the jar's own code.` : "No entity geometry recovered.");
161
180
  console.log(result.biomes > 0 ? `${result.biomes} biomes described in biomes.json.` : "No biomes to describe; biomes.json not written.");
162
181
  console.log(`${result.failures.length} entries in failures.json.`);
163
182
  return 0;
164
183
  } finally {
165
184
  await closeMods?.();
185
+ await classes?.close();
166
186
  }
167
187
  }
168
188
  //#endregion
package/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { n as builtinPackPath, t as bedCompatPath } from "./builtin-WkWjATeh.js";
3
3
  import { n as LayeredResourceManager, t as FolderResourceManager } from "./manager-BNibYkmI.js";
4
+ import { t as JarResourceManager } from "./jar-W2cV2ZVO.js";
4
5
  import { t as curatedModelOverrides } from "./models-CZjCOjs4.js";
5
6
  import { n as harvestTintOverrides, t as curatedTintOverrides } from "./tints-BspVCz2G.js";
6
- import { t as JarResourceManager } from "./jar-W2cV2ZVO.js";
7
7
  import { t as downloadClientJar } from "./download-1wAfrGKx.js";
8
- import { a as prepareVersionResources, i as eraForVersion, n as GEOMETRY_DONOR_VERSIONS } from "./prepare-8LswFoS-.js";
9
- import { t as runBlocksCli } from "./cli-DMTaIbDI.js";
10
- import { t as run } from "./run-UKgVb-kW.js";
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";
11
11
  import path from "node:path";
12
12
  import os from "node:os";
13
13
  import { parseArgs } from "node:util";
@@ -0,0 +1,2 @@
1
+ import { a as parseClassFile, i as MethodInfo, n as Constant, r as ConstantTag, t as ClassFile } from "../classfile-BwaQjnUM.js";
2
+ export { ClassFile, Constant, ConstantTag, MethodInfo, parseClassFile };
@@ -0,0 +1,2 @@
1
+ import { t as parseClassFile } from "../classfile-CAhS5qNf.js";
2
+ export { parseClassFile };
@@ -0,0 +1,13 @@
1
+ import { r as ExtractedModel } from "../model-PnQ4gV0-.js";
2
+ import { t as ParsedGeo } from "../geo-CmjrXu0G.js";
3
+ //#region src/entities/geo-model.d.ts
4
+ /**
5
+ * Converts one parsed `.geo.json` into a model.
6
+ *
7
+ * Bones are a flat list joined by `parent` name, so the tree is rebuilt here. A bone whose parent is
8
+ * missing becomes a root rather than being dropped, and a cube carrying its own rotation becomes a part
9
+ * of its own: `Cube` has nowhere to put a rotation, and 18% of the corpus's cubes have one.
10
+ */
11
+ declare function geoToModel(geo: ParsedGeo): ExtractedModel;
12
+ //#endregion
13
+ export { geoToModel };
@@ -0,0 +1,2 @@
1
+ import { t as geoToModel } from "../geo-model-Bo1gpEwX.js";
2
+ export { geoToModel };
@@ -0,0 +1,29 @@
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";
4
+ //#region src/entities/inherit.d.ts
5
+ interface Ancestry {
6
+ /** The class and its ancestors by internal name, parsed. */
7
+ ancestors: Map<string, ClassFile>;
8
+ /** The same classes, most derived first, with the bytes to interpret. */
9
+ chain: Array<{
10
+ internalName: string;
11
+ bytes: Uint8Array;
12
+ }>;
13
+ }
14
+ /** Reads a class and everything it inherits from that the jar still holds. */
15
+ declare function ancestryOf(internalName: string, read: (internalName: string) => Promise<Uint8Array | null>): Promise<Ancestry>;
16
+ /**
17
+ * Geometry for one class, with the code it builds on available and its ancestors' parts filled in.
18
+ *
19
+ * `code` widens what a call may be followed into beyond the ancestors, which some models need: the
20
+ * witch's body is the villager's, and a donkey's chest comes from the saddle model. Without it those
21
+ * models still come out, minus the piece the other class holds.
22
+ *
23
+ * Every ancestor is merged rather than only the first with boxes, because a deep hierarchy splits
24
+ * several ways: 1.16.5's sheep overrides a head in `SheepFurModel` and takes its legs from
25
+ * `QuadrupedModel` two hops up.
26
+ */
27
+ declare function extractInheritedModel(internalName: string, read: (internalName: string) => Promise<Uint8Array | null>, code?: ModelCode): Promise<ExtractedModel | null>;
28
+ //#endregion
29
+ export { Ancestry, ancestryOf, extractInheritedModel };
@@ -0,0 +1,2 @@
1
+ import { n as extractInheritedModel, t as ancestryOf } from "../inherit-KkDsM2N_.js";
2
+ export { ancestryOf, extractInheritedModel };
@@ -0,0 +1,26 @@
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 };
@@ -0,0 +1,2 @@
1
+ import { t as JarClassReader } from "../jar-classes-Bj15hjdr.js";
2
+ export { JarClassReader };