@nodecraft/rendermite 1.6.8 → 1.7.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.
- package/assets/builtin/mobheads/models/item/base/head_64_64_hat.json +31 -0
- package/assets/builtin/mobheads/models/item/player_skin.json +7 -0
- package/assets/builtin/renderchest/models/block/wall_sign.json +3 -3
- package/dist/{block-entities-XAynAVUE.js → block-entities-CPQeb5dV.js} +1 -1
- package/dist/blocks/block-entities.js +1 -1
- package/dist/blocks/cli.js +1 -1
- package/dist/blocks/ender-storage.d.ts +1 -1
- package/dist/blocks/entities.d.ts +1 -1
- package/dist/blocks/entity-models.d.ts +24 -2
- package/dist/blocks/entity-models.js +2 -2
- package/dist/blocks/export.js +1 -1
- package/dist/blocks/geo-blocks.d.ts +1 -1
- package/dist/blocks/item-sprites.d.ts +1 -1
- package/dist/blocks/pack-format.d.ts +2 -2
- package/dist/blocks/pack-format.js +2 -1
- package/dist/blocks/sprite-sheet.d.ts +1 -1
- package/dist/{cli-DLQHtzP3.js → cli-DFIB9i9c.js} +1 -1
- package/dist/cli.js +2 -2
- package/dist/dynamic/generators.js +1 -1
- package/dist/entities/inherit.js +1 -1
- package/dist/entities/link.d.ts +1 -1
- package/dist/entities/model-bytecode.d.ts +16 -1
- package/dist/entities/model-bytecode.js +2 -2
- package/dist/entity-models-DUKiHpn1.js +406 -0
- package/dist/{export-BZLBF1hS.js → export-DlXOK8_D.js} +4 -3
- package/dist/{generators-BCZVlWig.js → generators-D6giKoab.js} +1 -0
- package/dist/index.js +3 -3
- package/dist/{inherit-C5Ifg3SM.js → inherit-BYLi3Q28.js} +1 -1
- package/dist/{item-styles-DjYRdyHi.js → item-styles-BAeneY1R.js} +1 -1
- package/dist/{model-bytecode-BQKCLPze.js → model-bytecode-B43uSqet.js} +31 -2
- package/dist/output/item-styles.js +1 -1
- package/dist/pack-format-BP5dJMYY.js +10 -0
- package/dist/{pack-format-QcVFxG_b.d.ts → pack-format-D5IgQjcD.d.ts} +49 -1
- package/dist/pack.d.ts +1 -1
- package/dist/{pipeline-CjRcZB63.js → pipeline-CWRQQ9DM.js} +1 -1
- package/dist/render/pipeline.js +1 -1
- package/dist/{run-CGcHj_qq.js → run-CQXJCo8u.js} +2 -2
- package/dist/run.js +1 -1
- package/dist/workers/render-worker.js +1 -1
- package/package.json +1 -1
- package/dist/entity-models-DSZHxCx1.js +0 -127
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"__comment": "A 64x64 head that also draws the skin's own hat layer, for the player head. Same box as head_64_64, but the outer element is bound to the head sheet at the hat unwrap (texOffs 32,0) rather than to an empty sprite. On a default skin that region is fully transparent, so this draws exactly what head_64_64 did; on a real player's skin it is the hat, which is the half of a head that a consumer swapping in a fetched skin would otherwise lose. East/west and up/down are swapped against the game's own box unwrap for the same reason head_64_64 swaps them: the entity renderer draws through a scale(-1, -1, 1) that a block model has no equivalent of.",
|
|
3
|
+
"parent": "mobheads:item/base/head_display",
|
|
4
|
+
"texture_size": [64, 64],
|
|
5
|
+
"elements": [
|
|
6
|
+
{
|
|
7
|
+
"from": [4, 4, 4],
|
|
8
|
+
"to": [12, 12, 12],
|
|
9
|
+
"faces": {
|
|
10
|
+
"north": {"uv": [2, 2, 4, 4], "texture": "#texture"},
|
|
11
|
+
"east": {"uv": [0, 2, 2, 4], "texture": "#texture"},
|
|
12
|
+
"south": {"uv": [6, 2, 8, 4], "texture": "#texture"},
|
|
13
|
+
"west": {"uv": [4, 2, 6, 4], "texture": "#texture"},
|
|
14
|
+
"up": {"uv": [2, 0, 4, 2], "rotation": 180, "texture": "#texture"},
|
|
15
|
+
"down": {"uv": [4, 0, 6, 2], "texture": "#texture"}
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"from": [3.5, 3.5, 3.5],
|
|
20
|
+
"to": [12.5, 12.5, 12.5],
|
|
21
|
+
"faces": {
|
|
22
|
+
"north": {"uv": [10, 2, 12, 4], "texture": "#texture"},
|
|
23
|
+
"east": {"uv": [8, 2, 10, 4], "texture": "#texture"},
|
|
24
|
+
"south": {"uv": [14, 2, 16, 4], "texture": "#texture"},
|
|
25
|
+
"west": {"uv": [12, 2, 14, 4], "texture": "#texture"},
|
|
26
|
+
"up": {"uv": [10, 0, 12, 2], "rotation": 180, "texture": "#texture"},
|
|
27
|
+
"down": {"uv": [12, 0, 14, 2], "texture": "#texture"}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"__comment": "The player head as a block pack wants it: the same head as mobheads:item/player, plus the skin's own hat layer. Kept apart from the item model because the icon renderer samples a hair outside a face's rect at a silhouette edge, and the extra box — transparent on a default skin — still fringes the icon with a few pixels of whatever sits next to the hat unwrap. A block pack is drawn by a GPU from the geometry rather than by that rasterizer, so it takes the hat and the icon does not.",
|
|
3
|
+
"parent": "mobheads:item/base/head_64_64_hat",
|
|
4
|
+
"textures": {
|
|
5
|
+
"texture": "minecraft:entity/player/wide/steve"
|
|
6
|
+
}
|
|
7
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"__comment": "Wall sign: the same board as the standing sign with no post, sitting against the block behind it. Authored facing north, so the blockstate's facing rotates it from there.",
|
|
2
|
+
"__comment": "Wall sign: the same board as the standing sign with no post, sitting against the block behind it. Authored facing north, so the blockstate's facing rotates it from there. The block it hangs on is the one it faces AWAY from, so the board is at the far z: authored north, it sits against the south neighbour. Putting it at z 0 instead drew every wall sign in a world a full block clear of its wall.",
|
|
3
3
|
"texture_size": [64, 32],
|
|
4
4
|
"elements": [
|
|
5
5
|
{
|
|
6
6
|
"name": "board",
|
|
7
|
-
"from": [0, 4.5,
|
|
8
|
-
"to": [16, 12.5,
|
|
7
|
+
"from": [0, 4.5, 14.5],
|
|
8
|
+
"to": [16, 12.5, 16],
|
|
9
9
|
"faces": {
|
|
10
10
|
"north": { "uv": [0.5, 1, 6.5, 7], "texture": "#texture" },
|
|
11
11
|
"east": { "uv": [6.5, 1, 7, 7], "texture": "#texture" },
|
|
@@ -288,7 +288,7 @@ async function skullGeometry(blockId, context) {
|
|
|
288
288
|
} : { kind: "rotation16" }
|
|
289
289
|
};
|
|
290
290
|
};
|
|
291
|
-
const parts = mob.split("_");
|
|
291
|
+
const parts = (mob === "player" ? "player_skin" : mob).split("_");
|
|
292
292
|
for (let keep = parts.length; keep >= 1 && keep >= parts.length - 2; keep--) {
|
|
293
293
|
const model = `mobheads:item/${parts.slice(0, keep).join("_")}`;
|
|
294
294
|
const resolved = await context.models.load(model).catch(() => null);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as blockEntityGeometry, r as synthesizeVariants, t as INVISIBLE_BLOCKS } from "../block-entities-
|
|
1
|
+
import { n as blockEntityGeometry, r as synthesizeVariants, t as INVISIBLE_BLOCKS } from "../block-entities-CPQeb5dV.js";
|
|
2
2
|
export { INVISIBLE_BLOCKS, blockEntityGeometry, synthesizeVariants };
|
package/dist/blocks/cli.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as runBlocksCli } from "../cli-
|
|
1
|
+
import { t as runBlocksCli } from "../cli-DFIB9i9c.js";
|
|
2
2
|
export { runBlocksCli };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as ResourceManager } from "../manager-exOIcdyx.js";
|
|
2
|
-
import { f as BlockPackModel } from "../pack-format-
|
|
2
|
+
import { f as BlockPackModel } from "../pack-format-D5IgQjcD.js";
|
|
3
3
|
//#region src/blocks/ender-storage.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Ender Storage feeds this OBJ through CodeChickenLib's `swapYZ`, translates it almost exactly onto
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { a as ResourceManager } from "../manager-exOIcdyx.js";
|
|
2
2
|
import { i as TextureLoader } from "../loader-DUlx29PC.js";
|
|
3
|
-
import {
|
|
3
|
+
import { S as EntityPackEntry } from "../pack-format-D5IgQjcD.js";
|
|
4
4
|
//#region src/blocks/entities.d.ts
|
|
5
5
|
interface EntityPackResult {
|
|
6
6
|
entities: Record<string, EntityPackEntry>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { a as ResourceManager } from "../manager-exOIcdyx.js";
|
|
2
|
-
import {
|
|
2
|
+
import { C as EntityPackModel, T as EquipmentPack } from "../pack-format-D5IgQjcD.js";
|
|
3
3
|
import { t as ClassSource } from "../jar-classes-CSRrPAUy.js";
|
|
4
|
+
import { t as Mappings } from "../mappings-DxX4KoZl.js";
|
|
5
|
+
import { t as ModelCode } from "../model-code-BY44ao27.js";
|
|
4
6
|
//#region src/blocks/entity-models.d.ts
|
|
5
7
|
interface EntityGeometryResult {
|
|
6
8
|
/** Model id (the class it came from) → geometry. */
|
|
@@ -9,6 +11,8 @@ interface EntityGeometryResult {
|
|
|
9
11
|
modelOf: Map<string, string>;
|
|
10
12
|
/** Entity sheets the models address, to be stitched into the pack's own atlas. */
|
|
11
13
|
spriteIds: Set<string>;
|
|
14
|
+
/** Worn armour, where the version's classes described any. */
|
|
15
|
+
equipment: EquipmentPack | null;
|
|
12
16
|
failures: Array<{
|
|
13
17
|
id: string;
|
|
14
18
|
reason: string;
|
|
@@ -41,5 +45,23 @@ interface CollectEntityGeometryOptions {
|
|
|
41
45
|
* per entity.
|
|
42
46
|
*/
|
|
43
47
|
declare function collectEntityGeometry(options: CollectEntityGeometryOptions): Promise<EntityGeometryResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Reads the authored armour-trim atlas and names every generated worn sheet.
|
|
50
|
+
*
|
|
51
|
+
* The texture loader already resolves `paletted_permutations`; this only records the generated
|
|
52
|
+
* sprite ids so the normal entity-atlas stitcher asks it for those pixels. Copies are visited from
|
|
53
|
+
* lowest to highest precedence, matching atlas source resolution when packs extend the vanilla file.
|
|
54
|
+
*/
|
|
55
|
+
declare function collectArmourTrims(resources: ResourceManager, spriteIds: Set<string>): Promise<EquipmentPack['trims']>;
|
|
56
|
+
/**
|
|
57
|
+
* Worn armour for the pack: one humanoid mesh, the sheets each material is drawn with, and which
|
|
58
|
+
* item is which.
|
|
59
|
+
*
|
|
60
|
+
* Materials are discovered from the sheets the version actually ships rather than listed, so a
|
|
61
|
+
* version that adds one — copper, in the 26 line — needs no edit here. The item ids are the one part
|
|
62
|
+
* the assets cannot answer, since nothing in them maps `iron_helmet` to `iron`: they follow the
|
|
63
|
+
* game's own naming, and each is confirmed against a real item model before being claimed.
|
|
64
|
+
*/
|
|
65
|
+
declare function collectEquipment(names: readonly string[], mappings: Mappings, read: (internal: string) => Promise<Uint8Array | null>, code: ModelCode, resources: ResourceManager | undefined, models: Record<string, EntityPackModel>, spriteIds: Set<string>): Promise<EquipmentPack | null>;
|
|
44
66
|
//#endregion
|
|
45
|
-
export { CollectEntityGeometryOptions, EntityGeometryResult, collectEntityGeometry };
|
|
67
|
+
export { CollectEntityGeometryOptions, EntityGeometryResult, collectArmourTrims, collectEntityGeometry, collectEquipment };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { collectEntityGeometry };
|
|
1
|
+
import { n as collectEntityGeometry, r as collectEquipment, t as collectArmourTrims } from "../entity-models-DUKiHpn1.js";
|
|
2
|
+
export { collectArmourTrims, collectEntityGeometry, collectEquipment };
|
package/dist/blocks/export.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as exportBlockPack } from "../export-
|
|
1
|
+
import { t as exportBlockPack } from "../export-DlXOK8_D.js";
|
|
2
2
|
export { exportBlockPack };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as ResourceManager } from "../manager-exOIcdyx.js";
|
|
2
|
-
import { f as BlockPackModel } from "../pack-format-
|
|
2
|
+
import { f as BlockPackModel } from "../pack-format-D5IgQjcD.js";
|
|
3
3
|
//#region src/blocks/geo-blocks.d.ts
|
|
4
4
|
interface GeoBlockOverride {
|
|
5
5
|
model: BlockPackModel;
|
|
@@ -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 {
|
|
4
|
+
import { D as ItemPackEntry } from "../pack-format-D5IgQjcD.js";
|
|
5
5
|
//#region src/blocks/item-sprites.d.ts
|
|
6
6
|
interface ItemSpriteFailure {
|
|
7
7
|
id: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { C as
|
|
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
|
+
import { C as EntityPackModel, D as ItemPackEntry, E as EquipmentSlot, O as ItemPackLayer, S as EntityPackEntry, T as EquipmentPack, _ as BlockPackTintsFile, a as BlockPackBlockStatesFile, b as EntityPackCube, 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 EntityPackPart, x as EntityPackCubeFace, y as EQUIPMENT_SLOTS } from "../pack-format-D5IgQjcD.js";
|
|
2
|
+
export { BlockPackAtlasFile, BlockPackAtlasPage, BlockPackBiomesFile, BlockPackBlockState, BlockPackBlockStatesFile, BlockPackElement, BlockPackEntitiesFile, BlockPackEntityModelsFile, BlockPackFace, BlockPackItemsFile, BlockPackMetaFile, BlockPackModel, BlockPackModelsFile, BlockPackRenderLayer, BlockPackSprite, BlockPackSpriteFrame, BlockPackTintsFile, BlockPackVariant, EQUIPMENT_SLOTS, EntityPackCube, EntityPackCubeFace, EntityPackEntry, EntityPackModel, EntityPackPart, EquipmentPack, EquipmentSlot, ItemPackEntry, ItemPackLayer };
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { t as EQUIPMENT_SLOTS } from "../pack-format-BP5dJMYY.js";
|
|
2
|
+
export { EQUIPMENT_SLOTS };
|
|
@@ -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 { h as BlockPackSprite, m as BlockPackRenderLayer } from "../pack-format-
|
|
3
|
+
import { h as BlockPackSprite, m as BlockPackRenderLayer } from "../pack-format-D5IgQjcD.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
|
|
@@ -1,6 +1,6 @@
|
|
|
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-
|
|
3
|
+
import { t as exportBlockPack } from "./export-DlXOK8_D.js";
|
|
4
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";
|
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-
|
|
10
|
-
import { t as run } from "./run-
|
|
9
|
+
import { t as runBlocksCli } from "./cli-DFIB9i9c.js";
|
|
10
|
+
import { t as run } from "./run-CQXJCo8u.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 builtinDynamicResources, i as TRIM_MATERIALS, n as POTTERY_SHERDS, r as TRIM_DARKER_MATERIALS, t as ARMOR_ITEM_TYPES } from "../generators-
|
|
1
|
+
import { a as builtinDynamicResources, i as TRIM_MATERIALS, n as POTTERY_SHERDS, r as TRIM_DARKER_MATERIALS, t as ARMOR_ITEM_TYPES } from "../generators-D6giKoab.js";
|
|
2
2
|
export { ARMOR_ITEM_TYPES, POTTERY_SHERDS, TRIM_DARKER_MATERIALS, TRIM_MATERIALS, builtinDynamicResources };
|
package/dist/entities/inherit.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as extractInheritedModel, t as ancestryOf } from "../inherit-
|
|
1
|
+
import { n as extractInheritedModel, t as ancestryOf } from "../inherit-BYLi3Q28.js";
|
|
2
2
|
export { ancestryOf, extractInheritedModel };
|
package/dist/entities/link.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as ClassFile } from "../classfile-BdLIk4Pe.js";
|
|
2
1
|
import { t as Mappings } from "../mappings-DxX4KoZl.js";
|
|
2
|
+
import { t as ClassFile } from "../classfile-BdLIk4Pe.js";
|
|
3
3
|
//#region src/entities/link.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* Entity types whose renderer or model is not named after them. Values are class simple names to look
|
|
@@ -25,7 +25,22 @@ interface Following {
|
|
|
25
25
|
* Defaults to true, which is right when the caller has no way to tell the two apart.
|
|
26
26
|
*/
|
|
27
27
|
isModelCode?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Which of the class's methods may build the model. Defaults to everything but the armour meshes,
|
|
30
|
+
* which build the armour *worn on* this model rather than the model — see `ARMOUR_MESH`.
|
|
31
|
+
*
|
|
32
|
+
* `extractArmourMesh` passes the opposite, since that is exactly what it is after.
|
|
33
|
+
*/
|
|
34
|
+
methods?: (name: string) => boolean;
|
|
28
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* The armour a humanoid wears, as its own mesh. Empty where the class builds none.
|
|
38
|
+
*
|
|
39
|
+
* The baby form is skipped rather than competing: it has more boxes than the adult's — a separate
|
|
40
|
+
* head and body where the adult reuses the humanoid's — so the fullest-mesh rule would always pick
|
|
41
|
+
* it, and every suit of armour in the world would come out child-sized.
|
|
42
|
+
*/
|
|
43
|
+
declare function extractArmourMesh(bytes: Uint8Array, following: Following): ExtractedModel;
|
|
29
44
|
declare function extractModel(bytes: Uint8Array, following?: Following): ExtractedModel;
|
|
30
45
|
//#endregion
|
|
31
|
-
export { Following, extractModel };
|
|
46
|
+
export { Following, extractArmourMesh, extractModel };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { extractModel };
|
|
1
|
+
import { n as extractModel, t as extractArmourMesh } from "../model-bytecode-B43uSqet.js";
|
|
2
|
+
export { extractArmourMesh, extractModel };
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import { n as ResourceLocator } from "./locator-COMEtEn9.js";
|
|
2
|
+
import { t as findGeoForEntity } from "./entity-geo-DbTtMlPL.js";
|
|
3
|
+
import { t as EQUIPMENT_SLOTS } from "./pack-format-BP5dJMYY.js";
|
|
4
|
+
import { n as extractModel, t as extractArmourMesh } from "./model-bytecode-B43uSqet.js";
|
|
5
|
+
import { n as extractInheritedModel, t as ancestryOf } from "./inherit-BYLi3Q28.js";
|
|
6
|
+
import { a as linkEntityModel, i as classReader, r as buildModelNameIndex } from "./link-5GmBLTzk.js";
|
|
7
|
+
import { s as resolveMappings, t as MappingsUnavailableError } from "./mappings-BEPVaiwE.js";
|
|
8
|
+
import { n as loadModelCode } from "./model-code-1Vuk-zj_.js";
|
|
9
|
+
//#region src/blocks/entity-models.ts
|
|
10
|
+
/**
|
|
11
|
+
* Entity geometry for the pack: link each entity to the class that builds it, read that class's
|
|
12
|
+
* bytecode, and stitch the sheets those models are drawn with.
|
|
13
|
+
*
|
|
14
|
+
* The pieces all live in `src/entities/` — this is the part that knows what a *pack* wants. Which is
|
|
15
|
+
* mostly two things the extractor does not care about: several entities share one model (every zombie
|
|
16
|
+
* in the game is a `HumanoidModel`), so models are keyed by class and pointed at rather than copied;
|
|
17
|
+
* and the `uv` values in a model address the entity's own sheet, so those sheets have to be in an
|
|
18
|
+
* atlas the consumer can sample.
|
|
19
|
+
*
|
|
20
|
+
* Needs the *code*, not just the assets. An `--assets` folder has none, and a pack exported from one
|
|
21
|
+
* carries no entity geometry — which is the honest answer rather than a silent gap.
|
|
22
|
+
*/
|
|
23
|
+
function countCubes(part) {
|
|
24
|
+
return part.cubes.length + part.children.reduce((sum, child) => sum + countCubes(child), 0);
|
|
25
|
+
}
|
|
26
|
+
/** Drops the internal shape into the pack's, omitting what is at its default. */
|
|
27
|
+
function toPackPart(part) {
|
|
28
|
+
return {
|
|
29
|
+
name: part.name,
|
|
30
|
+
pivot: [...part.pivot],
|
|
31
|
+
rotation: [...part.rotation],
|
|
32
|
+
cubes: part.cubes.map((cube) => {
|
|
33
|
+
return {
|
|
34
|
+
origin: [...cube.origin],
|
|
35
|
+
size: [...cube.size],
|
|
36
|
+
uv: [...cube.uv],
|
|
37
|
+
...cube.inflate !== 0 && { inflate: cube.inflate },
|
|
38
|
+
...cube.mirror && { mirror: true },
|
|
39
|
+
...cube.faces && { faces: cube.faces }
|
|
40
|
+
};
|
|
41
|
+
}),
|
|
42
|
+
children: part.children.map((child) => toPackPart(child))
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Recovers geometry for as many of `entityIds` as the code describes.
|
|
47
|
+
*
|
|
48
|
+
* Mappings are resolved once: downloaded for an obfuscated jar, and the identity for one that is not
|
|
49
|
+
* (from the 26 line the client ships in the clear, and a mod jar never was obfuscated). A version that
|
|
50
|
+
* is obfuscated *and* unmapped — 1.13.x — yields nothing, with the reason recorded once rather than
|
|
51
|
+
* per entity.
|
|
52
|
+
*/
|
|
53
|
+
async function collectEntityGeometry(options) {
|
|
54
|
+
const { classes, entityIds } = options;
|
|
55
|
+
const models = {};
|
|
56
|
+
const modelOf = /* @__PURE__ */ new Map();
|
|
57
|
+
const spriteIds = /* @__PURE__ */ new Set();
|
|
58
|
+
const failures = [];
|
|
59
|
+
const names = await classes.list();
|
|
60
|
+
let mappings;
|
|
61
|
+
try {
|
|
62
|
+
({mappings} = await resolveMappings(options.version, options.cacheDir, async () => names));
|
|
63
|
+
} catch (err) {
|
|
64
|
+
failures.push({
|
|
65
|
+
id: options.version,
|
|
66
|
+
reason: err instanceof MappingsUnavailableError ? `no entity geometry: ${err.message}` : `no entity geometry: mappings could not be loaded (${err.message})`
|
|
67
|
+
});
|
|
68
|
+
return {
|
|
69
|
+
models,
|
|
70
|
+
modelOf,
|
|
71
|
+
spriteIds,
|
|
72
|
+
equipment: null,
|
|
73
|
+
failures
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
const code = await loadModelCode(names, async (internal) => await classes.read(internal), (internal) => mappings.originalOf.get(internal) ?? internal);
|
|
77
|
+
const extracted = /* @__PURE__ */ new Map();
|
|
78
|
+
const geometryOf = async (internal) => {
|
|
79
|
+
if (!extracted.has(internal)) extracted.set(internal, await extractInheritedModel(internal, async (name) => await classes.read(name), code));
|
|
80
|
+
return extracted.get(internal) ?? null;
|
|
81
|
+
};
|
|
82
|
+
const context = {
|
|
83
|
+
mappings,
|
|
84
|
+
read: classReader(async (internal) => await classes.read(internal)),
|
|
85
|
+
hasGeometry: async (internal) => {
|
|
86
|
+
const model = await geometryOf(internal);
|
|
87
|
+
return model !== null && model.parts.reduce((sum, part) => sum + countCubes(part), 0) > 0;
|
|
88
|
+
},
|
|
89
|
+
nameIndex: buildModelNameIndex(names)
|
|
90
|
+
};
|
|
91
|
+
const geoFor = async (entityId) => {
|
|
92
|
+
if (!options.resources) return null;
|
|
93
|
+
const [namespace, name] = entityId.includes(":") ? entityId.split(":") : ["minecraft", entityId];
|
|
94
|
+
return await findGeoForEntity(options.resources, namespace, name);
|
|
95
|
+
};
|
|
96
|
+
let done = 0;
|
|
97
|
+
for (const entityId of [...entityIds].toSorted((left, right) => left.localeCompare(right))) {
|
|
98
|
+
options.onProgress?.(++done, entityIds.length);
|
|
99
|
+
const link = await linkEntityModel(entityId, context);
|
|
100
|
+
const guessed = link?.route === "vanilla-name";
|
|
101
|
+
const found = link && !guessed ? {
|
|
102
|
+
id: link.className,
|
|
103
|
+
model: await geometryOf(link.obfuscated)
|
|
104
|
+
} : await geoFor(entityId) ?? (link ? {
|
|
105
|
+
id: link.className,
|
|
106
|
+
model: await geometryOf(link.obfuscated)
|
|
107
|
+
} : null);
|
|
108
|
+
if (!found?.model) continue;
|
|
109
|
+
const { id: modelId, model } = found;
|
|
110
|
+
if (!models[modelId]) models[modelId] = {
|
|
111
|
+
textureSize: [...model.textureSize],
|
|
112
|
+
parts: model.parts.map((part) => toPackPart(part)),
|
|
113
|
+
...model.notes.length > 0 && { notes: [...model.notes] }
|
|
114
|
+
};
|
|
115
|
+
modelOf.set(entityId, modelId);
|
|
116
|
+
const texture = options.textureOf.get(entityId);
|
|
117
|
+
if (texture) spriteIds.add(texture);
|
|
118
|
+
else failures.push({
|
|
119
|
+
id: entityId,
|
|
120
|
+
reason: `geometry recovered from ${modelId} but no entity texture resolved`
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
models,
|
|
125
|
+
modelOf,
|
|
126
|
+
spriteIds,
|
|
127
|
+
equipment: await collectEquipment(names, mappings, async (internal) => await classes.read(internal), code, options.resources, models, spriteIds),
|
|
128
|
+
failures
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* How much each armour layer grows the wearer's boxes by, in pixels.
|
|
133
|
+
*
|
|
134
|
+
* Not recovered from the code: the game passes these into the mesh builder from its renderers, so
|
|
135
|
+
* following them means interpreting a renderer, which the extractor deliberately refuses to do. They
|
|
136
|
+
* have been 1.0 and 0.5 since armour got its second layer, and getting them wrong only makes the two
|
|
137
|
+
* layers fight rather than losing the shape.
|
|
138
|
+
*/
|
|
139
|
+
const ARMOUR_INFLATE = {
|
|
140
|
+
outer: 1,
|
|
141
|
+
inner: .5
|
|
142
|
+
};
|
|
143
|
+
/** Which parts a slot lights up, and which layer it is drawn on. */
|
|
144
|
+
const ARMOUR_SLOTS = {
|
|
145
|
+
head: {
|
|
146
|
+
parts: ["head", "hat"],
|
|
147
|
+
layer: "outer"
|
|
148
|
+
},
|
|
149
|
+
chest: {
|
|
150
|
+
parts: [
|
|
151
|
+
"body",
|
|
152
|
+
"right_arm",
|
|
153
|
+
"left_arm"
|
|
154
|
+
],
|
|
155
|
+
layer: "outer"
|
|
156
|
+
},
|
|
157
|
+
legs: {
|
|
158
|
+
parts: [
|
|
159
|
+
"body",
|
|
160
|
+
"right_leg",
|
|
161
|
+
"left_leg"
|
|
162
|
+
],
|
|
163
|
+
layer: "inner"
|
|
164
|
+
},
|
|
165
|
+
feet: {
|
|
166
|
+
parts: ["right_leg", "left_leg"],
|
|
167
|
+
layer: "outer"
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* Where each layer's sheets live, across the two layouts the game has used.
|
|
172
|
+
*
|
|
173
|
+
* 1.21.2 moved armour under `entity/equipment/` and dropped the `_layer_N` suffix for a folder per
|
|
174
|
+
* layer. Both are matched rather than switched on a version, so a resource pack or a mod following
|
|
175
|
+
* either convention is found the same way.
|
|
176
|
+
*/
|
|
177
|
+
const ARMOUR_SHEETS = [
|
|
178
|
+
{
|
|
179
|
+
layer: "outer",
|
|
180
|
+
prefix: "entity/equipment/humanoid/",
|
|
181
|
+
suffix: ""
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
layer: "inner",
|
|
185
|
+
prefix: "entity/equipment/humanoid_leggings/",
|
|
186
|
+
suffix: ""
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
layer: "outer",
|
|
190
|
+
prefix: "models/armor/",
|
|
191
|
+
suffix: "_layer_1"
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
layer: "inner",
|
|
195
|
+
prefix: "models/armor/",
|
|
196
|
+
suffix: "_layer_2"
|
|
197
|
+
}
|
|
198
|
+
];
|
|
199
|
+
/** The item name a material takes, where it is not simply the material's own. */
|
|
200
|
+
const ARMOUR_ITEM_PREFIX = {
|
|
201
|
+
gold: "golden",
|
|
202
|
+
turtle_scute: "turtle"
|
|
203
|
+
};
|
|
204
|
+
/** Suffix per slot, as every vanilla armour item is named. */
|
|
205
|
+
const ARMOUR_ITEM_PIECE = {
|
|
206
|
+
head: "helmet",
|
|
207
|
+
chest: "chestplate",
|
|
208
|
+
legs: "leggings",
|
|
209
|
+
feet: "boots"
|
|
210
|
+
};
|
|
211
|
+
/** The layer and world pattern id named by one of the paths in the armour-trim atlas. */
|
|
212
|
+
function trimSheet(locator) {
|
|
213
|
+
const name = locator.path.split("/").at(-1)?.replace(/\.png$/, "");
|
|
214
|
+
if (!name) return null;
|
|
215
|
+
if (locator.path.includes("/humanoid_leggings/")) return {
|
|
216
|
+
layer: "inner",
|
|
217
|
+
pattern: new ResourceLocator(locator.namespace, name).toString()
|
|
218
|
+
};
|
|
219
|
+
if (locator.path.includes("/humanoid/")) return {
|
|
220
|
+
layer: "outer",
|
|
221
|
+
pattern: new ResourceLocator(locator.namespace, name).toString()
|
|
222
|
+
};
|
|
223
|
+
if (locator.path.includes("trims/models/armor/")) {
|
|
224
|
+
const leggings = name.endsWith("_leggings");
|
|
225
|
+
const pattern = leggings ? name.slice(0, -9) : name;
|
|
226
|
+
return {
|
|
227
|
+
layer: leggings ? "inner" : "outer",
|
|
228
|
+
pattern: new ResourceLocator(locator.namespace, pattern).toString()
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
return null;
|
|
232
|
+
}
|
|
233
|
+
/** The registry id represented by a palette or pattern texture. */
|
|
234
|
+
function trimId(locator) {
|
|
235
|
+
const name = locator.path.split("/").at(-1)?.replace(/\.png$/, "");
|
|
236
|
+
return name ? new ResourceLocator(locator.namespace, name).toString() : null;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Reads the authored armour-trim atlas and names every generated worn sheet.
|
|
240
|
+
*
|
|
241
|
+
* The texture loader already resolves `paletted_permutations`; this only records the generated
|
|
242
|
+
* sprite ids so the normal entity-atlas stitcher asks it for those pixels. Copies are visited from
|
|
243
|
+
* lowest to highest precedence, matching atlas source resolution when packs extend the vanilla file.
|
|
244
|
+
*/
|
|
245
|
+
async function collectArmourTrims(resources, spriteIds) {
|
|
246
|
+
const patterns = {};
|
|
247
|
+
const darker = {};
|
|
248
|
+
for (const namespace of await resources.listNamespaces()) {
|
|
249
|
+
const atlas = new ResourceLocator(namespace, "armor_trims");
|
|
250
|
+
const copies = await resources.getAllResources("atlas", atlas);
|
|
251
|
+
for (const raw of copies.toReversed()) {
|
|
252
|
+
let sources;
|
|
253
|
+
try {
|
|
254
|
+
sources = JSON.parse(raw.toString("utf8")).sources ?? [];
|
|
255
|
+
} catch {
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
for (const source of sources) {
|
|
259
|
+
if (String(source.type ?? "").replace(/^minecraft:/, "") !== "paletted_permutations" || !Array.isArray(source.textures) || !source.permutations) continue;
|
|
260
|
+
const separator = source.separator ?? "_";
|
|
261
|
+
for (const texture of source.textures) {
|
|
262
|
+
const base = ResourceLocator.tryParse(texture.replace(/\.png$/, ""));
|
|
263
|
+
if (!base) continue;
|
|
264
|
+
const sheet = trimSheet(base);
|
|
265
|
+
if (!sheet) continue;
|
|
266
|
+
const { layer, pattern } = sheet;
|
|
267
|
+
for (const [permutation, paletteName] of Object.entries(source.permutations)) {
|
|
268
|
+
const palette = ResourceLocator.tryParse(paletteName.replace(/\.png$/, ""));
|
|
269
|
+
const material = palette && trimId(palette);
|
|
270
|
+
if (!material) continue;
|
|
271
|
+
const sprite = new ResourceLocator(base.namespace, `${base.path}${separator}${permutation}`).toString();
|
|
272
|
+
patterns[pattern] ??= {};
|
|
273
|
+
patterns[pattern][material] = {
|
|
274
|
+
...patterns[pattern][material],
|
|
275
|
+
[layer]: sprite
|
|
276
|
+
};
|
|
277
|
+
spriteIds.add(sprite);
|
|
278
|
+
if (material.endsWith("_darker")) {
|
|
279
|
+
const plain = material.slice(0, -7);
|
|
280
|
+
darker[plain] = material;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
patterns,
|
|
289
|
+
darker
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* The class holding the humanoid armour shape, across the three places the game has kept it.
|
|
294
|
+
*
|
|
295
|
+
* A dedicated `HumanoidArmorModel` is armour throughout, so the whole class is read. From the 26 line
|
|
296
|
+
* it folded into `HumanoidModel` as a set of `create*ArmorMesh` factories beside the humanoid's own,
|
|
297
|
+
* which is what `extractArmourMesh` picks out. Failing both, the humanoid itself is the right shape —
|
|
298
|
+
* armour has never been anything but the wearer, grown.
|
|
299
|
+
*/
|
|
300
|
+
async function armourGeometry(names, mappings, read, code) {
|
|
301
|
+
const find = (simple) => names.find((name) => (mappings.originalOf.get(name) ?? name).endsWith(`/${simple}`) || (mappings.originalOf.get(name) ?? name).endsWith(`.${simple}`));
|
|
302
|
+
for (const route of [
|
|
303
|
+
{
|
|
304
|
+
simple: "HumanoidArmorModel",
|
|
305
|
+
armourOnly: false
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
simple: "HumanoidModel",
|
|
309
|
+
armourOnly: true
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
simple: "HumanoidModel",
|
|
313
|
+
armourOnly: false
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
simple: "BipedModel",
|
|
317
|
+
armourOnly: false
|
|
318
|
+
}
|
|
319
|
+
]) {
|
|
320
|
+
const internal = find(route.simple);
|
|
321
|
+
const bytes = internal ? await read(internal) : null;
|
|
322
|
+
if (!internal || !bytes) continue;
|
|
323
|
+
const { ancestors } = await ancestryOf(internal, read);
|
|
324
|
+
const resolve = (name) => ancestors.get(name) ?? code.resolve(name);
|
|
325
|
+
const model = route.armourOnly ? extractArmourMesh(bytes, {
|
|
326
|
+
resolve,
|
|
327
|
+
isModelCode: true
|
|
328
|
+
}) : extractModel(bytes, {
|
|
329
|
+
resolve,
|
|
330
|
+
isModelCode: true
|
|
331
|
+
});
|
|
332
|
+
if (model.parts.reduce((sum, part) => sum + countCubes(part), 0) > 0) return {
|
|
333
|
+
className: mappings.originalOf.get(internal) ?? internal,
|
|
334
|
+
model
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Worn armour for the pack: one humanoid mesh, the sheets each material is drawn with, and which
|
|
341
|
+
* item is which.
|
|
342
|
+
*
|
|
343
|
+
* Materials are discovered from the sheets the version actually ships rather than listed, so a
|
|
344
|
+
* version that adds one — copper, in the 26 line — needs no edit here. The item ids are the one part
|
|
345
|
+
* the assets cannot answer, since nothing in them maps `iron_helmet` to `iron`: they follow the
|
|
346
|
+
* game's own naming, and each is confirmed against a real item model before being claimed.
|
|
347
|
+
*/
|
|
348
|
+
async function collectEquipment(names, mappings, read, code, resources, models, spriteIds) {
|
|
349
|
+
if (!resources) return null;
|
|
350
|
+
const found = await armourGeometry(names, mappings, read, code);
|
|
351
|
+
if (!found) return null;
|
|
352
|
+
const materials = {};
|
|
353
|
+
const dyeable = [];
|
|
354
|
+
const textures = await resources.listResources("texture", "minecraft");
|
|
355
|
+
for (const { layer, prefix, suffix } of ARMOUR_SHEETS) for (const locator of textures) {
|
|
356
|
+
if (!locator.path.startsWith(prefix)) continue;
|
|
357
|
+
const name = locator.path.slice(prefix.length);
|
|
358
|
+
const overlay = name.endsWith("_overlay");
|
|
359
|
+
const bare = overlay ? name.slice(0, -8) : name;
|
|
360
|
+
if (!bare.endsWith(suffix)) continue;
|
|
361
|
+
const material = bare.slice(0, bare.length - suffix.length);
|
|
362
|
+
if (material.length === 0 || material.includes("/")) continue;
|
|
363
|
+
const id = `minecraft:${material}`;
|
|
364
|
+
if (overlay) {
|
|
365
|
+
if (!dyeable.includes(id)) dyeable.push(id);
|
|
366
|
+
continue;
|
|
367
|
+
}
|
|
368
|
+
materials[id] = {
|
|
369
|
+
...materials[id],
|
|
370
|
+
[layer]: locator.toString()
|
|
371
|
+
};
|
|
372
|
+
spriteIds.add(locator.toString());
|
|
373
|
+
}
|
|
374
|
+
if (Object.keys(materials).length === 0) return null;
|
|
375
|
+
const items = {};
|
|
376
|
+
for (const material of Object.keys(materials)) {
|
|
377
|
+
const bare = material.slice(10);
|
|
378
|
+
const prefix = ARMOUR_ITEM_PREFIX[bare] ?? bare;
|
|
379
|
+
for (const slot of EQUIPMENT_SLOTS) {
|
|
380
|
+
const id = `minecraft:${prefix}_${ARMOUR_ITEM_PIECE[slot]}`;
|
|
381
|
+
if (await resources.hasResource("model", new ResourceLocator("minecraft", `item/${prefix}_${ARMOUR_ITEM_PIECE[slot]}`))) items[id] = {
|
|
382
|
+
material,
|
|
383
|
+
slot
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
const trims = await collectArmourTrims(resources, spriteIds);
|
|
388
|
+
const modelKey = `${found.className}#armor`;
|
|
389
|
+
models[modelKey] = {
|
|
390
|
+
textureSize: [...found.model.textureSize],
|
|
391
|
+
parts: found.model.parts.map((part) => toPackPart(part)),
|
|
392
|
+
...found.model.notes.length > 0 && { notes: [...found.model.notes] }
|
|
393
|
+
};
|
|
394
|
+
return {
|
|
395
|
+
model: modelKey,
|
|
396
|
+
inflate: { ...ARMOUR_INFLATE },
|
|
397
|
+
slots: Object.fromEntries(EQUIPMENT_SLOTS.map((slot) => [slot, [...ARMOUR_SLOTS[slot].parts]])),
|
|
398
|
+
layerOf: Object.fromEntries(EQUIPMENT_SLOTS.map((slot) => [slot, ARMOUR_SLOTS[slot].layer])),
|
|
399
|
+
materials,
|
|
400
|
+
items,
|
|
401
|
+
dyeable,
|
|
402
|
+
trims
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
//#endregion
|
|
406
|
+
export { collectEntityGeometry as n, collectEquipment as r, collectArmourTrims as t };
|
|
@@ -1,11 +1,11 @@
|
|
|
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-
|
|
3
|
+
import { n as blockEntityGeometry, r as synthesizeVariants, t as INVISIBLE_BLOCKS } from "./block-entities-CPQeb5dV.js";
|
|
4
4
|
import { a as parseBlockState, n as collectModels } from "./blockstate-eval-CV_LwUwj.js";
|
|
5
5
|
import { a as salvageJson, i as resolveTexture, t as ModelLoader } from "./loader-C-NuJaEi.js";
|
|
6
6
|
import { t as enderStorageBlockModel } from "./ender-storage-C8i6Rxlq.js";
|
|
7
7
|
import { t as collectEntities } from "./entities-DubtdM11.js";
|
|
8
|
-
import {
|
|
8
|
+
import { n as collectEntityGeometry } from "./entity-models-DUKiHpn1.js";
|
|
9
9
|
import { t as geoBlockModel } from "./geo-blocks-BcSEBhko.js";
|
|
10
10
|
import { n as discoverItems } from "./discovery-CD0QqxSF.js";
|
|
11
11
|
import { t as collectItemSprites } from "./item-sprites-CnCH8YFv.js";
|
|
@@ -822,7 +822,8 @@ async function exportBlockPack(options) {
|
|
|
822
822
|
};
|
|
823
823
|
}),
|
|
824
824
|
sprites: sortedByKey(sheet.sprites),
|
|
825
|
-
models: sortedByKey(geometry.models)
|
|
825
|
+
models: sortedByKey(geometry.models),
|
|
826
|
+
...geometry.equipment && { equipment: geometry.equipment }
|
|
826
827
|
};
|
|
827
828
|
for (const [id, entry] of Object.entries(collected.entities)) if (entry.texture && sheet.missing.has(entry.texture)) delete collected.entities[id].texture;
|
|
828
829
|
}
|
package/dist/index.js
CHANGED
|
@@ -14,13 +14,13 @@ 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-
|
|
17
|
+
import { t as exportBlockPack } from "./export-DlXOK8_D.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";
|
|
21
21
|
import { n as encodeIcon, t as encodeAnimatedIcon } from "./encode-LR9wxigC.js";
|
|
22
|
-
import { a as builtinDynamicResources } from "./generators-
|
|
22
|
+
import { a as builtinDynamicResources } from "./generators-D6giKoab.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-
|
|
25
|
+
import { t as run } from "./run-CQXJCo8u.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
1
|
import { t as parseClassFile } from "./classfile-Bo7FUrrD.js";
|
|
2
2
|
import { a as mergeModels, i as dedupeCubes } from "./merge-DeHruviG.js";
|
|
3
|
-
import {
|
|
3
|
+
import { n as extractModel } from "./model-bytecode-B43uSqet.js";
|
|
4
4
|
//#region src/entities/inherit.ts
|
|
5
5
|
/**
|
|
6
6
|
* A model class read together with its ancestors.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as TRIM_MATERIALS, n as POTTERY_SHERDS, r as TRIM_DARKER_MATERIALS, t as ARMOR_ITEM_TYPES } from "./generators-
|
|
1
|
+
import { i as TRIM_MATERIALS, n as POTTERY_SHERDS, r as TRIM_DARKER_MATERIALS, t as ARMOR_ITEM_TYPES } from "./generators-D6giKoab.js";
|
|
2
2
|
//#region src/output/item-styles.ts
|
|
3
3
|
/**
|
|
4
4
|
* Per-item CSS style classification, ported from upstream's ItemStyleGenerators
|
|
@@ -790,17 +790,46 @@ function toPart(handle) {
|
|
|
790
790
|
children: handle.children.map((child) => toPart(child))
|
|
791
791
|
};
|
|
792
792
|
}
|
|
793
|
+
/**
|
|
794
|
+
* A method that builds the *armour worn on* a model rather than the model itself.
|
|
795
|
+
*
|
|
796
|
+
* The 26 line moved the armour meshes onto the models that wear them, so `HumanoidModel` now offers
|
|
797
|
+
* `createBaseArmorMesh` and `createBabyArmorMesh` beside its own `createMesh`. A baby's armour has
|
|
798
|
+
* more boxes than the humanoid does, so the fullest-mesh rule below picked it, and every player,
|
|
799
|
+
* zombie and armour stand in the pack came out as a set of leggings: a `waist` and an `inner_body`
|
|
800
|
+
* at knee height where the mob should have been.
|
|
801
|
+
*
|
|
802
|
+
* Matched by name, which is exact on a jar Mojang no longer obfuscates and harmless on one they did,
|
|
803
|
+
* where no method is named anything at all.
|
|
804
|
+
*/
|
|
805
|
+
const ARMOUR_MESH = /armou?r/i;
|
|
806
|
+
/** The baby form of an armour mesh, which is a scaled duplicate of the one worn by an adult. */
|
|
807
|
+
const BABY_MESH = /baby/i;
|
|
808
|
+
/**
|
|
809
|
+
* The armour a humanoid wears, as its own mesh. Empty where the class builds none.
|
|
810
|
+
*
|
|
811
|
+
* The baby form is skipped rather than competing: it has more boxes than the adult's — a separate
|
|
812
|
+
* head and body where the adult reuses the humanoid's — so the fullest-mesh rule would always pick
|
|
813
|
+
* it, and every suit of armour in the world would come out child-sized.
|
|
814
|
+
*/
|
|
815
|
+
function extractArmourMesh(bytes, following) {
|
|
816
|
+
return extractModel(bytes, {
|
|
817
|
+
...following,
|
|
818
|
+
methods: (name) => ARMOUR_MESH.test(name) && !BABY_MESH.test(name)
|
|
819
|
+
});
|
|
820
|
+
}
|
|
793
821
|
function extractModel(bytes, following) {
|
|
794
822
|
const classFile = parseClassFile(bytes);
|
|
795
823
|
const notes = [];
|
|
796
824
|
const candidates = [];
|
|
797
825
|
const outward = following?.isModelCode ?? true;
|
|
826
|
+
const wanted = following?.methods ?? ((name) => !ARMOUR_MESH.test(name));
|
|
798
827
|
const own = (internalName) => {
|
|
799
828
|
if (internalName === classFile.thisClass) return classFile;
|
|
800
829
|
return outward ? following?.resolve(internalName) ?? null : null;
|
|
801
830
|
};
|
|
802
831
|
for (const method of classFile.methods) {
|
|
803
|
-
if (!method.code) continue;
|
|
832
|
+
if (!method.code || !wanted(method.name)) continue;
|
|
804
833
|
const shared = newShared(own);
|
|
805
834
|
let ok;
|
|
806
835
|
try {
|
|
@@ -841,4 +870,4 @@ function extractModel(bytes, following) {
|
|
|
841
870
|
return model;
|
|
842
871
|
}
|
|
843
872
|
//#endregion
|
|
844
|
-
export { extractModel as t };
|
|
873
|
+
export { extractModel as n, extractArmourMesh as t };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as classifyItemStyle } from "../item-styles-
|
|
1
|
+
import { t as classifyItemStyle } from "../item-styles-BAeneY1R.js";
|
|
2
2
|
export { classifyItemStyle };
|
|
@@ -252,6 +252,54 @@ interface BlockPackEntityModelsFile {
|
|
|
252
252
|
pages: BlockPackAtlasPage[];
|
|
253
253
|
sprites: Record<string, BlockPackSprite>;
|
|
254
254
|
models: Record<string, EntityPackModel>;
|
|
255
|
+
/** Worn armour, when the version's classes described any. Absent otherwise. */
|
|
256
|
+
equipment?: EquipmentPack;
|
|
257
|
+
}
|
|
258
|
+
/** The armour slots the game dresses a humanoid in, in the order it layers them. */
|
|
259
|
+
declare const EQUIPMENT_SLOTS: readonly ["feet", "legs", "chest", "head"];
|
|
260
|
+
type EquipmentSlot = typeof EQUIPMENT_SLOTS[number];
|
|
261
|
+
/**
|
|
262
|
+
* Worn armour: one humanoid-shaped mesh, the two sizes it is drawn at, and a sheet per material.
|
|
263
|
+
*
|
|
264
|
+
* Armour is not geometry of its own — it is the wearer's own humanoid shape grown by a fixed amount,
|
|
265
|
+
* which is why one mesh dresses a player, a zombie and an armour stand alike. The leggings are the
|
|
266
|
+
* *inner* layer and everything else the *outer*, drawn a little larger so the two never fight.
|
|
267
|
+
*
|
|
268
|
+
* Everything a consumer needs to decide what to draw is stated here rather than derived, in keeping
|
|
269
|
+
* with the rest of the pack: which parts a slot lights up, which sheet a material uses, and which
|
|
270
|
+
* material an item is made of.
|
|
271
|
+
*/
|
|
272
|
+
interface EquipmentPack {
|
|
273
|
+
/** Key into `models`, holding the humanoid armour shape. */
|
|
274
|
+
model: string;
|
|
275
|
+
/** How much each layer grows the wearer's boxes by, in pixels. */
|
|
276
|
+
inflate: {
|
|
277
|
+
inner: number;
|
|
278
|
+
outer: number;
|
|
279
|
+
};
|
|
280
|
+
/** Parts each slot shows. A slot lights up some of the one mesh rather than owning geometry. */
|
|
281
|
+
slots: Record<EquipmentSlot, string[]>;
|
|
282
|
+
/** Which layer a slot is drawn on, which decides the sheet as well as the size. */
|
|
283
|
+
layerOf: Record<EquipmentSlot, 'inner' | 'outer'>;
|
|
284
|
+
/** Sprite ids per material and layer, into this file's own `sprites`. */
|
|
285
|
+
materials: Record<string, Partial<Record<'inner' | 'outer', string>>>;
|
|
286
|
+
/**
|
|
287
|
+
* The armour items themselves. Keyed by item id because that is what a world writes into an
|
|
288
|
+
* entity's `equipment` compound, and nothing in the assets maps one to the other.
|
|
289
|
+
*/
|
|
290
|
+
items: Record<string, {
|
|
291
|
+
material: string;
|
|
292
|
+
slot: EquipmentSlot;
|
|
293
|
+
}>;
|
|
294
|
+
/** Materials whose sheet is greyscale and takes the item's own dye colour. */
|
|
295
|
+
dyeable: string[];
|
|
296
|
+
/** Worn armour-trim sheets generated from the version's armour-trim atlas. */
|
|
297
|
+
trims: {
|
|
298
|
+
/** Sprite ids per pattern and material, into this file's own `sprites`. */
|
|
299
|
+
patterns: Record<string, Record<string, Partial<Record<'inner' | 'outer', string>>>>;
|
|
300
|
+
/** Material a trim falls back to when it matches the armour it is on. */
|
|
301
|
+
darker: Record<string, string>;
|
|
302
|
+
};
|
|
255
303
|
}
|
|
256
304
|
/** `meta.json`, written last because it hashes every other file. */
|
|
257
305
|
interface BlockPackMetaFile {
|
|
@@ -277,4 +325,4 @@ interface BlockPackMetaFile {
|
|
|
277
325
|
hashes: Record<string, string>;
|
|
278
326
|
}
|
|
279
327
|
//#endregion
|
|
280
|
-
export {
|
|
328
|
+
export { EntityPackModel as C, ItemPackEntry as D, EquipmentSlot as E, ItemPackLayer as O, EntityPackEntry as S, EquipmentPack as T, BlockPackTintsFile as _, BlockPackBlockStatesFile as a, EntityPackCube as b, BlockPackEntityModelsFile as c, BlockPackMetaFile as d, BlockPackModel as f, BlockPackSpriteFrame as g, BlockPackSprite as h, BlockPackBlockState as i, BlockPackFace as l, BlockPackRenderLayer as m, BlockPackAtlasPage as n, BlockPackElement as o, BlockPackModelsFile as p, BlockPackBiomesFile as r, BlockPackEntitiesFile as s, BlockPackAtlasFile as t, BlockPackItemsFile as u, BlockPackVariant as v, EntityPackPart as w, EntityPackCubeFace as x, EQUIPMENT_SLOTS as y };
|
package/dist/pack.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ import { n as BiomeClimatePack, t as BiomeClimate } from "./biomes-CJDJQqJb.js";
|
|
|
2
2
|
import { a as BlockStateMultipartCase, d as matchesCondition, 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";
|
|
3
3
|
import { n as ObjMesh, t as MeshGroup } from "./obj-mesh-ydhVfLKs.js";
|
|
4
4
|
import { n as BlockTintPack, t as BlockTint } from "./tints-DoBv5S9v.js";
|
|
5
|
-
import { _ as BlockPackTintsFile, a as BlockPackBlockStatesFile, 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, t as BlockPackAtlasFile, v as BlockPackVariant } from "./pack-format-
|
|
5
|
+
import { _ as BlockPackTintsFile, a as BlockPackBlockStatesFile, 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, t as BlockPackAtlasFile, v as BlockPackVariant } from "./pack-format-D5IgQjcD.js";
|
|
6
6
|
export { type BiomeClimate, type BiomeClimatePack, type BlockModelVariant, type BlockPackAtlasFile, type BlockPackAtlasPage, type BlockPackBiomesFile, type BlockPackBlockState, type BlockPackBlockStatesFile, type BlockPackElement, type BlockPackFace, type BlockPackMetaFile, type BlockPackModel, type BlockPackModelsFile, type BlockPackRenderLayer, type BlockPackSprite, type BlockPackSpriteFrame, type BlockPackTintsFile, type BlockPackVariant, type BlockProperties, type BlockStateDefinition, type BlockStateMultipartCase, type BlockStateVariantCase, type BlockTint, type BlockTintPack, type MeshGroup, type MultipartCondition, type ObjMesh, evaluateBlockState, matchesCondition, weightedVariantIndex };
|
|
@@ -10,7 +10,7 @@ import { t as loadAtlasResolver } from "./registry-DlduyjtM.js";
|
|
|
10
10
|
import { n as LayeredResourceManager, t as FolderResourceManager } from "./manager-BNibYkmI.js";
|
|
11
11
|
import { n as TextureLoader } from "./loader-C18GpurU.js";
|
|
12
12
|
import { t as encodeAnimatedIcon } from "./encode-LR9wxigC.js";
|
|
13
|
-
import { a as builtinDynamicResources } from "./generators-
|
|
13
|
+
import { a as builtinDynamicResources } from "./generators-D6giKoab.js";
|
|
14
14
|
import { a as spawnEggTints, i as renderEntityFallback, n as dyedVariantTint, r as renderDyedVariantFallback, t as dyeVariantName } from "./entity-fallback-BRMFKPlM.js";
|
|
15
15
|
import { t as legacyTintsForChain } from "./legacy-tints-l-541wgI.js";
|
|
16
16
|
import { n as defaultBlockStateModel, t as blockStateTransform } from "./blockstate-DVb8Mhxc.js";
|
package/dist/render/pipeline.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as ItemPipeline } from "../pipeline-
|
|
1
|
+
import { t as ItemPipeline } from "../pipeline-CWRQQ9DM.js";
|
|
2
2
|
export { ItemPipeline };
|
|
@@ -3,10 +3,10 @@ import { n as discoverItems } from "./discovery-CD0QqxSF.js";
|
|
|
3
3
|
import { n as LayeredResourceManager } from "./manager-BNibYkmI.js";
|
|
4
4
|
import { t as curatedModelOverrides } from "./models-CZjCOjs4.js";
|
|
5
5
|
import { r as encodeRasterAsset } from "./encode-LR9wxigC.js";
|
|
6
|
-
import { t as classifyItemStyle } from "./item-styles-
|
|
6
|
+
import { t as classifyItemStyle } from "./item-styles-BAeneY1R.js";
|
|
7
7
|
import { t as minifyStylesheet } from "./minify-bjMRmr5J.js";
|
|
8
8
|
import { t as generateStylesheet } from "./stylesheet-CovT3B2S.js";
|
|
9
|
-
import { t as ItemPipeline } from "./pipeline-
|
|
9
|
+
import { t as ItemPipeline } from "./pipeline-CWRQQ9DM.js";
|
|
10
10
|
import { t as describeResources } from "./descriptor-JyXhfd-c.js";
|
|
11
11
|
import { t as WorkerRenderPool } from "./pool-CKGp1qup.js";
|
|
12
12
|
import path from "node:path";
|
package/dist/run.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ItemPipeline } from "../pipeline-
|
|
1
|
+
import { t as ItemPipeline } from "../pipeline-CWRQQ9DM.js";
|
|
2
2
|
import { n as restoreResources } from "../descriptor-JyXhfd-c.js";
|
|
3
3
|
import sharp from "sharp";
|
|
4
4
|
import { parentPort, workerData } from "node:worker_threads";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodecraft/rendermite",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
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,127 +0,0 @@
|
|
|
1
|
-
import { t as findGeoForEntity } from "./entity-geo-DbTtMlPL.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
|
-
import { s as resolveMappings, t as MappingsUnavailableError } from "./mappings-BEPVaiwE.js";
|
|
5
|
-
import { n as loadModelCode } from "./model-code-1Vuk-zj_.js";
|
|
6
|
-
//#region src/blocks/entity-models.ts
|
|
7
|
-
/**
|
|
8
|
-
* Entity geometry for the pack: link each entity to the class that builds it, read that class's
|
|
9
|
-
* bytecode, and stitch the sheets those models are drawn with.
|
|
10
|
-
*
|
|
11
|
-
* The pieces all live in `src/entities/` — this is the part that knows what a *pack* wants. Which is
|
|
12
|
-
* mostly two things the extractor does not care about: several entities share one model (every zombie
|
|
13
|
-
* in the game is a `HumanoidModel`), so models are keyed by class and pointed at rather than copied;
|
|
14
|
-
* and the `uv` values in a model address the entity's own sheet, so those sheets have to be in an
|
|
15
|
-
* atlas the consumer can sample.
|
|
16
|
-
*
|
|
17
|
-
* Needs the *code*, not just the assets. An `--assets` folder has none, and a pack exported from one
|
|
18
|
-
* carries no entity geometry — which is the honest answer rather than a silent gap.
|
|
19
|
-
*/
|
|
20
|
-
function countCubes(part) {
|
|
21
|
-
return part.cubes.length + part.children.reduce((sum, child) => sum + countCubes(child), 0);
|
|
22
|
-
}
|
|
23
|
-
/** Drops the internal shape into the pack's, omitting what is at its default. */
|
|
24
|
-
function toPackPart(part) {
|
|
25
|
-
return {
|
|
26
|
-
name: part.name,
|
|
27
|
-
pivot: [...part.pivot],
|
|
28
|
-
rotation: [...part.rotation],
|
|
29
|
-
cubes: part.cubes.map((cube) => {
|
|
30
|
-
return {
|
|
31
|
-
origin: [...cube.origin],
|
|
32
|
-
size: [...cube.size],
|
|
33
|
-
uv: [...cube.uv],
|
|
34
|
-
...cube.inflate !== 0 && { inflate: cube.inflate },
|
|
35
|
-
...cube.mirror && { mirror: true },
|
|
36
|
-
...cube.faces && { faces: cube.faces }
|
|
37
|
-
};
|
|
38
|
-
}),
|
|
39
|
-
children: part.children.map((child) => toPackPart(child))
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
/**
|
|
43
|
-
* Recovers geometry for as many of `entityIds` as the code describes.
|
|
44
|
-
*
|
|
45
|
-
* Mappings are resolved once: downloaded for an obfuscated jar, and the identity for one that is not
|
|
46
|
-
* (from the 26 line the client ships in the clear, and a mod jar never was obfuscated). A version that
|
|
47
|
-
* is obfuscated *and* unmapped — 1.13.x — yields nothing, with the reason recorded once rather than
|
|
48
|
-
* per entity.
|
|
49
|
-
*/
|
|
50
|
-
async function collectEntityGeometry(options) {
|
|
51
|
-
const { classes, entityIds } = options;
|
|
52
|
-
const models = {};
|
|
53
|
-
const modelOf = /* @__PURE__ */ new Map();
|
|
54
|
-
const spriteIds = /* @__PURE__ */ new Set();
|
|
55
|
-
const failures = [];
|
|
56
|
-
const names = await classes.list();
|
|
57
|
-
let mappings;
|
|
58
|
-
try {
|
|
59
|
-
({mappings} = await resolveMappings(options.version, options.cacheDir, async () => names));
|
|
60
|
-
} catch (err) {
|
|
61
|
-
failures.push({
|
|
62
|
-
id: options.version,
|
|
63
|
-
reason: err instanceof MappingsUnavailableError ? `no entity geometry: ${err.message}` : `no entity geometry: mappings could not be loaded (${err.message})`
|
|
64
|
-
});
|
|
65
|
-
return {
|
|
66
|
-
models,
|
|
67
|
-
modelOf,
|
|
68
|
-
spriteIds,
|
|
69
|
-
failures
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
const code = await loadModelCode(names, async (internal) => await classes.read(internal), (internal) => mappings.originalOf.get(internal) ?? internal);
|
|
73
|
-
const extracted = /* @__PURE__ */ new Map();
|
|
74
|
-
const geometryOf = async (internal) => {
|
|
75
|
-
if (!extracted.has(internal)) extracted.set(internal, await extractInheritedModel(internal, async (name) => await classes.read(name), code));
|
|
76
|
-
return extracted.get(internal) ?? null;
|
|
77
|
-
};
|
|
78
|
-
const context = {
|
|
79
|
-
mappings,
|
|
80
|
-
read: classReader(async (internal) => await classes.read(internal)),
|
|
81
|
-
hasGeometry: async (internal) => {
|
|
82
|
-
const model = await geometryOf(internal);
|
|
83
|
-
return model !== null && model.parts.reduce((sum, part) => sum + countCubes(part), 0) > 0;
|
|
84
|
-
},
|
|
85
|
-
nameIndex: buildModelNameIndex(names)
|
|
86
|
-
};
|
|
87
|
-
const geoFor = async (entityId) => {
|
|
88
|
-
if (!options.resources) return null;
|
|
89
|
-
const [namespace, name] = entityId.includes(":") ? entityId.split(":") : ["minecraft", entityId];
|
|
90
|
-
return await findGeoForEntity(options.resources, namespace, name);
|
|
91
|
-
};
|
|
92
|
-
let done = 0;
|
|
93
|
-
for (const entityId of [...entityIds].toSorted((left, right) => left.localeCompare(right))) {
|
|
94
|
-
options.onProgress?.(++done, entityIds.length);
|
|
95
|
-
const link = await linkEntityModel(entityId, context);
|
|
96
|
-
const guessed = link?.route === "vanilla-name";
|
|
97
|
-
const found = link && !guessed ? {
|
|
98
|
-
id: link.className,
|
|
99
|
-
model: await geometryOf(link.obfuscated)
|
|
100
|
-
} : await geoFor(entityId) ?? (link ? {
|
|
101
|
-
id: link.className,
|
|
102
|
-
model: await geometryOf(link.obfuscated)
|
|
103
|
-
} : null);
|
|
104
|
-
if (!found?.model) continue;
|
|
105
|
-
const { id: modelId, model } = found;
|
|
106
|
-
if (!models[modelId]) models[modelId] = {
|
|
107
|
-
textureSize: [...model.textureSize],
|
|
108
|
-
parts: model.parts.map((part) => toPackPart(part)),
|
|
109
|
-
...model.notes.length > 0 && { notes: [...model.notes] }
|
|
110
|
-
};
|
|
111
|
-
modelOf.set(entityId, modelId);
|
|
112
|
-
const texture = options.textureOf.get(entityId);
|
|
113
|
-
if (texture) spriteIds.add(texture);
|
|
114
|
-
else failures.push({
|
|
115
|
-
id: entityId,
|
|
116
|
-
reason: `geometry recovered from ${modelId} but no entity texture resolved`
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
return {
|
|
120
|
-
models,
|
|
121
|
-
modelOf,
|
|
122
|
-
spriteIds,
|
|
123
|
-
failures
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
//#endregion
|
|
127
|
-
export { collectEntityGeometry as t };
|