minerender 2.1.0-alpha.94 → 2.1.0-alpha.95

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.
@@ -23257,7 +23257,7 @@ function matchesCondition(condition, state) {
23257
23257
  return typeof value === "string" && state[key] !== void 0 && value.split("|").includes(`${state[key]}`);
23258
23258
  });
23259
23259
  }
23260
- var BlockStateResolver = class {
23260
+ var BlockStateResolver = class _BlockStateResolver {
23261
23261
  /** Loads vanilla property defaults, falling back to preview values inferred from the blockstate file. */
23262
23262
  static async defaults(blockState3) {
23263
23263
  const defaults = blockState3.key ? await BlockStates.getDefaultState(blockState3.key) : void 0;
@@ -23280,7 +23280,7 @@ var BlockStateResolver = class {
23280
23280
  }
23281
23281
  /** Selects matching models. Supply `choose` to control selection within each alternatives array. */
23282
23282
  static select(blockState3, state, choose = this.choose) {
23283
- return this.matching(blockState3, state).map(choose);
23283
+ return this.matching(blockState3, state).map((variants) => choose(variants));
23284
23284
  }
23285
23285
  /** Returns matching model groups before choosing weighted alternatives. */
23286
23286
  static matching(blockState3, state) {
@@ -23306,8 +23306,8 @@ var BlockStateResolver = class {
23306
23306
  }
23307
23307
  return out;
23308
23308
  }
23309
- /** Selects a random alternative using positive integer weights, each defaulting to 1. */
23310
- static choose(variants) {
23309
+ /** Selects by positive integer weights (default 1); world block coordinates make the choice repeatable. */
23310
+ static choose(variants, position) {
23311
23311
  if (!Array.isArray(variants)) return variants;
23312
23312
  if (!variants.length) throw new MineRenderError("Blockstate variant arrays must not be empty");
23313
23313
  const total = variants.reduce((sum, variant) => {
@@ -23317,13 +23317,29 @@ var BlockStateResolver = class {
23317
23317
  }
23318
23318
  return sum + weight;
23319
23319
  }, 0);
23320
- let choice = Math.random() * total;
23320
+ let choice = position === void 0 ? Math.random() * total : _BlockStateResolver.positionSample(position, total);
23321
23321
  for (const variant of variants) {
23322
23322
  choice -= variant.weight ?? 1;
23323
23323
  if (choice < 0) return variant;
23324
23324
  }
23325
23325
  return variants[variants.length - 1];
23326
23326
  }
23327
+ static positionSample(position, bound) {
23328
+ if (bound > 2147483647) {
23329
+ throw new MineRenderError("Position-based blockstate variant total weight must not exceed 2147483647");
23330
+ }
23331
+ let mixed = BigInt(Math.imul(position[0], 3129871)) ^ BigInt(position[2]) * 116129781n ^ BigInt(position[1]);
23332
+ mixed = BigInt.asIntN(64, mixed * mixed * 42317861n + mixed * 11n) >> 16n;
23333
+ let seed = (mixed ^ 0x5deece66dn) & 0xffffffffffffn;
23334
+ let bits, value;
23335
+ do {
23336
+ seed = seed * 0x5deece66dn + 11n & 0xffffffffffffn;
23337
+ bits = Number(seed >> 17n);
23338
+ if ((bound & bound - 1) === 0) return Number(BigInt(bound) * BigInt(bits) >> 31n);
23339
+ value = bits % bound;
23340
+ } while ((bits - value + bound - 1 | 0) < 0);
23341
+ return value;
23342
+ }
23327
23343
  /** Converts blockstate rotations in degrees into the Euler rotation used by model rendering. */
23328
23344
  static rotation(variant) {
23329
23345
  const rotation = new Euler9();
@@ -23443,6 +23459,7 @@ var BlockObject = class _BlockObject extends SceneObject {
23443
23459
  this._entityPlacement = new Matrix411();
23444
23460
  this._entityGeneration = 0;
23445
23461
  this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
23462
+ this.variantPosition = options?.variantPosition ? [...options.variantPosition] : void 0;
23446
23463
  }
23447
23464
  static {
23448
23465
  this.DEFAULT_OPTIONS = (0, import_ts_deepmerge6.default)({}, ModelObject.DEFAULT_OPTIONS, {
@@ -23684,7 +23701,7 @@ var BlockObject = class _BlockObject extends SceneObject {
23684
23701
  return !!(await Models.getMerged(modelKey))?.elements?.length;
23685
23702
  }
23686
23703
  getSingleVariant(variants) {
23687
- return BlockStateResolver.choose(variants);
23704
+ return BlockStateResolver.choose(variants, this.variantPosition);
23688
23705
  }
23689
23706
  // @deprecated
23690
23707
  async createAVariant(variants, instanceInfo) {
@@ -29583,13 +29600,14 @@ var SectionModels = class {
29583
29600
  if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("maxAtlasSize must be a positive integer");
29584
29601
  }
29585
29602
  /** Returns templates for the matched parts, or `undefined` when the block needs an individual render object. */
29586
- async get(blockState3, properties = {}) {
29603
+ async get(blockState3, properties = {}, position) {
29604
+ const variantPosition = position ? [...position] : void 0;
29587
29605
  let states = this.states.get(blockState3);
29588
29606
  if (!states) this.states.set(blockState3, states = /* @__PURE__ */ new Map());
29589
29607
  const key = JSON.stringify(Object.entries(properties).sort(([a], [b]) => a.localeCompare(b)));
29590
29608
  const prepared = await cached(states, key, () => this.prepare(blockState3, properties));
29591
29609
  if (!prepared) return void 0;
29592
- return prepared.groups.map((group) => prepared.templates.get(BlockStateResolver.choose(group)));
29610
+ return prepared.groups.map((group) => prepared.templates.get(BlockStateResolver.choose(group, variantPosition)));
29593
29611
  }
29594
29612
  async prepare(blockState3, properties) {
29595
29613
  const state = { ...await BlockStateResolver.defaults(blockState3), ...properties };
@@ -30379,7 +30397,8 @@ var Chunk = class _Chunk {
30379
30397
  this.data.set(index, void 0);
30380
30398
  continue;
30381
30399
  }
30382
- const templates = perBlock ? void 0 : await this.sectionModels.get(blockState3, stored.properties);
30400
+ const variantPosition = worldPos.toArray();
30401
+ const templates = perBlock ? void 0 : await this.sectionModels.get(blockState3, stored.properties, variantPosition);
30383
30402
  if (templates) {
30384
30403
  this.sectionBlocks.set(index, templates.map((template) => ({ index, template, cullMask: 0 })));
30385
30404
  this.meshDirty = true;
@@ -30388,7 +30407,8 @@ var Chunk = class _Chunk {
30388
30407
  mergeMeshes: true,
30389
30408
  instanceMeshes: true,
30390
30409
  maxInstanceCount: 2e3,
30391
- initialState: stored.properties
30410
+ initialState: stored.properties,
30411
+ variantPosition
30392
30412
  });
30393
30413
  object3.setPosition(MineRenderWorld.worldToScenePosition(worldPos));
30394
30414
  }