@nodecraft/rendermite 1.10.1 → 1.11.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 +8 -7
  2. package/dist/{block-behaviour-CzK3KVLx.d.ts → block-behaviour-D1qC9_cc.d.ts} +5 -0
  3. package/dist/{block-overrides-XtxICunI.js → block-overrides-BhuJIxKC.js} +1 -1
  4. package/dist/blocks/block-behaviour.d.ts +1 -1
  5. package/dist/blocks/block-overrides.d.ts +1 -1
  6. package/dist/blocks/block-overrides.js +1 -1
  7. package/dist/blocks/cli.js +1 -1
  8. package/dist/blocks/ender-storage.d.ts +1 -1
  9. package/dist/blocks/ender-storage.js +1 -1
  10. package/dist/blocks/entities.d.ts +1 -1
  11. package/dist/blocks/entity-geo.js +1 -1
  12. package/dist/blocks/entity-models.d.ts +1 -1
  13. package/dist/blocks/entity-models.js +1 -1
  14. package/dist/blocks/entity-sizes.js +1 -1
  15. package/dist/blocks/export.d.ts +1 -1
  16. package/dist/blocks/export.js +1 -1
  17. package/dist/blocks/game-rules.js +1 -1
  18. package/dist/blocks/geo-blocks.d.ts +1 -1
  19. package/dist/blocks/geo-blocks.js +1 -1
  20. package/dist/blocks/item-sprites.d.ts +1 -1
  21. package/dist/blocks/light-bytecode.d.ts +1 -1
  22. package/dist/blocks/light-bytecode.js +1 -1
  23. package/dist/blocks/light-eval.d.ts +1 -1
  24. package/dist/blocks/light.d.ts +7 -2
  25. package/dist/blocks/light.js +2 -2
  26. package/dist/blocks/obj-mesh.js +1 -1
  27. package/dist/blocks/pack-format.d.ts +1 -1
  28. package/dist/blocks/sprite-sheet.d.ts +1 -1
  29. package/dist/blocks/sprite-sheet.js +1 -1
  30. package/dist/cached-BOX3n1Dl.js +54 -0
  31. package/dist/{cli-2mzPC8cy.js → cli-BsEk_aEv.js} +16 -2
  32. package/dist/cli.js +2 -2
  33. package/dist/{compose-BGsNFR12.js → compose-CuIKcRpx.js} +1 -1
  34. package/dist/{encode-LR9wxigC.js → encode-TzYXOEId.js} +5 -4
  35. package/dist/{ender-storage-Dgomp6r2.js → ender-storage-CKDiYgYc.js} +1 -1
  36. package/dist/entities/mappings.js +1 -1
  37. package/dist/entities/model-code.js +1 -1
  38. package/dist/{entity-fallback-BucEf6WB.js → entity-fallback-BEzCbJq0.js} +1 -1
  39. package/dist/{entity-geo-DbTtMlPL.js → entity-geo-DcrcN8TE.js} +1 -1
  40. package/dist/{entity-models-vFl_EwfA.js → entity-models-D6AMLAy6.js} +3 -3
  41. package/dist/{entity-sizes-DspxgSUA.js → entity-sizes-Dmr4w0vu.js} +4 -3
  42. package/dist/{export-DgB0e5sB.js → export-BdHar0ND.js} +36 -14
  43. package/dist/{export-CqeTinYL.d.ts → export-CnKiSTiu.d.ts} +8 -0
  44. package/dist/{face-DbyyYmzp.js → face-D6SfTISC.js} +1 -1
  45. package/dist/{game-rules-BDPTopVW.js → game-rules-Dehe210A.js} +4 -3
  46. package/dist/{geo-BoDxwvz5.js → geo-BOYYFFQn.js} +3 -3
  47. package/dist/{geo-blocks-W79q5A0f.js → geo-blocks-BQqFfAQT.js} +1 -1
  48. package/dist/index.d.ts +2 -2
  49. package/dist/index.js +6 -6
  50. package/dist/{light-BnaYFouC.js → light-Culwie4W.js} +26 -10
  51. package/dist/{light-bytecode-hhkkjMVi.js → light-bytecode-Bx3XLTRI.js} +1 -1
  52. package/dist/{light-eval-B4q-aVcf.d.ts → light-eval-Cl2L3RBz.d.ts} +1 -1
  53. package/dist/{mappings-DEl_7xxQ.js → mappings-CTB7_uZa.js} +16 -1
  54. package/dist/{model-code-BmA5ilgt.js → model-code-C5Au_FKU.js} +4 -3
  55. package/dist/{obj-DPEK_xee.js → obj-NxBaySXt.js} +67 -33
  56. package/dist/{obj-mesh-BFhtTBXX.js → obj-mesh-BBSLG2Fv.js} +1 -1
  57. package/dist/output/encode.js +1 -1
  58. package/dist/output/item-styles.d.ts +1 -1
  59. package/dist/output/stylesheet.d.ts +1 -1
  60. package/dist/output/stylesheet.js +1 -1
  61. package/dist/pack.d.ts +2 -2
  62. package/dist/{pipeline-Q_185kY6.js → pipeline-CCfkRth7.js} +7 -6
  63. package/dist/{rasterizer-DcVJzkxz.js → rasterizer-M9Y7mn-W.js} +13 -5
  64. package/dist/read-ahead-BlSzTexs.js +31 -0
  65. package/dist/render/compose.js +1 -1
  66. package/dist/render/entity-fallback.js +1 -1
  67. package/dist/render/face.js +1 -1
  68. package/dist/render/geo.js +1 -1
  69. package/dist/render/obj.js +1 -1
  70. package/dist/render/pipeline.js +1 -1
  71. package/dist/render/rasterizer.js +1 -1
  72. package/dist/render/renderer.js +1 -1
  73. package/dist/resources/cached.d.ts +27 -0
  74. package/dist/resources/cached.js +2 -0
  75. package/dist/resources/read-ahead.d.ts +12 -0
  76. package/dist/resources/read-ahead.js +2 -0
  77. package/dist/{run-5yX5KRiI.js → run-Bf5TLTJw.js} +7 -6
  78. package/dist/run.js +1 -1
  79. package/dist/{sprite-sheet-LQAEtGkp.js → sprite-sheet-BWsLl0Vd.js} +4 -2
  80. package/dist/{stylesheet-CovT3B2S.js → stylesheet-C61VrCAV.js} +6 -4
  81. package/dist/{stylesheet-i-t_7sZ7.d.ts → stylesheet-DxHkk4qA.d.ts} +2 -0
  82. package/dist/workers/render-worker.js +1 -1
  83. package/package.json +1 -1
