minerender 2.1.0-alpha.62 → 2.1.0-alpha.64

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.
@@ -1054,6 +1054,7 @@ interface Instanceable {
1054
1054
  isInstanceActive(index: number, reference: InstanceReference<Instanceable>): boolean;
1055
1055
  getMatrixAt(index: number, matrix?: Matrix4): Matrix4;
1056
1056
  setMatrixAt(index: number, matrix: Matrix4): void;
1057
+ setInstanceVisibleAt(index: number, visible: boolean): void;
1057
1058
  setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3): void;
1058
1059
  setPositionAt(index: number, position: Vector3): void;
1059
1060
  getPositionAt(index: number, vector?: Vector3): Vector3;
@@ -1075,6 +1076,7 @@ declare class InstanceReference<T extends Instanceable> implements Transformable
1075
1076
  dispose(): void;
1076
1077
  getMatrix(matrix?: Matrix4): Matrix4;
1077
1078
  setMatrix(matrix: Matrix4): void;
1079
+ setVisible(visible: boolean): void;
1078
1080
  setPositionRotationScale(position?: Vector3, rotation?: Euler, scale?: Vector3): void;
1079
1081
  setPosition(position: Vector3): void;
1080
1082
  getPosition(): Vector3;
@@ -1365,6 +1367,7 @@ declare class SceneObject extends Object3D<Object3DEventMap & {
1365
1367
  protected instanceMesh?: InstancedMesh;
1366
1368
  private readonly instanceReferences;
1367
1369
  private readonly freeInstanceIndices;
1370
+ private readonly hiddenInstanceMatrices;
1368
1371
  constructor(options?: Partial<SceneObjectOptions>);
1369
1372
  set scene(scene: MineRenderScene);
1370
1373
  get scene(): MineRenderScene;
@@ -1412,6 +1415,7 @@ declare class SceneObject extends Object3D<Object3DEventMap & {
1412
1415
  protected activeInstanceIndices(): Iterable<number>;
1413
1416
  getMatrixAt(index: number, matrix?: Matrix4): Matrix4;
1414
1417
  setMatrixAt(index: number, matrix: Matrix4): void;
1418
+ setInstanceVisibleAt(index: number, visible: boolean): void;
1415
1419
  setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3): void;
1416
1420
  setPositionAt(index: number, position: Vector3): void;
1417
1421
  getPositionAt(index: number, vector?: Vector3): Vector3;
@@ -1479,6 +1483,8 @@ declare class BlockObject extends SceneObject {
1479
1483
  private removeEntities;
1480
1484
  /** Entity models drawn for this block instead of its block model; they are scene children, unlike the block. */
1481
1485
  get blockEntities(): readonly EntityObject[];
1486
+ /** Sets visibility for this block's model instances and block entities. */
1487
+ setVisible(visible: boolean): void;
1482
1488
  /**
1483
1489
  * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,
1484
1490
  * when the block is not listed or one of its models cannot be loaded.
@@ -1551,7 +1557,11 @@ interface MultiBlockBlock extends Block {
1551
1557
  }
1552
1558
 
1553
1559
  declare class SchematicParser {
1554
- static parse(nbt: NBT): Promise<MultiBlockStructure>;
1560
+ /**
1561
+ * Parses a legacy schematic using custom mappings before the bundled defaults.
1562
+ * Keys are `id:metadata`; values are block states such as `minecraft:oak_log[axis=x]`.
1563
+ */
1564
+ static parse(nbt: NBT, customMappings?: Readonly<Record<string, string>>): Promise<MultiBlockStructure>;
1555
1565
  }
1556
1566
 
1557
1567
  declare class StructureParser {
@@ -2308,6 +2318,7 @@ declare class Chunk<SectionMeshing extends boolean = false> {
2308
2318
  private readonly data;
2309
2319
  private readonly renderedBlocks;
2310
2320
  private readonly sectionBlocks;
2321
+ private readonly hiddenBlocks;
2311
2322
  private sectionMesh?;
2312
2323
  private meshDirty;
2313
2324
  constructor(scene: MineRenderScene, x: number, y: number, z: number, onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined, sectionModels?: SectionModels | undefined);
@@ -2324,6 +2335,8 @@ declare class Chunk<SectionMeshing extends boolean = false> {
2324
2335
  * Set a block at integer chunk-local coordinates from 0 to 15.
2325
2336
  */
2326
2337
  setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3, onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<Maybe<BlockInfo<SectionMeshing>>>;
2338
+ setBlockVisibleAt(pos: Vector3, visible: boolean): Promise<void>;
2339
+ isBlockVisibleAt(pos: Vector3): boolean;
2327
2340
  isOccludingAt(pos: Vector3): boolean;
2328
2341
  setCullMaskAt(pos: Vector3, mask: number): Promise<void>;
2329
2342
  rebuildSectionMesh(): void;
@@ -2349,6 +2362,13 @@ declare class MineRenderWorld<SectionMeshing extends boolean = false> {
2349
2362
  setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo<SectionMeshing>>>;
2350
2363
  setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo<SectionMeshing>>>;
2351
2364
  private placeBlock;
2365
+ /**
2366
+ * Shows or hides a placed block without changing its data. Hidden blocks do not occlude neighbors.
2367
+ * Missing blocks are ignored; replacing or removing a block resets its visibility.
2368
+ */
2369
+ setBlockVisibleAt(x: number, y: number, z: number, visible: boolean): Promise<void>;
2370
+ setBlockVisibleAt(pos: Vector3, visible: boolean): Promise<void>;
2371
+ setBlockVisibleAt(pos: TripleArray, visible: boolean): Promise<void>;
2352
2372
  placeMultiBlock(multiblock: MultiBlockStructure, useBatches?: boolean, executor?: BatchedExecutor): Promise<void>;
2353
2373
  private placeBlocks;
2354
2374
  /** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
@@ -1054,6 +1054,7 @@ interface Instanceable {
1054
1054
  isInstanceActive(index: number, reference: InstanceReference<Instanceable>): boolean;
1055
1055
  getMatrixAt(index: number, matrix?: Matrix4): Matrix4;
1056
1056
  setMatrixAt(index: number, matrix: Matrix4): void;
1057
+ setInstanceVisibleAt(index: number, visible: boolean): void;
1057
1058
  setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3): void;
1058
1059
  setPositionAt(index: number, position: Vector3): void;
1059
1060
  getPositionAt(index: number, vector?: Vector3): Vector3;
@@ -1075,6 +1076,7 @@ declare class InstanceReference<T extends Instanceable> implements Transformable
1075
1076
  dispose(): void;
1076
1077
  getMatrix(matrix?: Matrix4): Matrix4;
1077
1078
  setMatrix(matrix: Matrix4): void;
1079
+ setVisible(visible: boolean): void;
1078
1080
  setPositionRotationScale(position?: Vector3, rotation?: Euler, scale?: Vector3): void;
1079
1081
  setPosition(position: Vector3): void;
1080
1082
  getPosition(): Vector3;
@@ -1365,6 +1367,7 @@ declare class SceneObject extends Object3D<Object3DEventMap & {
1365
1367
  protected instanceMesh?: InstancedMesh;
1366
1368
  private readonly instanceReferences;
1367
1369
  private readonly freeInstanceIndices;
1370
+ private readonly hiddenInstanceMatrices;
1368
1371
  constructor(options?: Partial<SceneObjectOptions>);
1369
1372
  set scene(scene: MineRenderScene);
1370
1373
  get scene(): MineRenderScene;
@@ -1412,6 +1415,7 @@ declare class SceneObject extends Object3D<Object3DEventMap & {
1412
1415
  protected activeInstanceIndices(): Iterable<number>;
1413
1416
  getMatrixAt(index: number, matrix?: Matrix4): Matrix4;
1414
1417
  setMatrixAt(index: number, matrix: Matrix4): void;
1418
+ setInstanceVisibleAt(index: number, visible: boolean): void;
1415
1419
  setPositionRotationScaleAt(index: number, position?: Vector3, rotation?: Euler, scale?: Vector3): void;
1416
1420
  setPositionAt(index: number, position: Vector3): void;
1417
1421
  getPositionAt(index: number, vector?: Vector3): Vector3;
@@ -1479,6 +1483,8 @@ declare class BlockObject extends SceneObject {
1479
1483
  private removeEntities;
1480
1484
  /** Entity models drawn for this block instead of its block model; they are scene children, unlike the block. */
1481
1485
  get blockEntities(): readonly EntityObject[];
1486
+ /** Sets visibility for this block's model instances and block entities. */
1487
+ setVisible(visible: boolean): void;
1482
1488
  /**
1483
1489
  * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,
1484
1490
  * when the block is not listed or one of its models cannot be loaded.
@@ -1551,7 +1557,11 @@ interface MultiBlockBlock extends Block {
1551
1557
  }
1552
1558
 
1553
1559
  declare class SchematicParser {
1554
- static parse(nbt: NBT): Promise<MultiBlockStructure>;
1560
+ /**
1561
+ * Parses a legacy schematic using custom mappings before the bundled defaults.
1562
+ * Keys are `id:metadata`; values are block states such as `minecraft:oak_log[axis=x]`.
1563
+ */
1564
+ static parse(nbt: NBT, customMappings?: Readonly<Record<string, string>>): Promise<MultiBlockStructure>;
1555
1565
  }
1556
1566
 
1557
1567
  declare class StructureParser {
@@ -2308,6 +2318,7 @@ declare class Chunk<SectionMeshing extends boolean = false> {
2308
2318
  private readonly data;
2309
2319
  private readonly renderedBlocks;
2310
2320
  private readonly sectionBlocks;
2321
+ private readonly hiddenBlocks;
2311
2322
  private sectionMesh?;
2312
2323
  private meshDirty;
2313
2324
  constructor(scene: MineRenderScene, x: number, y: number, z: number, onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined, sectionModels?: SectionModels | undefined);
@@ -2324,6 +2335,8 @@ declare class Chunk<SectionMeshing extends boolean = false> {
2324
2335
  * Set a block at integer chunk-local coordinates from 0 to 15.
2325
2336
  */
2326
2337
  setBlockInChunkAt(pos: Vector3, block?: Block, worldPos?: Vector3, onBlocksChanged?: ((positions: Vector3[]) => Promise<void>) | undefined): Promise<Maybe<BlockInfo<SectionMeshing>>>;
2338
+ setBlockVisibleAt(pos: Vector3, visible: boolean): Promise<void>;
2339
+ isBlockVisibleAt(pos: Vector3): boolean;
2327
2340
  isOccludingAt(pos: Vector3): boolean;
2328
2341
  setCullMaskAt(pos: Vector3, mask: number): Promise<void>;
2329
2342
  rebuildSectionMesh(): void;
@@ -2349,6 +2362,13 @@ declare class MineRenderWorld<SectionMeshing extends boolean = false> {
2349
2362
  setBlockAt(pos: Vector3, block: Maybe<Block>): Promise<Maybe<BlockInfo<SectionMeshing>>>;
2350
2363
  setBlockAt(pos: TripleArray, block: Maybe<Block>): Promise<Maybe<BlockInfo<SectionMeshing>>>;
2351
2364
  private placeBlock;
2365
+ /**
2366
+ * Shows or hides a placed block without changing its data. Hidden blocks do not occlude neighbors.
2367
+ * Missing blocks are ignored; replacing or removing a block resets its visibility.
2368
+ */
2369
+ setBlockVisibleAt(x: number, y: number, z: number, visible: boolean): Promise<void>;
2370
+ setBlockVisibleAt(pos: Vector3, visible: boolean): Promise<void>;
2371
+ setBlockVisibleAt(pos: TripleArray, visible: boolean): Promise<void>;
2352
2372
  placeMultiBlock(multiblock: MultiBlockStructure, useBatches?: boolean, executor?: BatchedExecutor): Promise<void>;
2353
2373
  private placeBlocks;
2354
2374
  /** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
@@ -3461,6 +3461,9 @@ var init_InstanceReference = __esm({
3461
3461
  setMatrix(matrix) {
3462
3462
  this.activeInstanceable.setMatrixAt(this.index, matrix);
3463
3463
  }
3464
+ setVisible(visible) {
3465
+ this.activeInstanceable.setInstanceVisibleAt(this.index, visible);
3466
+ }
3464
3467
  setPositionRotationScale(position, rotation, scale) {
3465
3468
  this.activeInstanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
3466
3469
  }
@@ -3515,6 +3518,7 @@ var init_SceneObject = __esm({
3515
3518
  this._instanceCounter = 0;
3516
3519
  this.instanceReferences = /* @__PURE__ */ new Map();
3517
3520
  this.freeInstanceIndices = [];
3521
+ this.hiddenInstanceMatrices = /* @__PURE__ */ new Map();
3518
3522
  this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
3519
3523
  console.log("SceneObject options", this.options);
3520
3524
  }
@@ -3709,6 +3713,7 @@ var init_SceneObject = __esm({
3709
3713
  removeInstanceAt(index) {
3710
3714
  if (!this.instanceReferences.has(index)) return;
3711
3715
  const mesh = this.instanceMesh;
3716
+ this.hiddenInstanceMatrices.delete(index);
3712
3717
  this.setMatrixAt(index, new import_three12.Matrix4().makeScale(0, 0, 0));
3713
3718
  this.instanceReferences.delete(index);
3714
3719
  this.freeInstanceIndices.push(index);
@@ -3741,18 +3746,46 @@ var init_SceneObject = __esm({
3741
3746
  //<editor-fold desc="TRANSFORMATION">
3742
3747
  getMatrixAt(index, matrix = new import_three12.Matrix4()) {
3743
3748
  if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3749
+ const hidden = this.hiddenInstanceMatrices.get(index);
3750
+ if (hidden) {
3751
+ return matrix.copy(hidden);
3752
+ }
3744
3753
  this.instanceMesh.getMatrixAt(index, matrix);
3745
3754
  return matrix;
3746
3755
  }
3747
3756
  setMatrixAt(index, matrix) {
3748
3757
  if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3749
3758
  const mesh = this.instanceMesh;
3750
- mesh.setMatrixAt(index, matrix);
3759
+ const hidden = this.hiddenInstanceMatrices.get(index);
3760
+ if (hidden) {
3761
+ hidden.copy(matrix);
3762
+ }
3763
+ mesh.setMatrixAt(index, hidden ? new import_three12.Matrix4().makeScale(0, 0, 0) : matrix);
3751
3764
  mesh.instanceMatrix.needsUpdate = true;
3752
3765
  mesh.boundingBox = null;
3753
3766
  mesh.boundingSphere = null;
3754
3767
  this.notifyDirty();
3755
3768
  }
3769
+ setInstanceVisibleAt(index, visible) {
3770
+ if (!this.instanceReferences.has(index)) {
3771
+ throw new MineRenderError("Instance is not active");
3772
+ }
3773
+ const hidden = this.hiddenInstanceMatrices.get(index);
3774
+ if (visible) {
3775
+ if (!hidden) {
3776
+ return;
3777
+ }
3778
+ this.hiddenInstanceMatrices.delete(index);
3779
+ this.setMatrixAt(index, hidden);
3780
+ } else {
3781
+ if (hidden) {
3782
+ return;
3783
+ }
3784
+ const matrix = this.getMatrixAt(index);
3785
+ this.hiddenInstanceMatrices.set(index, matrix);
3786
+ this.setMatrixAt(index, matrix);
3787
+ }
3788
+ }
3756
3789
  setPositionRotationScaleAt(index, position, rotation, scale) {
3757
3790
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3758
3791
  const oldPosition = new import_three12.Vector3();
@@ -3892,6 +3925,7 @@ var init_SceneObject = __esm({
3892
3925
  if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;
3893
3926
  this.instanceReferences.clear();
3894
3927
  this.freeInstanceIndices.length = 0;
3928
+ this.hiddenInstanceMatrices.clear();
3895
3929
  this._instanceCounter = 0;
3896
3930
  this.instanceMesh.count = 0;
3897
3931
  this.instanceMesh.dispose();
@@ -9263,6 +9297,21 @@ var _BlockObject = class _BlockObject extends SceneObject {
9263
9297
  get blockEntities() {
9264
9298
  return this._entities;
9265
9299
  }
9300
+ /** Sets visibility for this block's model instances and block entities. */
9301
+ setVisible(visible) {
9302
+ this.visible = visible;
9303
+ for (const model of this._models) {
9304
+ if (isInstanceReference(model)) {
9305
+ model.setVisible(visible);
9306
+ } else {
9307
+ model.visible = visible;
9308
+ }
9309
+ }
9310
+ for (const entity of this._entities) {
9311
+ entity.visible = visible;
9312
+ }
9313
+ this.notifyDirty();
9314
+ }
9266
9315
  /**
9267
9316
  * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,
9268
9317
  * when the block is not listed or one of its models cannot be loaded.
@@ -9296,6 +9345,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
9296
9345
  BlockEntities.matrix(resolved, this._entityPlacement);
9297
9346
  this._entities = created;
9298
9347
  this.placeEntities();
9348
+ this.setVisible(this.visible);
9299
9349
  return true;
9300
9350
  }
9301
9351
  placeEntities() {
@@ -9305,6 +9355,9 @@ var _BlockObject = class _BlockObject extends SceneObject {
9305
9355
  }
9306
9356
  }
9307
9357
  get isOccluding() {
9358
+ if (!this.visible) {
9359
+ return false;
9360
+ }
9308
9361
  return this._models.some((model) => {
9309
9362
  const object = isInstanceReference(model) ? model.instanceable : model;
9310
9363
  return object.isOpaqueFullCube && this.getModelCullMask(model, 63) === 63;
@@ -9360,6 +9413,9 @@ var _BlockObject = class _BlockObject extends SceneObject {
9360
9413
  this._models = replacements;
9361
9414
  this._cullMask = worldMask;
9362
9415
  this.removeModels(previous.filter((model) => !replacements.includes(model)));
9416
+ if (!this.visible) {
9417
+ this.setVisible(false);
9418
+ }
9363
9419
  this.notifyDirty();
9364
9420
  }
9365
9421
  get state() {
@@ -9395,6 +9451,9 @@ var _BlockObject = class _BlockObject extends SceneObject {
9395
9451
  this._isInstanced || (this._isInstanced = isInstanceReference(replacement));
9396
9452
  this._instanceCounter = this._isInstanced ? 1 : 0;
9397
9453
  if (previous) this.removeModels([previous]);
9454
+ if (!this.visible) {
9455
+ this.setVisible(false);
9456
+ }
9398
9457
  this.notifyDirty();
9399
9458
  }
9400
9459
  nextInstance() {
@@ -9423,6 +9482,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
9423
9482
  this._models.push(await this.createVariant(blockStateVariant));
9424
9483
  }
9425
9484
  await this.updateFluid(this._fluidSampler);
9485
+ this.setVisible(this.visible);
9426
9486
  }
9427
9487
  async hasGeometry(variant) {
9428
9488
  const modelKey = AssetKey.parse("models", variant.model);
@@ -11260,7 +11320,11 @@ var legacyBlocks_default = {
11260
11320
 
11261
11321
  // src/model/multiblock/SchematicParser.ts
11262
11322
  var SchematicParser = class {
11263
- static async parse(nbt) {
11323
+ /**
11324
+ * Parses a legacy schematic using custom mappings before the bundled defaults.
11325
+ * Keys are `id:metadata`; values are block states such as `minecraft:oak_log[axis=x]`.
11326
+ */
11327
+ static async parse(nbt, customMappings = {}) {
11264
11328
  const tags = nbt.value;
11265
11329
  if (tags.Materials?.type !== "string" || tags.Materials.value !== "Alpha") {
11266
11330
  throw new MineRenderError("Schematic Materials must be Alpha");
@@ -11302,15 +11366,16 @@ var SchematicParser = class {
11302
11366
  const high = packed >> (index & 1) * 4 & 15;
11303
11367
  const id = high << 8 | ids.value[index] & 255;
11304
11368
  const metadata = data.value[index] & 255;
11305
- const mapped = mapping[`${id}:${metadata}`];
11369
+ const key = `${id}:${metadata}`;
11370
+ const mapped = customMappings[key] ?? mapping[key];
11306
11371
  if (!mapped) throw new MineRenderError(`Unsupported legacy block ${id}:${metadata} at schematic index ${index}`);
11307
11372
  const [type, state] = mapped.split("[");
11308
11373
  if (type === "minecraft:air") continue;
11309
11374
  const properties = {};
11310
11375
  if (state) {
11311
11376
  for (const property of state.slice(0, -1).split(",")) {
11312
- const [key, value] = property.split("=");
11313
- properties[key] = value;
11377
+ const [key2, value] = property.split("=");
11378
+ properties[key2] = value;
11314
11379
  }
11315
11380
  }
11316
11381
  blocks.push({
@@ -14206,6 +14271,16 @@ var MineRenderWorld = class {
14206
14271
  const chunk = Chunk.isAir(value) ? this.getChunkAt(pos) : this.getOrCreateChunkAt(pos);
14207
14272
  return chunk?.setBlockInChunkAt(chunk.worldPosToChunkPos(pos), value, pos, onBlocksChanged);
14208
14273
  }
14274
+ async setBlockVisibleAt(posOrX, yOrVisible, z, visible) {
14275
+ if (typeof posOrX === "number") {
14276
+ return this.setBlockVisibleAt(new import_three38.Vector3(posOrX, yOrVisible, z), visible);
14277
+ }
14278
+ if (isTripleArray(posOrX)) {
14279
+ return this.setBlockVisibleAt(new import_three38.Vector3(...posOrX), yOrVisible);
14280
+ }
14281
+ this.validatePosBounds(posOrX);
14282
+ await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible);
14283
+ }
14209
14284
  async placeMultiBlock(multiblock, useBatches = true, executor) {
14210
14285
  const changes = /* @__PURE__ */ new Map();
14211
14286
  try {
@@ -14321,12 +14396,14 @@ var MineRenderWorld = class {
14321
14396
  if (!chunk) continue;
14322
14397
  changed.add(chunk);
14323
14398
  const block = chunk.getBlockAt(pos);
14324
- if (!block) continue;
14399
+ if (!block || !chunk.isBlockVisibleAt(pos)) {
14400
+ continue;
14401
+ }
14325
14402
  if (block.object?.fluidKind) {
14326
14403
  await block.object.updateFluid((x, y, z) => {
14327
14404
  const neighbor = pos.clone().add(new import_three38.Vector3(x, y, z));
14328
14405
  const section = this.getChunkAt(neighbor);
14329
- const object = section?.getBlockAt(neighbor)?.object;
14406
+ const object = section?.isBlockVisibleAt(neighbor) ? section.getBlockAt(neighbor)?.object : void 0;
14330
14407
  return {
14331
14408
  fluid: object?.fluidKind,
14332
14409
  level: object?.fluidLevel,
@@ -14513,6 +14590,7 @@ var Chunk = class _Chunk {
14513
14590
  this.data = new ChunkData();
14514
14591
  this.renderedBlocks = /* @__PURE__ */ new Map();
14515
14592
  this.sectionBlocks = /* @__PURE__ */ new Map();
14593
+ this.hiddenBlocks = /* @__PURE__ */ new Set();
14516
14594
  this.meshDirty = false;
14517
14595
  this.scene = scene;
14518
14596
  this.x = x;
@@ -14550,6 +14628,7 @@ var Chunk = class _Chunk {
14550
14628
  worldPos = this.chunkPosToWorldPos(pos);
14551
14629
  }
14552
14630
  const index = _Chunk.chunkPosToBlockIndex(pos);
14631
+ this.hiddenBlocks.delete(index);
14553
14632
  this.data.set(index, block);
14554
14633
  const readBlock = this.data.snapshot(index);
14555
14634
  this.renderedBlocks.get(index)?.object?.removeFromScene();
@@ -14591,9 +14670,31 @@ var Chunk = class _Chunk {
14591
14670
  await onBlocksChanged?.([worldPos]);
14592
14671
  }
14593
14672
  }
14673
+ async setBlockVisibleAt(pos, visible) {
14674
+ const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
14675
+ const block = this.renderedBlocks.get(index);
14676
+ if (!block || visible === !this.hiddenBlocks.has(index)) {
14677
+ return;
14678
+ }
14679
+ if (visible) {
14680
+ this.hiddenBlocks.delete(index);
14681
+ } else {
14682
+ this.hiddenBlocks.add(index);
14683
+ }
14684
+ block.object?.setVisible(visible);
14685
+ if (this.sectionBlocks.has(index)) {
14686
+ this.meshDirty = true;
14687
+ }
14688
+ this.scene.dirty = true;
14689
+ await this.onBlocksChanged?.([pos]);
14690
+ }
14691
+ isBlockVisibleAt(pos) {
14692
+ const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
14693
+ return this.renderedBlocks.has(index) && !this.hiddenBlocks.has(index);
14694
+ }
14594
14695
  isOccludingAt(pos) {
14595
14696
  const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
14596
- return this.sectionBlocks.has(index) || (this.renderedBlocks.get(index)?.object?.isOccluding ?? false);
14697
+ return !this.hiddenBlocks.has(index) && (this.sectionBlocks.has(index) || (this.renderedBlocks.get(index)?.object?.isOccluding ?? false));
14597
14698
  }
14598
14699
  async setCullMaskAt(pos, mask) {
14599
14700
  const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
@@ -14609,7 +14710,10 @@ var Chunk = class _Chunk {
14609
14710
  }
14610
14711
  rebuildSectionMesh() {
14611
14712
  if (!this.meshDirty) return;
14612
- const next = this.sectionBlocks.size ? SectionMesh.build([...this.sectionBlocks.values()], this.sectionModels.maxAtlasSize) : void 0;
14713
+ const next = this.sectionBlocks.size ? SectionMesh.build(
14714
+ [...this.sectionBlocks.values()].filter((entry) => !this.hiddenBlocks.has(entry.index)),
14715
+ this.sectionModels.maxAtlasSize
14716
+ ) : void 0;
14613
14717
  this.sectionMesh?.dispose();
14614
14718
  this.sectionMesh = next;
14615
14719
  if (next) {
@@ -14629,6 +14733,7 @@ var Chunk = class _Chunk {
14629
14733
  this.sectionMesh = void 0;
14630
14734
  this.meshDirty = false;
14631
14735
  this.renderedBlocks.clear();
14736
+ this.hiddenBlocks.clear();
14632
14737
  this.data.clear();
14633
14738
  await onBlocksChanged?.(positions);
14634
14739
  }