minerender 2.1.0-alpha.39 → 2.1.0-alpha.40

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.
@@ -1137,6 +1137,8 @@ declare class BlockObject extends SceneObject {
1137
1137
  }
1138
1138
  interface BlockObjectOptions extends ModelObjectOptions {
1139
1139
  applyDefaultState: boolean;
1140
+ /** Properties applied before model creation, overriding defaults when applyDefaultState is enabled. */
1141
+ initialState?: BlockStateProperties;
1140
1142
  }
1141
1143
  declare function isBlockObject(obj: any): obj is BlockObject;
1142
1144
 
@@ -1807,8 +1809,8 @@ declare class Chunk {
1807
1809
  /**
1808
1810
  * Set a block at integer chunk-local coordinates from 0 to 15.
1809
1811
  */
1810
- setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3): Promise<Maybe<BlockInfo>>;
1811
- clear(): Promise<void>;
1812
+ setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3, onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<Maybe<BlockInfo>>;
1813
+ clear(onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<void>;
1812
1814
  dispose(): Promise<void>;
1813
1815
  static isAir(block: Maybe<Block>): boolean;
1814
1816
  static chunkPosToBlockIndex(pos: Vector3): number;
@@ -1828,7 +1830,9 @@ declare class MineRenderWorld {
1828
1830
  setBlockAt(x: number, y: number, z: number, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1829
1831
  setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1830
1832
  setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1833
+ private placeBlock;
1831
1834
  placeMultiBlock(multiblock: MultiBlockStructure, useBatches?: boolean, executor?: BatchedExecutor): Promise<void>;
1835
+ private placeBlocks;
1832
1836
  /** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
1833
1837
  placeChunk(chunk: AnvilChunk, executor?: BatchedExecutor): Promise<void>;
1834
1838
  clear(): Promise<void>;
@@ -1137,6 +1137,8 @@ declare class BlockObject extends SceneObject {
1137
1137
  }
1138
1138
  interface BlockObjectOptions extends ModelObjectOptions {
1139
1139
  applyDefaultState: boolean;
1140
+ /** Properties applied before model creation, overriding defaults when applyDefaultState is enabled. */
1141
+ initialState?: BlockStateProperties;
1140
1142
  }
1141
1143
  declare function isBlockObject(obj: any): obj is BlockObject;
1142
1144
 
@@ -1807,8 +1809,8 @@ declare class Chunk {
1807
1809
  /**
1808
1810
  * Set a block at integer chunk-local coordinates from 0 to 15.
1809
1811
  */
1810
- setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3): Promise<Maybe<BlockInfo>>;
1811
- clear(): Promise<void>;
1812
+ setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3, onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<Maybe<BlockInfo>>;
1813
+ clear(onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<void>;
1812
1814
  dispose(): Promise<void>;
1813
1815
  static isAir(block: Maybe<Block>): boolean;
1814
1816
  static chunkPosToBlockIndex(pos: Vector3): number;
@@ -1828,7 +1830,9 @@ declare class MineRenderWorld {
1828
1830
  setBlockAt(x: number, y: number, z: number, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1829
1831
  setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1830
1832
  setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1833
+ private placeBlock;
1831
1834
  placeMultiBlock(multiblock: MultiBlockStructure, useBatches?: boolean, executor?: BatchedExecutor): Promise<void>;
1835
+ private placeBlocks;
1832
1836
  /** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
1833
1837
  placeChunk(chunk: AnvilChunk, executor?: BatchedExecutor): Promise<void>;
1834
1838
  clear(): Promise<void>;
@@ -4870,19 +4870,19 @@ var BlockObject = class _BlockObject extends SceneObject {
4870
4870
  for (let k in defaultState) {
4871
4871
  state[k] = defaultState[k].default;
4872
4872
  }
4873
- await this.setState(state);
4873
+ this._setState(state);
4874
4874
  } else {
4875
4875
  if (this.blockState.variants) {
4876
- await this.setState(Object.keys(this.blockState.variants)[0]);
4876
+ this._setState(Object.keys(this.blockState.variants)[0]);
4877
4877
  } else if (this.blockState.multipart) {
4878
4878
  const condition = this.blockState.multipart.map((part) => part.when).find((when) => when !== void 0 && Object.values(when).every((value) => typeof value === "string"));
4879
4879
  const state = Object.fromEntries(Object.entries(condition ?? {}).map(([key, value]) => [key, value.split("|")[0]]));
4880
- await this.setState(state);
4880
+ this._setState(state);
4881
4881
  }
4882
4882
  }
4883
- } else {
4884
- await this.recreateModels();
4885
4883
  }
4884
+ if (this.options.initialState !== void 0) this._setState(this.options.initialState);
4885
+ await this.recreateModels();
4886
4886
  }
4887
4887
  dispose() {
4888
4888
  this.clearModels();
@@ -9563,12 +9563,26 @@ var MineRenderWorld = class {
9563
9563
  if (isTripleArray(posOrX)) {
9564
9564
  return this.setBlockAt(new import_three25.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
9565
9565
  }
9566
- this.validatePosBounds(posOrX);
9567
- const value = yOrBlock;
9568
- const chunk = Chunk.isAir(value) ? this.getChunkAt(posOrX) : this.getOrCreateChunkAt(posOrX);
9569
- return chunk?.setBlockAt(posOrX, value);
9566
+ return this.placeBlock(posOrX, yOrBlock);
9567
+ }
9568
+ async placeBlock(pos, value, onBlocksChanged) {
9569
+ this.validatePosBounds(pos);
9570
+ const chunk = Chunk.isAir(value) ? this.getChunkAt(pos) : this.getOrCreateChunkAt(pos);
9571
+ return chunk?.setBlockInChunkAt(chunk.worldPosToChunkPos(pos), value, pos, onBlocksChanged);
9570
9572
  }
9571
9573
  async placeMultiBlock(multiblock, useBatches = true, executor) {
9574
+ const changes = /* @__PURE__ */ new Map();
9575
+ try {
9576
+ await this.placeBlocks(multiblock, useBatches, executor, changes);
9577
+ } finally {
9578
+ await this.updateCulling([...changes.values()]);
9579
+ }
9580
+ }
9581
+ async placeBlocks(multiblock, useBatches, executor, changes) {
9582
+ const collect = async (positions2) => {
9583
+ for (const pos of positions2) changes.set(pos.toArray().join(","), pos);
9584
+ };
9585
+ const place = (block) => this.placeBlock(new import_three25.Vector3(...block.position), block, collect);
9572
9586
  const keys = /* @__PURE__ */ new Map();
9573
9587
  for (const block of multiblock.blocks) {
9574
9588
  if (Chunk.isAir(block)) continue;
@@ -9577,7 +9591,7 @@ var MineRenderWorld = class {
9577
9591
  }
9578
9592
  await BlockStates.getAll(keys.values());
9579
9593
  if (!useBatches) {
9580
- for (const block of multiblock.blocks) await this.setBlockAt(block.position, block);
9594
+ for (const block of multiblock.blocks) await place(block);
9581
9595
  return;
9582
9596
  }
9583
9597
  const positions = /* @__PURE__ */ new Map();
@@ -9593,7 +9607,7 @@ var MineRenderWorld = class {
9593
9607
  for (let i = 0; i < groups.length; i += queue.batch) {
9594
9608
  const results = await Promise.allSettled(groups.slice(i, i + queue.batch).map(
9595
9609
  (blocks) => queue.submit(async () => {
9596
- for (const block of blocks) await this.setBlockAt(block.position, block);
9610
+ for (const block of blocks) await place(block);
9597
9611
  })
9598
9612
  ));
9599
9613
  const failure = results.find((result) => result.status === "rejected");
@@ -9605,25 +9619,32 @@ var MineRenderWorld = class {
9605
9619
  }
9606
9620
  /** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
9607
9621
  async placeChunk(chunk, executor) {
9608
- const previous = [...this._chunks.entries()].filter(([, section]) => section.x === chunk.x && section.z === chunk.z);
9609
- for (const [key, section] of previous) {
9610
- this._chunks.delete(key);
9611
- await section.dispose();
9612
- }
9613
- for (const section of chunk.sections) {
9614
- const blocks = [];
9615
- for (let index = 0; index < 4096; index++) {
9616
- const block = section.data.get(index);
9617
- if (block) blocks.push({
9618
- ...block,
9619
- position: [
9620
- chunk.x * 16 + index % 16,
9621
- section.y * 16 + Math.floor(index / 256),
9622
- chunk.z * 16 + Math.floor(index / 16) % 16
9623
- ]
9622
+ const changes = /* @__PURE__ */ new Map();
9623
+ try {
9624
+ const previous = [...this._chunks.entries()].filter(([, section]) => section.x === chunk.x && section.z === chunk.z);
9625
+ for (const [key, section] of previous) {
9626
+ this._chunks.delete(key);
9627
+ await section.clear(async (positions) => {
9628
+ for (const pos of positions) changes.set(pos.toArray().join(","), pos);
9624
9629
  });
9625
9630
  }
9626
- await this.placeMultiBlock({ size: [16, 16, 16], blocks }, true, executor);
9631
+ for (const section of chunk.sections) {
9632
+ const blocks = [];
9633
+ for (let index = 0; index < 4096; index++) {
9634
+ const block = section.data.get(index);
9635
+ if (block) blocks.push({
9636
+ ...block,
9637
+ position: [
9638
+ chunk.x * 16 + index % 16,
9639
+ section.y * 16 + Math.floor(index / 256),
9640
+ chunk.z * 16 + Math.floor(index / 16) % 16
9641
+ ]
9642
+ });
9643
+ }
9644
+ await this.placeBlocks({ size: [16, 16, 16], blocks }, true, executor, changes);
9645
+ }
9646
+ } finally {
9647
+ await this.updateCulling([...changes.values()]);
9627
9648
  }
9628
9649
  }
9629
9650
  async clear() {
@@ -9746,7 +9767,7 @@ var Chunk = class _Chunk {
9746
9767
  /**
9747
9768
  * Set a block at integer chunk-local coordinates from 0 to 15.
9748
9769
  */
9749
- async setBlockInChunkAt(pos, block, worldPos) {
9770
+ async setBlockInChunkAt(pos, block, worldPos, onBlocksChanged = this.onBlocksChanged) {
9750
9771
  if (typeof worldPos === "undefined") {
9751
9772
  worldPos = this.chunkPosToWorldPos(pos);
9752
9773
  }
@@ -9767,9 +9788,9 @@ var Chunk = class _Chunk {
9767
9788
  object = await this.scene.addBlock(blockState, {
9768
9789
  mergeMeshes: true,
9769
9790
  instanceMeshes: true,
9770
- maxInstanceCount: 2e3
9791
+ maxInstanceCount: 2e3,
9792
+ initialState: stored.properties
9771
9793
  });
9772
- if (stored.properties) await object.setState(stored.properties);
9773
9794
  object.setPosition(MineRenderWorld.worldToScenePosition(worldPos));
9774
9795
  const info = { get block() {
9775
9796
  return readBlock();
@@ -9781,17 +9802,17 @@ var Chunk = class _Chunk {
9781
9802
  object?.removeFromScene();
9782
9803
  throw error;
9783
9804
  } finally {
9784
- await this.onBlocksChanged?.([worldPos]);
9805
+ await onBlocksChanged?.([worldPos]);
9785
9806
  }
9786
9807
  }
9787
- async clear() {
9808
+ async clear(onBlocksChanged = this.onBlocksChanged) {
9788
9809
  const positions = [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
9789
9810
  new import_three26.Vector3(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
9790
9811
  ));
9791
9812
  for (const info of this.renderedBlocks.values()) info.object.removeFromScene();
9792
9813
  this.renderedBlocks.clear();
9793
9814
  this.data.clear();
9794
- await this.onBlocksChanged?.(positions);
9815
+ await onBlocksChanged?.(positions);
9795
9816
  }
9796
9817
  async dispose() {
9797
9818
  await this.clear();