package/README.md CHANGED
@@ -116,13 +116,14 @@ Benchmarked against PHP renderchest v5.1.0 on the same machine, rendering the sa
116
116
 
117
117
  | | wall time | items written | silent drops | throughput |
118
118
  | --- | --- | --- | --- | --- |
119
- | renderchest (docker, 8 workers) | 210s | 1,573 | 33 | ~449/min |
120
- | rendermite (one Node process, pool 8) | 22.9s | 2,065 | 0 | ~5,410/min |
121
-
122
- That comparison is a fixed point in time; rendermite has since roughly halved its own wall
123
- time again (worker threads, a faster compositor, bounded animations). Run `npm run bench` for
124
- current numbers on your machine — CI runs the same suite and comments the delta on pull
125
- requests.
119
+ | renderchest (docker, 8 cores) | 186s | 1,573 | 33 | ~506/min |
120
+ | rendermite (one Node process, 8 worker threads) | 12.1s | 2,035 | 0 | ~10,070/min |
121
+
122
+ 15x faster with 29% more items rendered. renderchest logged 1,606 items as rendered and exited 0,
123
+ but wrote 1,573 of them; rendermite reports every item it could not draw in
124
+ `rc-minecraft-failures.json`. Both run with `--size 64 --format webp --fallback --item-list`,
125
+ median of warm runs, measured September 2026. Run `npm run bench` for current numbers on your
126
+ machine; CI runs the same suite and comments the delta on pull requests.
126
127
 
127
128
  ## Testing
128
129
 
@@ -394,6 +394,11 @@ interface BlockPackMetaFile {
394
394
  names: number;
395
395
  failures: number;
396
396
  };
397
+ /**
398
+ * The version `behaviour.json` was read from, when it is not this pack's own: 1.13 to 1.14.3 ship
399
+ * no mappings, so their table is 1.14.4's, kept to the blocks this version has.
400
+ */
401
+ behaviourFrom?: string;
397
402
  /** sha256 per file, enough to verify a cached copy without refetching it. */
398
403
  hashes: Record<string, string>;
399
404
  }
@@ -1,4 +1,4 @@
1
- import { n as instructions } from "./entity-sizes-DspxgSUA.js";
1
+ import { n as instructions } from "./entity-sizes-Dmr4w0vu.js";
2
2
  //#region src/blocks/block-overrides.ts
