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.
@@ -1136,6 +1136,8 @@ declare class BlockObject extends SceneObject {
1136
1136
  }
1137
1137
  interface BlockObjectOptions extends ModelObjectOptions {
1138
1138
  applyDefaultState: boolean;
1139
+ /** Properties applied before model creation, overriding defaults when applyDefaultState is enabled. */
1140
+ initialState?: BlockStateProperties;
1139
1141
  }
1140
1142
  declare function isBlockObject(obj: any): obj is BlockObject;
1141
1143
 
@@ -1806,8 +1808,8 @@ declare class Chunk {
1806
1808
  /**
1807
1809
  * Set a block at integer chunk-local coordinates from 0 to 15.
1808
1810
  */
1809
- setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3): Promise<Maybe<BlockInfo>>;
1810
- clear(): Promise<void>;
1811
+ setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3, onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<Maybe<BlockInfo>>;
1812
+ clear(onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<void>;
1811
1813
  dispose(): Promise<void>;
1812
1814
  static isAir(block: Maybe<Block>): boolean;
1813
1815
  static chunkPosToBlockIndex(pos: Vector3): number;
@@ -1827,7 +1829,9 @@ declare class MineRenderWorld {
1827
1829
  setBlockAt(x: number, y: number, z: number, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1828
1830
  setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1829
1831
  setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1832
+ private placeBlock;
1830
1833
  placeMultiBlock(multiblock: MultiBlockStructure, useBatches?: boolean, executor?: BatchedExecutor): Promise<void>;
1834
+ private placeBlocks;
1831
1835
  /** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
1832
1836
  placeChunk(chunk: AnvilChunk, executor?: BatchedExecutor): Promise<void>;
1833
1837
  clear(): Promise<void>;
@@ -1136,6 +1136,8 @@ declare class BlockObject extends SceneObject {
1136
1136
  }
1137
1137
  interface BlockObjectOptions extends ModelObjectOptions {
1138
1138
  applyDefaultState: boolean;
1139
+ /** Properties applied before model creation, overriding defaults when applyDefaultState is enabled. */
1140
+ initialState?: BlockStateProperties;
1139
1141
  }
1140
1142
  declare function isBlockObject(obj: any): obj is BlockObject;
1141
1143
 
@@ -1806,8 +1808,8 @@ declare class Chunk {
1806
1808
  /**
1807
1809
  * Set a block at integer chunk-local coordinates from 0 to 15.
1808
1810
  */
1809
- setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3): Promise<Maybe<BlockInfo>>;
1810
- clear(): Promise<void>;
1811
+ setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3, onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<Maybe<BlockInfo>>;
1812
+ clear(onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<void>;
1811
1813
  dispose(): Promise<void>;
1812
1814
  static isAir(block: Maybe<Block>): boolean;
1813
1815
  static chunkPosToBlockIndex(pos: Vector3): number;
@@ -1827,7 +1829,9 @@ declare class MineRenderWorld {
1827
1829
  setBlockAt(x: number, y: number, z: number, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1828
1830
  setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1829
1831
  setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo>>;
1832
+ private placeBlock;
1830
1833
  placeMultiBlock(multiblock: MultiBlockStructure, useBatches?: boolean, executor?: BatchedExecutor): Promise<void>;
1834
+ private placeBlocks;
1831
1835
  /** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
1832
1836
  placeChunk(chunk: AnvilChunk, executor?: BatchedExecutor): Promise<void>;
1833
1837
  clear(): Promise<void>;
@@ -4819,19 +4819,19 @@ var _BlockObject = class _BlockObject extends SceneObject {
4819
4819
  for (let k in defaultState) {
4820
4820
  state[k] = defaultState[k].default;
4821
4821
  }
4822
- await this.setState(state);
4822
+ this._setState(state);
4823
4823
  } else {
4824
4824
  if (this.blockState.variants) {
4825
- await this.setState(Object.keys(this.blockState.variants)[0]);
4825
+ this._setState(Object.keys(this.blockState.variants)[0]);
4826
4826
  } else if (this.blockState.multipart) {
4827
4827
  const condition = this.blockState.multipart.map((part) => part.when).find((when) => when !== void 0 && Object.values(when).every((value) => typeof value === "string"));
4828
4828
  const state = Object.fromEntries(Object.entries(condition ?? {}).map(([key, value]) => [key, value.split("|")[0]]));
4829
- await this.setState(state);
4829
+ this._setState(state);
4830
4830
  }
4831
4831
  }
4832
- } else {
4833
- await this.recreateModels();
4834
4832
  }
4833
+ if (this.options.initialState !== void 0) this._setState(this.options.initialState);
4834
+ await this.recreateModels();
4835
4835
  }
4836
4836
  dispose() {
4837
4837
  this.clearModels();
@@ -9514,12 +9514,26 @@ var MineRenderWorld = class {
9514
9514
  if (isTripleArray(posOrX)) {
9515
9515
  return this.setBlockAt(new import_three25.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
9516
9516
  }
9517
- this.validatePosBounds(posOrX);
9518
- const value = yOrBlock;
9519
- const chunk = Chunk.isAir(value) ? this.getChunkAt(posOrX) : this.getOrCreateChunkAt(posOrX);
9520
- return chunk?.setBlockAt(posOrX, value);
9517
+ return this.placeBlock(posOrX, yOrBlock);
9518
+ }
9519
+ async placeBlock(pos, value, onBlocksChanged) {
9520
+ this.validatePosBounds(pos);
9521
+ const chunk = Chunk.isAir(value) ? this.getChunkAt(pos) : this.getOrCreateChunkAt(pos);
9522
+ return chunk?.setBlockInChunkAt(chunk.worldPosToChunkPos(pos), value, pos, onBlocksChanged);
9521
9523
  }
9522
9524
  async placeMultiBlock(multiblock, useBatches = true, executor) {
9525
+ const changes = /* @__PURE__ */ new Map();
9526
+ try {
9527
+ await this.placeBlocks(multiblock, useBatches, executor, changes);
9528
+ } finally {
9529
+ await this.updateCulling([...changes.values()]);
9530
+ }
9531
+ }
9532
+ async placeBlocks(multiblock, useBatches, executor, changes) {
9533
+ const collect = async (positions2) => {
9534
+ for (const pos of positions2) changes.set(pos.toArray().join(","), pos);
9535
+ };
9536
+ const place = (block) => this.placeBlock(new import_three25.Vector3(...block.position), block, collect);
9523
9537
  const keys = /* @__PURE__ */ new Map();
9524
9538
  for (const block of multiblock.blocks) {
9525
9539
  if (Chunk.isAir(block)) continue;
@@ -9528,7 +9542,7 @@ var MineRenderWorld = class {
9528
9542
  }
9529
9543
  await BlockStates.getAll(keys.values());
9530
9544
  if (!useBatches) {
9531
- for (const block of multiblock.blocks) await this.setBlockAt(block.position, block);
9545
+ for (const block of multiblock.blocks) await place(block);
9532
9546
  return;
9533
9547
  }
9534
9548
  const positions = /* @__PURE__ */ new Map();
@@ -9544,7 +9558,7 @@ var MineRenderWorld = class {
9544
9558
  for (let i = 0; i < groups.length; i += queue.batch) {
9545
9559
  const results = await Promise.allSettled(groups.slice(i, i + queue.batch).map(
9546
9560
  (blocks) => queue.submit(async () => {
9547
- for (const block of blocks) await this.setBlockAt(block.position, block);
9561
+ for (const block of blocks) await place(block);
9548
9562
  })
9549
9563
  ));
9550
9564
  const failure = results.find((result) => result.status === "rejected");
@@ -9556,25 +9570,32 @@ var MineRenderWorld = class {
9556
9570
  }
9557
9571
  /** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
9558
9572
  async placeChunk(chunk, executor) {
9559
- const previous = [...this._chunks.entries()].filter(([, section]) => section.x === chunk.x && section.z === chunk.z);
9560
- for (const [key, section] of previous) {
9561
- this._chunks.delete(key);
9562
- await section.dispose();
9563
- }
9564
- for (const section of chunk.sections) {
9565
- const blocks = [];
9566
- for (let index = 0; index < 4096; index++) {
9567
- const block = section.data.get(index);
9568
- if (block) blocks.push({
9569
- ...block,
9570
- position: [
9571
- chunk.x * 16 + index % 16,
9572
- section.y * 16 + Math.floor(index / 256),
9573
- chunk.z * 16 + Math.floor(index / 16) % 16
9574
- ]
9573
+ const changes = /* @__PURE__ */ new Map();
9574
+ try {
9575
+ const previous = [...this._chunks.entries()].filter(([, section]) => section.x === chunk.x && section.z === chunk.z);
9576
+ for (const [key, section] of previous) {
9577
+ this._chunks.delete(key);
9578
+ await section.clear(async (positions) => {
9579
+ for (const pos of positions) changes.set(pos.toArray().join(","), pos);
9575
9580
  });
9576
9581
  }
9577
- await this.placeMultiBlock({ size: [16, 16, 16], blocks }, true, executor);
9582
+ for (const section of chunk.sections) {
9583
+ const blocks = [];
9584
+ for (let index = 0; index < 4096; index++) {
9585
+ const block = section.data.get(index);
9586
+ if (block) blocks.push({
9587
+ ...block,
9588
+ position: [
9589
+ chunk.x * 16 + index % 16,
9590
+ section.y * 16 + Math.floor(index / 256),
9591
+ chunk.z * 16 + Math.floor(index / 16) % 16
9592
+ ]
9593
+ });
9594
+ }
9595
+ await this.placeBlocks({ size: [16, 16, 16], blocks }, true, executor, changes);
9596
+ }
9597
+ } finally {
9598
+ await this.updateCulling([...changes.values()]);
9578
9599
  }
9579
9600
  }
9580
9601
  async clear() {
@@ -9697,7 +9718,7 @@ var Chunk = class _Chunk {
9697
9718
  /**
9698
9719
  * Set a block at integer chunk-local coordinates from 0 to 15.
9699
9720
  */
9700
- async setBlockInChunkAt(pos, block, worldPos) {
9721
+ async setBlockInChunkAt(pos, block, worldPos, onBlocksChanged = this.onBlocksChanged) {
9701
9722
  if (typeof worldPos === "undefined") {
9702
9723
  worldPos = this.chunkPosToWorldPos(pos);
9703
9724
  }
@@ -9718,9 +9739,9 @@ var Chunk = class _Chunk {
9718
9739
  object = await this.scene.addBlock(blockState, {
9719
9740
  mergeMeshes: true,
9720
9741
  instanceMeshes: true,
9721
- maxInstanceCount: 2e3
9742
+ maxInstanceCount: 2e3,
9743
+ initialState: stored.properties
9722
9744
  });
9723
- if (stored.properties) await object.setState(stored.properties);
9724
9745
  object.setPosition(MineRenderWorld.worldToScenePosition(worldPos));
9725
9746
  const info = { get block() {
9726
9747
  return readBlock();
@@ -9732,17 +9753,17 @@ var Chunk = class _Chunk {
9732
9753
  object?.removeFromScene();
9733
9754
  throw error;
9734
9755
  } finally {
9735
- await this.onBlocksChanged?.([worldPos]);
9756
+ await onBlocksChanged?.([worldPos]);
9736
9757
  }
9737
9758
  }
9738
- async clear() {
9759
+ async clear(onBlocksChanged = this.onBlocksChanged) {
9739
9760
  const positions = [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
9740
9761
  new import_three26.Vector3(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
9741
9762
  ));
9742
9763
  for (const info of this.renderedBlocks.values()) info.object.removeFromScene();
9743
9764
  this.renderedBlocks.clear();
9744
9765
  this.data.clear();
9745
- await this.onBlocksChanged?.(positions);
9766
+ await onBlocksChanged?.(positions);
9746
9767
  }
9747
9768
  async dispose() {
9748
9769
  await this.clear();