minerender 2.1.0-alpha.20 → 2.1.0-alpha.22

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/dist/bundle.js CHANGED
@@ -25869,17 +25869,17 @@ var MineRender = (() => {
25869
25869
  expr = expr.replace(/\$/g, "$$$$");
25870
25870
  return str.replace(new RegExp(dataVar, "g"), expr + "$1");
25871
25871
  }
25872
- function schemaHasRules(schema, rules) {
25872
+ function schemaHasRules(schema, rules2) {
25873
25873
  if (typeof schema == "boolean") return !schema;
25874
- for (var key in schema) if (rules[key]) return true;
25874
+ for (var key in schema) if (rules2[key]) return true;
25875
25875
  }
25876
- function schemaHasRulesExcept(schema, rules, exceptKeyword) {
25876
+ function schemaHasRulesExcept(schema, rules2, exceptKeyword) {
25877
25877
  if (typeof schema == "boolean") return !schema && exceptKeyword != "not";
25878
- for (var key in schema) if (key != exceptKeyword && rules[key]) return true;
25878
+ for (var key in schema) if (key != exceptKeyword && rules2[key]) return true;
25879
25879
  }
25880
- function schemaUnknownRules(schema, rules) {
25880
+ function schemaUnknownRules(schema, rules2) {
25881
25881
  if (typeof schema == "boolean") return;
25882
- for (var key in schema) if (!rules[key]) return key;
25882
+ for (var key in schema) if (!rules2[key]) return key;
25883
25883
  }
25884
25884
  function toQuotedString(str) {
25885
25885
  return "'" + escapeQuotes(str) + "'";
@@ -26806,9 +26806,9 @@ var MineRender = (() => {
26806
26806
  out += " var " + $valid + " = errors === errs_" + $lvl + ";";
26807
26807
  }
26808
26808
  function $shouldUseGroup($rulesGroup2) {
26809
- var rules = $rulesGroup2.rules;
26810
- for (var i4 = 0; i4 < rules.length; i4++)
26811
- if ($shouldUseRule(rules[i4])) return true;
26809
+ var rules2 = $rulesGroup2.rules;
26810
+ for (var i4 = 0; i4 < rules2.length; i4++)
26811
+ if ($shouldUseRule(rules2[i4])) return true;
26812
26812
  }
26813
26813
  function $shouldUseRule($rule2) {
26814
26814
  return it.schema[$rule2.keyword] !== void 0 || $rule2.implements && $ruleImplementsSomeKeyword($rule2);
@@ -29887,7 +29887,7 @@ var MineRender = (() => {
29887
29887
  init_process2();
29888
29888
  var ruleModules = require_dotjs();
29889
29889
  var toHash = require_util().toHash;
29890
- module2.exports = function rules() {
29890
+ module2.exports = function rules2() {
29891
29891
  var RULES = [
29892
29892
  {
29893
29893
  type: "number",
@@ -30624,10 +30624,10 @@ var MineRender = (() => {
30624
30624
  delete RULES.all[keyword];
30625
30625
  delete RULES.custom[keyword];
30626
30626
  for (var i4 = 0; i4 < RULES.length; i4++) {
30627
- var rules = RULES[i4].rules;
30628
- for (var j4 = 0; j4 < rules.length; j4++) {
30629
- if (rules[j4].keyword == keyword) {
30630
- rules.splice(j4, 1);
30627
+ var rules2 = RULES[i4].rules;
30628
+ for (var j4 = 0; j4 < rules2.length; j4++) {
30629
+ if (rules2[j4].keyword == keyword) {
30630
+ rules2.splice(j4, 1);
30631
30631
  break;
30632
30632
  }
30633
30633
  }
@@ -30683,7 +30683,7 @@ var MineRender = (() => {
30683
30683
  var SchemaObject = require_schema_obj();
30684
30684
  var stableStringify = require_fast_json_stable_stringify();
30685
30685
  var formats = require_formats();
30686
- var rules = require_rules();
30686
+ var rules2 = require_rules();
30687
30687
  var $dataMetaSchema = require_data();
30688
30688
  var util = require_util();
30689
30689
  module2.exports = Ajv;
@@ -30722,7 +30722,7 @@ var MineRender = (() => {
30722
30722
  this._cache = opts.cache || new Cache();
30723
30723
  this._loadingSchemas = {};
30724
30724
  this._compilations = [];
30725
- this.RULES = rules();
30725
+ this.RULES = rules2();
30726
30726
  this._getId = chooseGetId(opts);
30727
30727
  opts.loopRequired = opts.loopRequired || Infinity;
30728
30728
  if (opts.errorDataPath == "property") opts._errorDataPathProperty = true;
@@ -45356,6 +45356,7 @@ return ${compiler2.callType("value", tagType)}
45356
45356
  BlockEntityModels: () => BlockEntityModels,
45357
45357
  BlockObject: () => BlockObject,
45358
45358
  BlockStates: () => BlockStates,
45359
+ BlockTints: () => BlockTints,
45359
45360
  BrowserArchiveProxy: () => BrowserArchiveProxy,
45360
45361
  BrowserCache: () => BrowserCache,
45361
45362
  BrowserEnv: () => BrowserEnv,
@@ -45372,6 +45373,7 @@ return ${compiler2.callType("value", tagType)}
45372
45373
  DISPLAY_POSITIONS: () => DISPLAY_POSITIONS,
45373
45374
  DefaultBlockStates: () => DefaultBlockStates,
45374
45375
  DisplayPosition: () => DisplayPosition,
45376
+ DisplayTransforms: () => DisplayTransforms,
45375
45377
  Entities: () => Entities,
45376
45378
  EntityModels: () => EntityModels,
45377
45379
  EntityObject: () => EntityObject,
@@ -66380,6 +66382,7 @@ return ${compiler2.callType("value", tagType)}
66380
66382
  this.blockStateCache,
66381
66383
  this.listAssetCache,
66382
66384
  this.defaultBlockStatesCache,
66385
+ this.blockTintCache,
66383
66386
  this.entityModelsCache
66384
66387
  ];
66385
66388
  }
@@ -66422,6 +66425,7 @@ return ${compiler2.callType("value", tagType)}
66422
66425
  _Caching.blockStateCache = Caches.builder().expireAfterWrite(Time.minutes(10)).expireAfterAccess(Time.minutes(5)).expirationInterval(Time.seconds(30)).buildAsync();
66423
66426
  _Caching.listAssetCache = _Caching.createAssetCache();
66424
66427
  _Caching.defaultBlockStatesCache = _Caching.createAssetCache();
66428
+ _Caching.blockTintCache = _Caching.createAssetCache();
66425
66429
  _Caching.entityModelsCache = _Caching.createAssetCache();
66426
66430
  var Caching = _Caching;
66427
66431
 
@@ -67216,15 +67220,82 @@ return ${compiler2.callType("value", tagType)}
67216
67220
  return isBasicAssetKey(obj) && obj.isAssetKey === true;
67217
67221
  }
67218
67222
 
67223
+ // src/model/DisplayTransforms.ts
67224
+ init_dirname();
67225
+ init_buffer2();
67226
+ init_process2();
67227
+
67228
+ // src/model/DisplayPosition.ts
67229
+ init_dirname();
67230
+ init_buffer2();
67231
+ init_process2();
67232
+ var DisplayPosition = /* @__PURE__ */ ((DisplayPosition2) => {
67233
+ DisplayPosition2["THIRDPERSON_RIGHTHAND"] = "thirdperson_righthand";
67234
+ DisplayPosition2["THIRDPERSON_LEFTHAND"] = "thirdperson_lefthand";
67235
+ DisplayPosition2["FIRSTPERSON_RIGHTHAND"] = "firstperson_righthand";
67236
+ DisplayPosition2["FIRSTPERSON_LEFTHAND"] = "firstperson_lefthand";
67237
+ DisplayPosition2["GUI"] = "gui";
67238
+ DisplayPosition2["HEAD"] = "head";
67239
+ DisplayPosition2["GROUND"] = "ground";
67240
+ DisplayPosition2["FIXED"] = "fixed";
67241
+ DisplayPosition2["ON_SHELF"] = "on_shelf";
67242
+ return DisplayPosition2;
67243
+ })(DisplayPosition || {});
67244
+ var DISPLAY_POSITIONS = Object.values(DisplayPosition);
67245
+
67246
+ // src/model/DisplayTransforms.ts
67247
+ var DisplayTransforms = class {
67248
+ /** Resolve hand fallbacks within one model, before inheriting parent display entries. */
67249
+ static withHandFallbacks(display) {
67250
+ if (!display) return void 0;
67251
+ const resolved = { ...display };
67252
+ for (const [left, right] of [
67253
+ ["thirdperson_lefthand" /* THIRDPERSON_LEFTHAND */, "thirdperson_righthand" /* THIRDPERSON_RIGHTHAND */],
67254
+ ["firstperson_lefthand" /* FIRSTPERSON_LEFTHAND */, "firstperson_righthand" /* FIRSTPERSON_RIGHTHAND */]
67255
+ ]) {
67256
+ if (resolved[left] === void 0 && resolved[right] !== void 0) resolved[left] = resolved[right];
67257
+ }
67258
+ return resolved;
67259
+ }
67260
+ /** Build a display pose for geometry already centered at the model's [8, 8, 8] pivot. */
67261
+ static getMatrix(display, position) {
67262
+ const transform = this.withHandFallbacks(display)?.[position] ?? {};
67263
+ const left = position === "firstperson_lefthand" /* FIRSTPERSON_LEFTHAND */ || position === "thirdperson_lefthand" /* THIRDPERSON_LEFTHAND */;
67264
+ const sign = left ? -1 : 1;
67265
+ const [x4, y5, z4] = transform.rotation ?? [0, 0, 0];
67266
+ const rotation = new Quaternion().setFromEuler(new Euler(toRadians(x4), sign * toRadians(y5), sign * toRadians(z4), "XYZ"));
67267
+ const translation = new Vector3(...transform.translation ?? [0, 0, 0]).clampScalar(-80, 80);
67268
+ translation.x *= sign;
67269
+ const scale = new Vector3(...transform.scale ?? [1, 1, 1]).clampScalar(-4, 4);
67270
+ return new Matrix4().compose(translation, rotation, scale);
67271
+ }
67272
+ static apply(geometry, matrix) {
67273
+ geometry.applyMatrix4(matrix);
67274
+ if (matrix.determinant() < 0) {
67275
+ if (!geometry.index) geometry.setIndex(Array.from({ length: geometry.getAttribute("position").count }, (_4, i4) => i4));
67276
+ const index = geometry.index;
67277
+ for (let i4 = 0; i4 < index.count; i4 += 3) {
67278
+ const second = index.getX(i4 + 1);
67279
+ index.setX(i4 + 1, index.getX(i4 + 2));
67280
+ index.setX(i4 + 2, second);
67281
+ }
67282
+ index.needsUpdate = true;
67283
+ }
67284
+ }
67285
+ };
67286
+
67219
67287
  // src/model/ModelMerger.ts
67220
67288
  var ModelMerger = class {
67221
67289
  static async mergeWithParents(model) {
67222
67290
  const models = await this.collectAllParents(model);
67223
67291
  let merged = {};
67224
- for (let parentModel of models) {
67225
- merged = import_ts_deepmerge.default.withOptions({ mergeArrays: false }, merged, parentModel);
67292
+ for (const source of [...models, model]) {
67293
+ const inheritedDisplay = merged.display;
67294
+ merged = import_ts_deepmerge.default.withOptions({ mergeArrays: false }, merged, source);
67295
+ if (source.display) {
67296
+ merged.display = { ...inheritedDisplay, ...DisplayTransforms.withHandFallbacks(source.display) };
67297
+ }
67226
67298
  }
67227
- merged = import_ts_deepmerge.default.withOptions({ mergeArrays: false }, merged, model);
67228
67299
  merged.hierarchy = models.map((m4) => m4.parent).filter((p15) => `${p15}`);
67229
67300
  merged.hierarchy.push(`${merged.parent}`);
67230
67301
  return merged;
@@ -79288,23 +79359,6 @@ return ${compiler2.callType("value", tagType)}
79288
79359
  init_buffer2();
79289
79360
  init_process2();
79290
79361
 
79291
- // src/model/DisplayPosition.ts
79292
- init_dirname();
79293
- init_buffer2();
79294
- init_process2();
79295
- var DisplayPosition = /* @__PURE__ */ ((DisplayPosition2) => {
79296
- DisplayPosition2["THIRDPERSON_RIGHTHAND"] = "thirdperson_righthand";
79297
- DisplayPosition2["THIRDPERSON_LEFTHAND"] = "thirdperson_lefthand";
79298
- DisplayPosition2["FIRSTPERSON_RIGHTHAND"] = "firstperson_righthand";
79299
- DisplayPosition2["FIRSTPERSON_LEFTHAND"] = "firstperson_lefthand";
79300
- DisplayPosition2["GUI"] = "gui";
79301
- DisplayPosition2["HEAD"] = "head";
79302
- DisplayPosition2["GROUND"] = "ground";
79303
- DisplayPosition2["FIXED"] = "fixed";
79304
- return DisplayPosition2;
79305
- })(DisplayPosition || {});
79306
- var DISPLAY_POSITIONS = Object.values(DisplayPosition);
79307
-
79308
79362
  // src/model/ElementFace.ts
79309
79363
  init_dirname();
79310
79364
  init_buffer2();
@@ -79368,6 +79422,96 @@ return ${compiler2.callType("value", tagType)}
79368
79422
  init_buffer2();
79369
79423
  init_process2();
79370
79424
 
79425
+ // src/model/block/BlockTints.ts
79426
+ init_dirname();
79427
+ init_buffer2();
79428
+ init_process2();
79429
+
79430
+ // src/model/block/blockTints.json
79431
+ var blockTints_default = {
79432
+ "minecraft:large_fern": { source: "grass" },
79433
+ "minecraft:tall_grass": { source: "grass" },
79434
+ "minecraft:grass_block": { source: "grass" },
79435
+ "minecraft:fern": { source: "grass" },
79436
+ "minecraft:grass": { source: "grass" },
79437
+ "minecraft:short_grass": { source: "grass" },
79438
+ "minecraft:potted_fern": { source: "grass" },
79439
+ "minecraft:bush": { source: "grass" },
79440
+ "minecraft:pink_petals": { source: "grass", untinted: [0] },
79441
+ "minecraft:wildflowers": { source: "grass", untinted: [0] },
79442
+ "minecraft:spruce_leaves": { source: "constant", color: 6396257 },
79443
+ "minecraft:birch_leaves": { source: "constant", color: 8431445 },
79444
+ "minecraft:oak_leaves": { source: "constant", color: 4764952 },
79445
+ "minecraft:jungle_leaves": { source: "constant", color: 4764952 },
79446
+ "minecraft:acacia_leaves": { source: "constant", color: 4764952 },
79447
+ "minecraft:dark_oak_leaves": { source: "constant", color: 4764952 },
79448
+ "minecraft:vine": { source: "constant", color: 4764952 },
79449
+ "minecraft:mangrove_leaves": { source: "constant", color: 4764952 },
79450
+ "minecraft:leaf_litter": { source: "constant", color: 6044722 },
79451
+ "minecraft:water_cauldron": { source: "constant", color: 4159204 },
79452
+ "minecraft:redstone_wire": { source: "redstone" },
79453
+ "minecraft:attached_melon_stem": { source: "constant", color: 14731036 },
79454
+ "minecraft:attached_pumpkin_stem": { source: "constant", color: 14731036 },
79455
+ "minecraft:melon_stem": { source: "stem" },
79456
+ "minecraft:pumpkin_stem": { source: "stem" },
79457
+ "minecraft:lily_pad": { source: "constant", color: 7455580 }
79458
+ };
79459
+
79460
+ // src/model/block/BlockTints.ts
79461
+ var rules = blockTints_default;
79462
+ var BlockTints = class {
79463
+ /** Resolves block preview colors without biome context; explicit tints take precedence. */
79464
+ static async get(key, state, model, tints) {
79465
+ const rule = key && rules[key.toNamespacedString()];
79466
+ if (!key || !rule) return tints;
79467
+ const indices = /* @__PURE__ */ new Set();
79468
+ for (const element of model.elements ?? []) {
79469
+ for (const face of Object.values(element.faces)) {
79470
+ const index = face?.tintindex;
79471
+ if (index !== void 0 && index >= 0 && tints?.[index] === void 0 && !rule.untinted?.includes(index)) {
79472
+ indices.add(index);
79473
+ }
79474
+ }
79475
+ }
79476
+ if (!indices.size) return tints;
79477
+ let color2;
79478
+ switch (rule.source) {
79479
+ case "constant":
79480
+ color2 = rule.color;
79481
+ break;
79482
+ case "grass":
79483
+ color2 = await this.grassColor(key);
79484
+ break;
79485
+ case "redstone": {
79486
+ const power = Number(state.power ?? 0) / 15;
79487
+ const red = power * 0.6 + (power > 0 ? 0.4 : 0.3);
79488
+ const green = Math.max(0, power * power * 0.7 - 0.5);
79489
+ const blue = Math.max(0, power * power * 0.6 - 0.7);
79490
+ color2 = Math.floor(red * 255) << 16 | Math.floor(green * 255) << 8 | Math.floor(blue * 255);
79491
+ break;
79492
+ }
79493
+ case "stem": {
79494
+ const age = Number(state.age ?? 0);
79495
+ color2 = age * 32 << 16 | 255 - age * 8 << 8 | age * 4;
79496
+ break;
79497
+ }
79498
+ }
79499
+ return { ...Object.fromEntries([...indices].map((index) => [index, color2])), ...tints };
79500
+ }
79501
+ static async grassColor(origin) {
79502
+ const key = AssetKey.parse("textures", "minecraft:colormap/grass", origin);
79503
+ return await Caching.blockTintCache.get(key.serialize(), async () => {
79504
+ const image = await ModelTextures.get(key);
79505
+ if (!image) throw new MineRenderError(`Missing grass colormap: ${key.toNamespacedString()}`);
79506
+ if (image.width !== 256 || image.height !== 256) {
79507
+ throw new MineRenderError("Grass colormaps must be 256 \xD7 256 pixels");
79508
+ }
79509
+ const [red, green, blue] = image.data.getImageData(127, 127, 1, 1).data;
79510
+ return red << 16 | green << 8 | blue;
79511
+ });
79512
+ }
79513
+ };
79514
+
79371
79515
  // src/model/block/scene/index.ts
79372
79516
  init_dirname();
79373
79517
  init_buffer2();
@@ -79949,6 +80093,7 @@ return ${compiler2.callType("value", tagType)}
79949
80093
  createMeshes(force = false) {
79950
80094
  if (this.meshesCreated && !force) return;
79951
80095
  const mat = Materials.MISSING_TEXTURE;
80096
+ const displayTransform = this.options.displayPosition ? DisplayTransforms.getMatrix(this.originalModel.display, this.options.displayPosition) : void 0;
79952
80097
  let allGeos = [];
79953
80098
  if (this.atlas) {
79954
80099
  if (this.atlas.model.elements) {
@@ -79977,6 +80122,7 @@ return ${compiler2.callType("value", tagType)}
79977
80122
  applyElementRotation(el.rotation, elGeo);
79978
80123
  }
79979
80124
  elGeo.applyMatrix4(new Matrix4().makeTranslation(-8, -8, -8));
80125
+ if (displayTransform) DisplayTransforms.apply(elGeo, displayTransform);
79980
80126
  if (this.options.mergeMeshes) {
79981
80127
  allGeos.push(elGeo);
79982
80128
  } else {
@@ -79998,6 +80144,7 @@ return ${compiler2.callType("value", tagType)}
79998
80144
  combinedGeo = mergeBufferGeometries(allGeos);
79999
80145
  } else {
80000
80146
  combinedGeo = new BoxGeometry(16, 16, 16);
80147
+ if (displayTransform) DisplayTransforms.apply(combinedGeo, displayTransform);
80001
80148
  }
80002
80149
  combinedGeo.computeBoundingBox();
80003
80150
  let mesh;
@@ -80215,6 +80362,7 @@ return ${compiler2.callType("value", tagType)}
80215
80362
  const model = await Models.getMerged(AssetKey.parse("models", variant.model));
80216
80363
  const options = {
80217
80364
  ...this.options,
80365
+ tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints) : this.options.tints,
80218
80366
  uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0) ? [rotation.x, rotation.y, rotation.z] : void 0
80219
80367
  };
80220
80368
  const obj = await this.scene.addModel(model, options);
@@ -81329,7 +81477,8 @@ return ${compiler2.callType("value", tagType)}
81329
81477
  console.log("instanceMeshes + key");
81330
81478
  let key = asset.key.serialize();
81331
81479
  if (isModelObject(obj)) {
81332
- const { uvLockRotation, tints } = obj.options;
81480
+ const { displayPosition, uvLockRotation, tints } = obj.options;
81481
+ if (displayPosition) key += `|display:${displayPosition}`;
81333
81482
  if (uvLockRotation) key += `|uvlock:${uvLockRotation.join(",")}`;
81334
81483
  const palette = Object.entries(tints ?? {}).sort(([a4], [b4]) => Number(a4) - Number(b4));
81335
81484
  if (palette.length) key += `|tints:${JSON.stringify(palette)}`;