3
3
  /**
4
4
  * Where a block's own class answers a question itself, rather than leaving it to its `Properties`.
@@ -1,2 +1,2 @@
1
- import { i as statedMapColor, n as PushReactionName, r as blockBehaviour, t as BlockBehaviour } from "../block-behaviour-CzK3KVLx.js";
1
+ import { i as statedMapColor, n as PushReactionName, r as blockBehaviour, t as BlockBehaviour } from "../block-behaviour-D1qC9_cc.js";
2
2
  export { BlockBehaviour, PushReactionName, blockBehaviour, statedMapColor };
@@ -1,4 +1,4 @@
1
- import { d as MemberReference } from "../block-behaviour-CzK3KVLx.js";
1
+ import { d as MemberReference } from "../block-behaviour-D1qC9_cc.js";
2
2
  import { t as ClassFile } from "../classfile-Dzn0gW9M.js";
3
3
  //#region src/blocks/block-overrides.d.ts
4
4
  interface OverrideSource {
@@ -1,2 +1,2 @@
1
- import { i as overrideOf, n as constantFluidOf, r as constantsReadBy, t as alwaysInvisible } from "../block-overrides-XtxICunI.js";
1
+ import { i as overrideOf, n as constantFluidOf, r as constantsReadBy, t as alwaysInvisible } from "../block-overrides-BhuJIxKC.js";
2
2
  export { alwaysInvisible, constantFluidOf, constantsReadBy, overrideOf };
@@ -1,2 +1,2 @@
1
- import { t as runBlocksCli } from "../cli-2mzPC8cy.js";
1
+ import { t as runBlocksCli } from "../cli-BsEk_aEv.js";
2
2
  export { runBlocksCli };
@@ -1,5 +1,5 @@
1
1
  import { a as ResourceManager } from "../manager-Ct0dEOMg.js";
2
- import { P as BlockPackModel } from "../block-behaviour-CzK3KVLx.js";
2
+ import { P as BlockPackModel } from "../block-behaviour-D1qC9_cc.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,2 +1,2 @@
1
- import { t as enderStorageBlockModel } from "../ender-storage-Dgomp6r2.js";
1
+ import { t as enderStorageBlockModel } from "../ender-storage-CKDiYgYc.js";
2
2
  export { enderStorageBlockModel };
@@ -1,6 +1,6 @@
1
1
  import { a as ResourceManager } from "../manager-Ct0dEOMg.js";
2
2
  import { i as TextureLoader } from "../loader-C4gsX_wO.js";
3
- import { q as EntityPackEntry } from "../block-behaviour-CzK3KVLx.js";
3
+ import { q as EntityPackEntry } from "../block-behaviour-D1qC9_cc.js";
4
4
  //#region src/blocks/entities.d.ts
5
5
  interface EntityPackResult {
6
6
  entities: Record<string, EntityPackEntry>;
@@ -1,2 +1,2 @@
1
- import { t as findGeoForEntity } from "../entity-geo-DbTtMlPL.js";
1
+ import { t as findGeoForEntity } from "../entity-geo-DcrcN8TE.js";
2
2
  export { findGeoForEntity };
@@ -1,6 +1,6 @@
1
1
  import { a as ResourceManager } from "../manager-Ct0dEOMg.js";
2
2
  import { t as ClassSource } from "../jar-classes-CSRrPAUy.js";
3
- import { J as EntityPackModel, X as EquipmentPack } from "../block-behaviour-CzK3KVLx.js";
3
+ import { J as EntityPackModel, X as EquipmentPack } from "../block-behaviour-D1qC9_cc.js";
4
4
  import { t as Mappings } from "../mappings-DhOPQTgV.js";
5
5
  import { t as ModelCode } from "../model-code-BclYt1do.js";
6
6
  //#region src/blocks/entity-models.d.ts
@@ -1,2 +1,2 @@
1
- import { n as collectEntityGeometry, r as collectEquipment, t as collectArmourTrims } from "../entity-models-vFl_EwfA.js";
1
+ import { n as collectEntityGeometry, r as collectEquipment, t as collectArmourTrims } from "../entity-models-D6AMLAy6.js";
2
2
  export { collectArmourTrims, collectEntityGeometry, collectEquipment };
@@ -1,2 +1,2 @@
1
- import { n as instructions, t as collectEntitySizes } from "../entity-sizes-DspxgSUA.js";
1
+ import { n as instructions, t as collectEntitySizes } from "../entity-sizes-Dmr4w0vu.js";
2
2
  export { collectEntitySizes, instructions };
@@ -1,2 +1,2 @@
1
- import { i as exportBlockPack, n as BlockPackResult, r as ExportBlockPackOptions, t as BlockPackFailure } from "../export-CqeTinYL.js";
1
+ import { i as exportBlockPack, n as BlockPackResult, r as ExportBlockPackOptions, t as BlockPackFailure } from "../export-CnKiSTiu.js";
2
2
  export { BlockPackFailure, BlockPackResult, ExportBlockPackOptions, exportBlockPack };
@@ -1,2 +1,2 @@
1
- import { t as exportBlockPack } from "../export-DgB0e5sB.js";
1
+ import { t as exportBlockPack } from "../export-BdHar0ND.js";
2
2
  export { exportBlockPack };
@@ -1,2 +1,2 @@
1
- import { t as collectGameRules } from "../game-rules-BDPTopVW.js";
1
+ import { t as collectGameRules } from "../game-rules-Dehe210A.js";
2
2
  export { collectGameRules };
@@ -1,5 +1,5 @@
1
1
  import { a as ResourceManager } from "../manager-Ct0dEOMg.js";
2
- import { P as BlockPackModel } from "../block-behaviour-CzK3KVLx.js";
2
+ import { P as BlockPackModel } from "../block-behaviour-D1qC9_cc.js";
3
3
  //#region src/blocks/geo-blocks.d.ts
4
4
  interface GeoBlockOverride {
5
5
  model: BlockPackModel;
@@ -1,2 +1,2 @@
1
- import { t as geoBlockModel } from "../geo-blocks-W79q5A0f.js";
1
+ import { t as geoBlockModel } from "../geo-blocks-BQqFfAQT.js";
2
2
  export { geoBlockModel };
@@ -1,7 +1,7 @@
1
1
  import { a as ResourceManager } from "../manager-Ct0dEOMg.js";
2
2
  import { i as TextureLoader } from "../loader-C4gsX_wO.js";
3
3
  import { t as ModelLoader } from "../loader-BYyPIs9f.js";
4
- import { Q as ItemPackEntry } from "../block-behaviour-CzK3KVLx.js";
4
+ import { Q as ItemPackEntry } from "../block-behaviour-D1qC9_cc.js";
5
5
  //#region src/blocks/item-sprites.d.ts
6
6
  interface ItemSpriteFailure {
7
7
  id: string;
@@ -1,2 +1,2 @@
1
- import { _ as extractBlockLight, a as Handle, c as LightExtraction, d as MemberReference, f as PropertyDomain, g as Value, h as StateProbe, l as LightGetter, m as Registration, o as LambdaValue, p as PropsCall, s as LightCodeSource, u as LightSpec } from "../block-behaviour-CzK3KVLx.js";
1
+ import { _ as extractBlockLight, a as Handle, c as LightExtraction, d as MemberReference, f as PropertyDomain, g as Value, h as StateProbe, l as LightGetter, m as Registration, o as LambdaValue, p as PropsCall, s as LightCodeSource, u as LightSpec } from "../block-behaviour-D1qC9_cc.js";
2
2
  export { Handle, LambdaValue, LightCodeSource, LightExtraction, LightGetter, LightSpec, MemberReference, PropertyDomain, PropsCall, Registration, StateProbe, Value, extractBlockLight };
@@ -1,2 +1,2 @@
1
- import { t as extractBlockLight } from "../light-bytecode-hhkkjMVi.js";
1
+ import { t as extractBlockLight } from "../light-bytecode-Bx3XLTRI.js";
2
2
  export { extractBlockLight };
@@ -1,2 +1,2 @@
1
- import { t as blockLightLevel } from "../light-eval-B4q-aVcf.js";
1
+ import { t as blockLightLevel } from "../light-eval-Cl2L3RBz.js";
2
2
  export { blockLightLevel };
@@ -1,5 +1,5 @@
1
1
  import { t as ClassSource } from "../jar-classes-CSRrPAUy.js";
2
- import { j as BlockPackLight, t as BlockBehaviour } from "../block-behaviour-CzK3KVLx.js";
2
+ import { j as BlockPackLight, t as BlockBehaviour } from "../block-behaviour-D1qC9_cc.js";
3
3
  //#region src/blocks/light.d.ts
4
4
  interface CollectBlockLightOptions {
5
5
  version: string;
@@ -34,6 +34,11 @@ interface BlockLightResult {
34
34
  /** What the interpreter gave up on along the way, for a person reading a failure. */
35
35
  notes: string[];
36
36
  }
37
+ /**
38
+ * Blockstate files that describe no block. The item frames are entities whose model the game looks up
39
+ * through a blockstate, so they have no registration to find and emit nothing.
40
+ */
41
+ declare const NOT_BLOCKS: ReadonlySet<string>;
37
42
  declare function collectBlockLight(options: CollectBlockLightOptions): Promise<BlockLightResult>;
38
43
  /**
39
44
  * Vanilla's emitters, transcribed from `Blocks.java` across 1.13 → 26.2 and checked against the wiki.
@@ -47,4 +52,4 @@ declare const VANILLA_LIGHT: Record<string, BlockPackLight>;
47
52
  /** The vanilla table as it stood at a version: `VANILLA_LIGHT` with the history applied. */
48
53
  declare function vanillaLightAt(version: string): Record<string, BlockPackLight>;
49
54
  //#endregion
50
- export { BlockLightResult, CollectBlockLightOptions, VANILLA_LIGHT, collectBlockLight, vanillaLightAt };
55
+ export { BlockLightResult, CollectBlockLightOptions, NOT_BLOCKS, VANILLA_LIGHT, collectBlockLight, vanillaLightAt };
@@ -1,2 +1,2 @@
1
- import { n as collectBlockLight, r as vanillaLightAt, t as VANILLA_LIGHT } from "../light-BnaYFouC.js";
2
- export { VANILLA_LIGHT, collectBlockLight, vanillaLightAt };
1
+ import { i as vanillaLightAt, n as VANILLA_LIGHT, r as collectBlockLight, t as NOT_BLOCKS } from "../light-Culwie4W.js";
2
+ export { NOT_BLOCKS, VANILLA_LIGHT, collectBlockLight, vanillaLightAt };
@@ -1,2 +1,2 @@
1
- import { n as buildObjMesh, t as ObjMeshError } from "../obj-mesh-BFhtTBXX.js";
1
+ import { n as buildObjMesh, t as ObjMeshError } from "../obj-mesh-BBSLG2Fv.js";
2
2
  export { ObjMeshError, buildObjMesh };
@@ -1,2 +1,2 @@
1
- import { $ as ItemPackLayer, A as BlockPackItemsFile, B as BlockPackStatesFile, C as BlockPackBlockState, D as BlockPackEntityModelsFile, E as BlockPackEntitiesFile, F as BlockPackModelsFile, G as EntityPackCube, H as BlockPackTintsFile, I as BlockPackNamesFile, J as EntityPackModel, K as EntityPackCubeFace, L as BlockPackRenderLayer, M as BlockPackLightFile, N as BlockPackMetaFile, O as BlockPackFace, P as BlockPackModel, Q as ItemPackEntry, R as BlockPackSprite, S as BlockPackBiomesFile, T as BlockPackElement, U as BlockPackVariant, V as BlockPackTagsFile, W as EQUIPMENT_SLOTS, X as EquipmentPack, Y as EntityPackPart, Z as EquipmentSlot, b as BlockPackAtlasPage, j as BlockPackLight, k as BlockPackGameRulesFile, q as EntityPackEntry, v as BlockPackAdvancementsFile, w as BlockPackBlockStatesFile, x as BlockPackBehaviourFile, y as BlockPackAtlasFile, z as BlockPackSpriteFrame } from "../block-behaviour-CzK3KVLx.js";
1
+ import { $ as ItemPackLayer, A as BlockPackItemsFile, B as BlockPackStatesFile, C as BlockPackBlockState, D as BlockPackEntityModelsFile, E as BlockPackEntitiesFile, F as BlockPackModelsFile, G as EntityPackCube, H as BlockPackTintsFile, I as BlockPackNamesFile, J as EntityPackModel, K as EntityPackCubeFace, L as BlockPackRenderLayer, M as BlockPackLightFile, N as BlockPackMetaFile, O as BlockPackFace, P as BlockPackModel, Q as ItemPackEntry, R as BlockPackSprite, S as BlockPackBiomesFile, T as BlockPackElement, U as BlockPackVariant, V as BlockPackTagsFile, W as EQUIPMENT_SLOTS, X as EquipmentPack, Y as EntityPackPart, Z as EquipmentSlot, b as BlockPackAtlasPage, j as BlockPackLight, k as BlockPackGameRulesFile, q as EntityPackEntry, v as BlockPackAdvancementsFile, w as BlockPackBlockStatesFile, x as BlockPackBehaviourFile, y as BlockPackAtlasFile, z as BlockPackSpriteFrame } from "../block-behaviour-D1qC9_cc.js";
2
2
  export { BlockPackAdvancementsFile, BlockPackAtlasFile, BlockPackAtlasPage, BlockPackBehaviourFile, BlockPackBiomesFile, BlockPackBlockState, BlockPackBlockStatesFile, BlockPackElement, BlockPackEntitiesFile, BlockPackEntityModelsFile, BlockPackFace, BlockPackGameRulesFile, BlockPackItemsFile, BlockPackLight, BlockPackLightFile, BlockPackMetaFile, BlockPackModel, BlockPackModelsFile, BlockPackNamesFile, BlockPackRenderLayer, BlockPackSprite, BlockPackSpriteFrame, BlockPackStatesFile, BlockPackTagsFile, BlockPackTintsFile, BlockPackVariant, EQUIPMENT_SLOTS, EntityPackCube, EntityPackCubeFace, EntityPackEntry, EntityPackModel, EntityPackPart, EquipmentPack, EquipmentSlot, ItemPackEntry, ItemPackLayer };
@@ -1,6 +1,6 @@
1
1
  import { i as TextureLoader, r as Texture } from "../loader-C4gsX_wO.js";
2
2
  import { i as PackedPage } from "../atlas-pack-BUadroKy.js";
3
- import { L as BlockPackRenderLayer, R as BlockPackSprite } from "../block-behaviour-CzK3KVLx.js";
3
+ import { L as BlockPackRenderLayer, R as BlockPackSprite } from "../block-behaviour-D1qC9_cc.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,2 +1,2 @@
1
- import { i as missingTexture, n as buildSpriteSheet, r as inferRenderLayer, t as MISSING_SPRITE } from "../sprite-sheet-LQAEtGkp.js";
1
+ import { i as missingTexture, n as buildSpriteSheet, r as inferRenderLayer, t as MISSING_SPRITE } from "../sprite-sheet-BWsLl0Vd.js";
2
2
  export { MISSING_SPRITE, buildSpriteSheet, inferRenderLayer, missingTexture };
@@ -0,0 +1,54 @@
1
+ //#region src/resources/cached.ts
2
+ /**
3
+ * Remembers directory listings for the lifetime of one render or export.
4
+ *
5
+ * Fallback lookups (mob heads, chests, geo files, sprite fallbacks) scan a
6
+ * whole namespace per item, and every scan re-walked the jar index, re-read
7
+ * the builtin pack from disk and re-deduplicated thousands of locators across
8
+ * layers: one block export listed `minecraft` textures 849 times. The model
9
+ * and texture caches beside it already assume the tree is fixed for the run,
10
+ * so this assumes the same and no more. Reads pass straight through.
11
+ */
12
+ var CachedListingResourceManager = class {
13
+ inner;
14
+ listings = /* @__PURE__ */ new Map();
15
+ namespaces = null;
16
+ constructor(inner) {
17
+ this.inner = inner;
18
+ }
19
+ getResource(kind, locator) {
20
+ return this.inner.getResource(kind, locator);
21
+ }
22
+ getAllResources(kind, locator) {
23
+ return this.inner.getAllResources(kind, locator);
24
+ }
25
+ hasResource(kind, locator) {
26
+ return this.inner.hasResource(kind, locator);
27
+ }
28
+ async listResources(kind, namespace) {
29
+ const key = `${kind} ${namespace}`;
30
+ let listing = this.listings.get(key);
31
+ if (!listing) {
32
+ listing = this.inner.listResources(kind, namespace);
33
+ this.listings.set(key, listing);
34
+ listing.catch(() => this.listings.delete(key));
35
+ }
36
+ return [...await listing];
37
+ }
38
+ async listNamespaces() {
39
+ if (!this.namespaces) {
40
+ const pending = this.inner.listNamespaces();
41
+ this.namespaces = pending;
42
+ pending.catch(() => {
43
+ this.namespaces = null;
44
+ });
45
+ }
46
+ return [...await this.namespaces];
47
+ }
48
+ describe() {
49
+ const describable = this.inner;
50
+ return typeof describable.describe === "function" ? describable.describe() : null;
51
+ }
52
+ };
53
+ //#endregion
54
+ export { CachedListingResourceManager as t };
@@ -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-D6zXmFrO.js";
3
3
  import { a as prepareVersionResources, r as compareVersions } from "./prepare-DkJkZXuQ.js";
4
- import { t as exportBlockPack } from "./export-DgB0e5sB.js";
4
+ import { t as exportBlockPack } from "./export-BdHar0ND.js";
5
5
  import { n as layeredClasses, t as JarClassReader } from "./jar-classes-0wqWbTax.js";
6
6
  import { n as prepareModResources } from "./prepare-sj36BP90.js";
7
7
  import { t as downloadClientJar } from "./download-1wAfrGKx.js";
@@ -16,6 +16,8 @@ import { parseArgs } from "node:util";
16
16
  */
17
17
  /** The Flattening: below it a block is `35:14` and needs a numeric-id table. */
18
18
  const MINIMUM_VERSION = "1.13";
19
+ /** The first release Mojang published mappings for; older jars borrow its block behaviour. */
20
+ const FIRST_MAPPED_VERSION = "1.14.4";
19
21
  const HELP = `rendermite blocks — Minecraft block pack export (geometry + atlas, 1.13+)
20
22
 
21
23
  Usage:
@@ -135,6 +137,7 @@ async function runBlocksCli(argv) {
135
137
  const cacheDir = values["cache-dir"] ?? path.join(os.homedir(), ".rendermite");
136
138
  let resources;
137
139
  let classes = null;
140
+ let behaviourFrom;
138
141
  if (values.version) {
139
142
  console.log(`Fetching client jar for ${values.version}…`);
140
143
  const jar = await downloadClientJar(values.version, cacheDir);
@@ -142,7 +145,16 @@ async function runBlocksCli(argv) {
142
145
  version: values.version,
143
146
  jar
144
147
  });
145
- if (!values["no-entity-geometry"]) classes = new JarClassReader(jar);
148
+ if (!values["no-entity-geometry"]) {
149
+ classes = new JarClassReader(jar);
150
+ if (compareVersions(values.version, FIRST_MAPPED_VERSION) < 0 && !values.mod?.length) {
151
+ console.log(`Fetching client jar for ${FIRST_MAPPED_VERSION}, to read the block behaviour ${values.version} has no mappings for…`);
152
+ behaviourFrom = {
153
+ version: FIRST_MAPPED_VERSION,
154
+ classes: new JarClassReader(await downloadClientJar(FIRST_MAPPED_VERSION, cacheDir))
155
+ };
156
+ }
157
+ }
146
158
  } else {
147
159
  const managers = (values.assets ?? []).map((root) => new FolderResourceManager(root));
148
160
  resources = managers.length === 1 ? managers[0] : new LayeredResourceManager(managers);
@@ -175,6 +187,7 @@ async function runBlocksCli(argv) {
175
187
  items: !values["no-items"],
176
188
  entities: !values["no-entities"],
177
189
  classes: classes ?? void 0,
190
+ behaviourFrom,
178
191
  cacheDir,
179
192
  reports: values.reports,
180
193
  onProgress: (stage, done, total) => {
@@ -193,6 +206,7 @@ async function runBlocksCli(argv) {
193
206
  } finally {
194
207
  await closeMods?.();
195
208
  await classes?.close();
209
+ await behaviourFrom?.classes.close();
196
210
  }
197
211
  }
198
212
  //#endregion
package/dist/cli.js CHANGED
@@ -6,8 +6,8 @@ import { a as prepareVersionResources, i as eraForVersion, n as GEOMETRY_DONOR_V
6
6
  import { t as curatedModelOverrides } from "./models-BsYA-NZg.js";
7
7
  import { n as harvestTintOverrides, t as curatedTintOverrides } from "./tints-CZeyKzMv.js";
8
8
  import { t as downloadClientJar } from "./download-1wAfrGKx.js";
9
- import { t as runBlocksCli } from "./cli-2mzPC8cy.js";
10
- import { t as run } from "./run-5yX5KRiI.js";
9
+ import { t as runBlocksCli } from "./cli-BsEk_aEv.js";
10
+ import { t as run } from "./run-Bf5TLTJw.js";
11
11
  import path from "node:path";
12
12
  import os from "node:os";
13
13
  import { parseArgs } from "node:util";
@@ -68,7 +68,7 @@ function combineFaceBuffers(width, height, faces) {
68
68
  deep[slotIndex] = index;
69
69
  deepDepth[slotIndex] = depth;
70
70
  deepRank[slotIndex] = rank[index];
71
- } else {
71
+ } else if (face.colors[localPixel * 4 + 3] > 0) {
72
72
  let slotIndex = flatCount++;
73
73
  while (slotIndex > 0 && flatRank[slotIndex - 1] > rank[index]) {
74
74
  flat[slotIndex] = flat[slotIndex - 1];
@@ -103,22 +103,23 @@ function countColors(data, cap) {
103
103
  }
104
104
  async function encodeIcon(texture, options = {}) {
105
105
  const bytes = toByteTexture(texture);
106
- const raw = sharp(Buffer.from(bytes.data.buffer, bytes.data.byteOffset, bytes.data.length), { raw: {
106
+ const pixels = Buffer.from(bytes.data.buffer, bytes.data.byteOffset, bytes.data.length);
107
+ const raw = () => sharp(pixels, { raw: {
107
108
  width: bytes.width,
108
109
  height: bytes.height,
109
110
  channels: 4
110
111
  } });
111
112
  const paletteSafe = countColors(bytes.data, 256) <= 256;
112
- const pngPromise = raw.clone().png({
113
+ const pngPromise = raw().png({
113
114
  compressionLevel: 9,
114
115
  effort: 10,
115
116
  palette: paletteSafe
116
117
  }).toBuffer();
117
- const webpPromise = options.webp !== false ? raw.clone().webp({
118
+ const webpPromise = options.webp !== false ? raw().webp({
118
119
  lossless: true,
119
120
  effort: STATIC_WEBP_EFFORT
120
121
  }).toBuffer() : Promise.resolve(void 0);
121
- const avifPromise = options.avif ? raw.clone().avif({
122
+ const avifPromise = options.avif ? raw().avif({
122
123
  lossless: true,
123
124
  effort: 6
124
125
  }).toBuffer() : Promise.resolve(void 0);
@@ -1,5 +1,5 @@
1
1
  import { n as ResourceLocator } from "./locator-COMEtEn9.js";
2
- import { r as parseObj } from "./obj-DPEK_xee.js";
2
+ import { r as parseObj } from "./obj-NxBaySXt.js";
3
3
  //#region src/blocks/ender-storage.ts
4
4
  /** Geometry for Ender Storage blocks whose shipped JSON model is only an empty Java-renderer hook. */
5
5
  const BLOCK_UNITS = 16;
@@ -1,2 +1,2 @@
1
- import { a as loadMappings, c as resolveMappings, i as isObfuscated, n as downloadClientMappings, o as parseMappings, r as identityMappings, s as remapDescriptor, t as MappingsUnavailableError } from "../mappings-DEl_7xxQ.js";
1
+ import { a as loadMappings, c as resolveMappings, i as isObfuscated, n as downloadClientMappings, o as parseMappings, r as identityMappings, s as remapDescriptor, t as MappingsUnavailableError } from "../mappings-CTB7_uZa.js";
2
2
  export { MappingsUnavailableError, downloadClientMappings, identityMappings, isObfuscated, loadMappings, parseMappings, remapDescriptor, resolveMappings };
@@ -1,2 +1,2 @@
1
- import { n as loadModelCode, t as isModelCode } from "../model-code-BmA5ilgt.js";
1
+ import { n as loadModelCode, t as isModelCode } from "../model-code-C5Au_FKU.js";
2
2
  export { isModelCode, loadModelCode };
@@ -1,6 +1,6 @@
1
1
  import { n as ResourceLocator } from "./locator-COMEtEn9.js";
2
2
  import { c as findEntityTexture, d as findMobTexture, h as tokens, m as resolveChestSheets, n as HEAD_LAYOUTS, o as findBedTexture, p as layerAccentSheet, t as DYE_COLORS } from "./entity-textures-DG6NUNyp.js";
3
- import { c as renderModel } from "./obj-DPEK_xee.js";
3
+ import { c as renderModel } from "./obj-NxBaySXt.js";
4
4
  //#region src/render/entity-fallback.ts
5
5
  /**
6
6
  * Heuristic rendering for mod items that parent `builtin/entity` — chests,
@@ -1,6 +1,6 @@
1
1
  import { n as ResourceLocator } from "./locator-COMEtEn9.js";
2
2
  import { t as geoToModel } from "./geo-model-Bo1gpEwX.js";
3
- import { i as parseGeo, r as nameTokens } from "./geo-BoDxwvz5.js";
3
+ import { i as parseGeo, r as nameTokens } from "./geo-BOYYFFQn.js";
4
4
  //#region src/blocks/entity-geo.ts
5
5
  /**
6
6
  * Finding the `.geo.json` a GeckoLib entity is drawn from.
@@ -1,12 +1,12 @@
1
1
  import { n as ResourceLocator } from "./locator-COMEtEn9.js";
2
- import { t as findGeoForEntity } from "./entity-geo-DbTtMlPL.js";
2
+ import { t as findGeoForEntity } from "./entity-geo-DcrcN8TE.js";
3
3
  import { t as EQUIPMENT_SLOTS } from "./pack-format-BP5dJMYY.js";
4
4
  import { t as parseClassFile } from "./classfile-BJSs3JH0.js";
5
5
  import { n as extractModel, t as extractArmourMesh } from "./model-bytecode-CXYAZ5dX.js";
6
6
  import { n as extractInheritedModel, t as ancestryOf } from "./inherit-DJ45bOB_.js";
7
7
  import { a as linkEntityModel, i as classReader, r as buildModelNameIndex } from "./link-IDjVJ2Ij.js";
8
- import { c as resolveMappings, t as MappingsUnavailableError } from "./mappings-DEl_7xxQ.js";
9
- import { n as loadModelCode } from "./model-code-BmA5ilgt.js";
8
+ import { c as resolveMappings, t as MappingsUnavailableError } from "./mappings-CTB7_uZa.js";
9
+ import { n as loadModelCode } from "./model-code-C5Au_FKU.js";
10
10
  //#region src/blocks/entity-models.ts
11
11
  /**
12
12
  * Entity geometry for the pack: link each entity to the class that builds it, read that class's
@@ -1,5 +1,6 @@
1
1
  import { t as parseClassFile } from "./classfile-BJSs3JH0.js";
2
- import { c as resolveMappings, t as MappingsUnavailableError } from "./mappings-DEl_7xxQ.js";
2
+ import { c as resolveMappings, t as MappingsUnavailableError } from "./mappings-CTB7_uZa.js";
3
+ import { t as readAhead } from "./read-ahead-BlSzTexs.js";
3
4
  //#region src/blocks/entity-sizes.ts
4
5
  /**
5
6
  * Each entity type's hitbox, read out of the code that registers it.
@@ -119,8 +120,8 @@ async function collectEntitySizes(options) {
119
120
  }
120
121
  const originalName = (owner, name, descriptor) => mappings.nameOf?.get(`${owner.replaceAll("/", ".")}.${name}${descriptor}`) ?? name;
121
122
  const parsed = [];
122
- for (const name of names) {
123
- const bytes = await options.classes.read(name);
123
+ for (const [, pending] of readAhead(names, (internal) => options.classes.read(internal))) {
124
+ const bytes = await pending;
124
125
  if (!bytes) continue;
125
126
  try {
126
127
  parsed.push(parseClassFile(bytes));
@@ -5,21 +5,22 @@ import { n as blockEntityGeometry, r as synthesizeVariants, t as INVISIBLE_BLOCK
5
5
  import { a as parseBlockState, n as collectModels } from "./blockstate-eval-CV_LwUwj.js";
6
6
  import { t as collectDatapack } from "./datapack-D6eH46ay.js";
7
7
  import { a as salvageJson, i as resolveTexture, t as ModelLoader } from "./loader-qOH0Jynq.js";
8
- import { t as enderStorageBlockModel } from "./ender-storage-Dgomp6r2.js";
8
+ import { t as enderStorageBlockModel } from "./ender-storage-CKDiYgYc.js";
9
9
  import { t as collectEntities } from "./entities-rQ4TZjEo.js";
10
- import { n as collectEntityGeometry } from "./entity-models-vFl_EwfA.js";
11
- import { t as collectEntitySizes } from "./entity-sizes-DspxgSUA.js";
12
- import { t as collectGameRules } from "./game-rules-BDPTopVW.js";
13
- import { t as geoBlockModel } from "./geo-blocks-W79q5A0f.js";
10
+ import { n as collectEntityGeometry } from "./entity-models-D6AMLAy6.js";
11
+ import { t as collectEntitySizes } from "./entity-sizes-Dmr4w0vu.js";
12
+ import { t as collectGameRules } from "./game-rules-Dehe210A.js";
13
+ import { t as geoBlockModel } from "./geo-blocks-BQqFfAQT.js";
14
14
  import { n as discoverItems } from "./discovery-CD0QqxSF.js";
15
15
  import { t as collectItemSprites } from "./item-sprites-CwiEBEAJ.js";
16
- import { n as collectBlockLight } from "./light-BnaYFouC.js";
16
+ import { r as collectBlockLight, t as NOT_BLOCKS } from "./light-Culwie4W.js";
17
17
  import { t as collectNames } from "./names-GLa5TyL7.js";
18
- import { n as buildObjMesh } from "./obj-mesh-BFhtTBXX.js";
19
- import { n as buildSpriteSheet, t as MISSING_SPRITE } from "./sprite-sheet-LQAEtGkp.js";
18
+ import { n as buildObjMesh } from "./obj-mesh-BBSLG2Fv.js";
19
+ import { n as buildSpriteSheet, t as MISSING_SPRITE } from "./sprite-sheet-BWsLl0Vd.js";
20
20
  import { t as readBlockStates } from "./states-BvoZA-ql.js";
21
21
  import { n as buildBlockTints, t as UNREGISTERED_TINTS } from "./tints-Cl0r-Ol3.js";
22
22
  import { t as loadAtlasResolver } from "./registry-DafxsAhG.js";
23
+ import { t as CachedListingResourceManager } from "./cached-BOX3n1Dl.js";
23
24
  import { n as TextureLoader } from "./loader-CsgtBuBo.js";
24
25
  import path from "node:path";
25
26
  import { createHash } from "node:crypto";
@@ -315,7 +316,7 @@ function bakeModel(id, model, failures) {
315
316
  }
316
317
  async function exportBlockPack(options) {
317
318
  const { output, version } = options;
318
- const resources = options.builtin ? new LayeredResourceManager([options.resources, new FolderResourceManager(options.builtin)]) : options.resources;
319
+ const resources = new CachedListingResourceManager(options.builtin ? new LayeredResourceManager([options.resources, new FolderResourceManager(options.builtin)]) : options.resources);
319
320
  const namespaces = options.namespaces ?? ["minecraft"];
320
321
  const failures = [];
321
322
  const report = (stage, done, total) => options.onProgress?.(stage, done, total);
@@ -702,13 +703,16 @@ async function exportBlockPack(options) {
702
703
  const states = options.reports === void 0 ? null : await readBlockStates(options.reports);
703
704
  let lightPack = {};
704
705
  let behaviourPack = {};
706
+ let behaviourFrom;
705
707
  if (options.classes) {
708
+ const blockIds = [.../* @__PURE__ */ new Set([...blockLocators.map((locator) => locator.toString()), ...Object.keys(blockStates)])];
709
+ const defaultStateOf = (id) => states?.[id]?.default ?? null;
706
710
  const collected = await collectBlockLight({
707
711
  version,
708
712
  cacheDir: options.cacheDir ?? output,
709
713
  classes: options.classes,
710
- blockIds: [.../* @__PURE__ */ new Set([...blockLocators.map((locator) => locator.toString()), ...Object.keys(blockStates)])],
711
- defaultStateOf: (id) => states?.[id]?.default ?? null,
714
+ blockIds,
715
+ defaultStateOf,
712
716
  onProgress: (count, total) => report("light", count, total)
713
717
  });
714
718
  lightPack = sortedByKey(collected.light);
@@ -717,11 +721,28 @@ async function exportBlockPack(options) {
717
721
  kind: "light",
718
722
  reason: failure.reason
719
723
  });
720
- behaviourPack = sortedByKey(collected.behaviour);
721
- for (const failure of collected.behaviourFailures) failures.push({
724
+ let behaviour = collected;
725
+ if (Object.keys(collected.behaviour).length === 0 && options.behaviourFrom) {
726
+ behaviour = await collectBlockLight({
727
+ version: options.behaviourFrom.version,
728
+ cacheDir: options.cacheDir ?? output,
729
+ classes: options.behaviourFrom.classes,
730
+ blockIds,
731
+ defaultStateOf,
732
+ onProgress: (count, total) => report("behaviour", count, total)
733
+ });
734
+ behaviourFrom = options.behaviourFrom.version;
735
+ for (const id of blockIds) if (!NOT_BLOCKS.has(id) && !(id in behaviour.behaviour)) failures.push({
736
+ id,
737
+ kind: "behaviour",
738
+ reason: `${behaviourFrom} registers no such block, so its behaviour is unknown`
739
+ });
740
+ }
741
+ behaviourPack = sortedByKey(behaviour.behaviour);
742
+ for (const failure of behaviour.behaviourFailures) failures.push({
722
743
  id: failure.id,
723
744
  kind: "behaviour",
724
- reason: failure.reason
745
+ reason: behaviourFrom ? `read from ${behaviourFrom}: ${failure.reason}` : failure.reason
725
746
  });
726
747
  if (process.env.RENDERMITE_LIGHT_DEBUG) console.error(collected.notes.join("\n"));
727
748
  }
@@ -987,6 +1008,7 @@ async function exportBlockPack(options) {
987
1008
  version,
988
1009
  namespaces,
989
1010
  counts,
1011
+ ...behaviourFrom && Object.keys(behaviourPack).length > 0 && { behaviourFrom },
990
1012
  hashes: sortedByKey(hashes)
991
1013
  }, null, " "));
992
1014
  return {
@@ -40,6 +40,14 @@ interface ExportBlockPackOptions {
40
40
  * answer there is no geometry rather than a silent gap.
41
41
  */
42
42
  classes?: ClassSource;
43
+ /**
44
+ * A mapped version's classes to read `behaviour.json` from, for a jar with no mappings of its own
45
+ * (1.13 to 1.14.3), whose builder calls have no names to read. Used only when `classes` read none.
46
+ */
47
+ behaviourFrom?: {
48
+ version: string;
49
+ classes: ClassSource;
50
+ };
43
51
  /** Where mappings cache; the jar cache directory. */
44
52
  cacheDir?: string;
45
53
  /**
@@ -1,6 +1,6 @@
1
1
  import { a as scaleTextureAlpha, n as cloneFloatTexture, r as darkenTexture, s as tintTexture, u as uvWindow } from "./blend-KXMclcHk.js";
2
2
  import { c as normalize, g as transformVector, h as transformDirection, m as sub, r as dot, t as cross } from "./vector-CCxLae_T.js";
3
- import { a as drawTexturedTriangle, i as createFaceBuffer, n as clearFaceBuffer, o as phpRound, r as compactFaceBuffer, t as RowCursor } from "./rasterizer-DcVJzkxz.js";
3
+ import { a as drawTexturedTriangle, i as createFaceBuffer, n as clearFaceBuffer, o as phpRound, r as compactFaceBuffer, t as RowCursor } from "./rasterizer-M9Y7mn-W.js";
4
4
  //#region src/render/face.ts
5
5
  /**
6
6
  * Face rendering: cull, transform, project, tint, darken, rasterize — a faithful
@@ -1,5 +1,6 @@
1
1
  import { t as parseClassFile } from "./classfile-BJSs3JH0.js";
2
- import { n as instructions } from "./entity-sizes-DspxgSUA.js";
2
+ import { t as readAhead } from "./read-ahead-BlSzTexs.js";
3
+ import { n as instructions } from "./entity-sizes-Dmr4w0vu.js";
3
4
  //#region src/blocks/game-rules.ts
4
5
  /**
5
6
  * The version's game rules: each one's name, whether it is on/off or a number, and its default.
@@ -32,8 +33,8 @@ function valueKind(descriptor) {
32
33
  */
33
34
  async function collectGameRules(classes) {
34
35
  let best = {};
35
- for (const name of await classes.list()) {
36
- const bytes = await classes.read(name);
36
+ for (const [, pending] of readAhead(await classes.list(), (internal) => classes.read(internal))) {
37
+ const bytes = await pending;
37
38
  if (!bytes || ![...MARKERS].some((marker) => Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength).includes(marker))) continue;
38
39
  let classFile;
39
40
  try {