minerender 2.1.0-alpha.61 → 2.1.0-alpha.63

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.
@@ -3322,11 +3322,11 @@ var init_Entities = __esm({
3322
3322
  return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
3323
3323
  }
3324
3324
  /**
3325
- * Vanilla's keyframe animations of a model by name, or undefined when the model or the selected version has none.
3325
+ * Native and sampled vanilla clips by name, or undefined when the model or selected version has none.
3326
3326
  */
3327
3327
  static async getAnimations(modelKey) {
3328
3328
  const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
3329
- const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json");
3329
+ const key = new AssetKey(modelKey.namespace, path, void 0, void 0, "entity-models/animations", ".json", isAssetKey(modelKey) ? modelKey.root : void 0);
3330
3330
  const file = await Caching.entityAnimationCache.get(key.serialize(), () => AssetLoader.get(key, "json" /* JSON */));
3331
3331
  return file?.animations;
3332
3332
  }
@@ -3376,7 +3376,7 @@ function sampleEntityKeyframes(keyframes, time) {
3376
3376
  let low = 0, high = keyframes.length;
3377
3377
  while (low < high) {
3378
3378
  const middle = low + high >>> 1;
3379
- if (time <= keyframes[middle].time) high = middle;
3379
+ if (time < keyframes[middle].time) high = middle;
3380
3380
  else low = middle + 1;
3381
3381
  }
3382
3382
  const a = Math.max(0, low - 1);
@@ -3415,6 +3415,7 @@ var init_EntityAnimation = __esm({
3415
3415
  });
3416
3416
 
3417
3417
  // src/entity/scene/EntityAnimationPlayer.ts
3418
+ import { Euler as Euler3, Vector3 as Vector35 } from "three";
3418
3419
  var ZERO, EntityAnimationPlayer;
3419
3420
  var init_EntityAnimationPlayer = __esm({
3420
3421
  "src/entity/scene/EntityAnimationPlayer.ts"() {
@@ -3434,25 +3435,45 @@ var init_EntityAnimationPlayer = __esm({
3434
3435
  return this._time;
3435
3436
  }
3436
3437
  /**
3437
- * Starts an animation on the named parts below each layer root. The current pose of a part becomes its default;
3438
- * bones without a matching part are skipped.
3438
+ * Starts an animation on matching named parts. Supplied baked poses are the baseline for offsets;
3439
+ * without them, the current pose is used. Stopping restores the pose from before playback.
3439
3440
  */
3440
- play(layers, animation, options = {}) {
3441
+ play(layers, animation, options = {}, poses) {
3441
3442
  this.stop();
3442
3443
  this._animation = animation;
3443
3444
  this._time = options.time ?? 0;
3444
3445
  this.loop = options.loop ?? animation.loop;
3445
3446
  this.speed = options.speed ?? 1;
3446
3447
  for (const layer of layers) {
3447
- for (const bone of Object.keys(animation.bones)) {
3448
- const object = layer.getObjectByName(`group:${bone}`);
3449
- if (!object) continue;
3450
- this.parts.push({ bone, object, position: object.position.clone(), rotation: object.rotation.clone(), scale: object.scale.clone() });
3448
+ const objects = [];
3449
+ if (poses) {
3450
+ layer.traverse((object) => {
3451
+ if (poses.has(object)) objects.push(object);
3452
+ });
3453
+ } else {
3454
+ for (const bone of Object.keys(animation.bones)) {
3455
+ const object = layer.getObjectByName(`group:${bone}`);
3456
+ if (object) objects.push(object);
3457
+ }
3458
+ }
3459
+ for (const object of objects) {
3460
+ const bone = object.name.slice("group:".length);
3461
+ const pose = poses?.get(object);
3462
+ this.parts.push({
3463
+ bone,
3464
+ object,
3465
+ position: object.position.clone(),
3466
+ rotation: object.rotation.clone(),
3467
+ scale: object.scale.clone(),
3468
+ basePosition: pose ? new Vector35(...pose.offset) : object.position.clone(),
3469
+ baseRotation: pose ? new Euler3(...pose.rotation, "ZYX") : object.rotation.clone(),
3470
+ baseScale: pose ? new Vector35(...pose.scale ?? [1, 1, 1]) : object.scale.clone()
3471
+ });
3451
3472
  }
3452
3473
  }
3453
3474
  this.apply();
3454
3475
  }
3455
- /** Restores the default poses. Returns whether an animation was active. */
3476
+ /** Restores the poses from before playback. Returns whether an animation was active. */
3456
3477
  stop() {
3457
3478
  if (!this._animation) return false;
3458
3479
  for (const part of this.parts) {
@@ -3481,10 +3502,10 @@ var init_EntityAnimationPlayer = __esm({
3481
3502
  apply() {
3482
3503
  const pose = sampleEntityAnimation(this._animation, this._time, this.loop);
3483
3504
  for (const part of this.parts) {
3484
- const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone];
3485
- part.object.position.set(part.position.x + position[0], part.position.y + position[1], part.position.z + position[2]);
3486
- part.object.rotation.set(part.rotation.x + rotation[0], part.rotation.y + rotation[1], part.rotation.z + rotation[2], part.rotation.order);
3487
- part.object.scale.set(part.scale.x + scale[0], part.scale.y + scale[1], part.scale.z + scale[2]);
3505
+ const { position = ZERO, rotation = ZERO, scale = ZERO } = pose[part.bone] ?? {};
3506
+ part.object.position.set(part.basePosition.x + position[0], part.basePosition.y + position[1], part.basePosition.z + position[2]);
3507
+ part.object.rotation.set(part.baseRotation.x + rotation[0], part.baseRotation.y + rotation[1], part.baseRotation.z + rotation[2], part.baseRotation.order);
3508
+ part.object.scale.set(part.baseScale.x + scale[0], part.baseScale.y + scale[1], part.baseScale.z + scale[2]);
3488
3509
  }
3489
3510
  }
3490
3511
  };
@@ -3524,6 +3545,9 @@ var init_InstanceReference = __esm({
3524
3545
  setMatrix(matrix) {
3525
3546
  this.activeInstanceable.setMatrixAt(this.index, matrix);
3526
3547
  }
3548
+ setVisible(visible) {
3549
+ this.activeInstanceable.setInstanceVisibleAt(this.index, visible);
3550
+ }
3527
3551
  setPositionRotationScale(position, rotation, scale) {
3528
3552
  this.activeInstanceable.setPositionRotationScaleAt(this.index, position, rotation, scale);
3529
3553
  }
@@ -3551,7 +3575,7 @@ var init_InstanceReference = __esm({
3551
3575
  });
3552
3576
 
3553
3577
  // src/renderer/SceneObject.ts
3554
- import { Color as Color2, Euler as Euler3, InstancedBufferAttribute, InstancedMesh, MathUtils, Matrix4 as Matrix44, Mesh as Mesh3, Object3D as Object3D2, Quaternion as Quaternion3, Vector3 as Vector35 } from "three";
3578
+ import { Color as Color2, Euler as Euler4, InstancedBufferAttribute, InstancedMesh, MathUtils, Matrix4 as Matrix44, Mesh as Mesh3, Object3D as Object3D2, Quaternion as Quaternion3, Vector3 as Vector36 } from "three";
3555
3579
  function isSceneObject(obj) {
3556
3580
  return obj.isSceneObject;
3557
3581
  }
@@ -3578,6 +3602,7 @@ var init_SceneObject = __esm({
3578
3602
  this._instanceCounter = 0;
3579
3603
  this.instanceReferences = /* @__PURE__ */ new Map();
3580
3604
  this.freeInstanceIndices = [];
3605
+ this.hiddenInstanceMatrices = /* @__PURE__ */ new Map();
3581
3606
  this.options = (0, import_ts_deepmerge3.default)({}, _SceneObject.DEFAULT_OPTIONS, options ?? {});
3582
3607
  console.log("SceneObject options", this.options);
3583
3608
  }
@@ -3780,6 +3805,7 @@ var init_SceneObject = __esm({
3780
3805
  removeInstanceAt(index) {
3781
3806
  if (!this.instanceReferences.has(index)) return;
3782
3807
  const mesh = this.instanceMesh;
3808
+ this.hiddenInstanceMatrices.delete(index);
3783
3809
  this.setMatrixAt(index, new Matrix44().makeScale(0, 0, 0));
3784
3810
  this.instanceReferences.delete(index);
3785
3811
  this.freeInstanceIndices.push(index);
@@ -3812,23 +3838,51 @@ var init_SceneObject = __esm({
3812
3838
  //<editor-fold desc="TRANSFORMATION">
3813
3839
  getMatrixAt(index, matrix = new Matrix44()) {
3814
3840
  if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3841
+ const hidden = this.hiddenInstanceMatrices.get(index);
3842
+ if (hidden) {
3843
+ return matrix.copy(hidden);
3844
+ }
3815
3845
  this.instanceMesh.getMatrixAt(index, matrix);
3816
3846
  return matrix;
3817
3847
  }
3818
3848
  setMatrixAt(index, matrix) {
3819
3849
  if (!this.instanceReferences.has(index)) throw new MineRenderError("Instance is not active");
3820
3850
  const mesh = this.instanceMesh;
3821
- mesh.setMatrixAt(index, matrix);
3851
+ const hidden = this.hiddenInstanceMatrices.get(index);
3852
+ if (hidden) {
3853
+ hidden.copy(matrix);
3854
+ }
3855
+ mesh.setMatrixAt(index, hidden ? new Matrix44().makeScale(0, 0, 0) : matrix);
3822
3856
  mesh.instanceMatrix.needsUpdate = true;
3823
3857
  mesh.boundingBox = null;
3824
3858
  mesh.boundingSphere = null;
3825
3859
  this.notifyDirty();
3826
3860
  }
3861
+ setInstanceVisibleAt(index, visible) {
3862
+ if (!this.instanceReferences.has(index)) {
3863
+ throw new MineRenderError("Instance is not active");
3864
+ }
3865
+ const hidden = this.hiddenInstanceMatrices.get(index);
3866
+ if (visible) {
3867
+ if (!hidden) {
3868
+ return;
3869
+ }
3870
+ this.hiddenInstanceMatrices.delete(index);
3871
+ this.setMatrixAt(index, hidden);
3872
+ } else {
3873
+ if (hidden) {
3874
+ return;
3875
+ }
3876
+ const matrix = this.getMatrixAt(index);
3877
+ this.hiddenInstanceMatrices.set(index, matrix);
3878
+ this.setMatrixAt(index, matrix);
3879
+ }
3880
+ }
3827
3881
  setPositionRotationScaleAt(index, position, rotation, scale) {
3828
3882
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3829
- const oldPosition = new Vector35();
3883
+ const oldPosition = new Vector36();
3830
3884
  const oldRotation = new Quaternion3();
3831
- const oldScale = new Vector35();
3885
+ const oldScale = new Vector36();
3832
3886
  const matrix = new Matrix44();
3833
3887
  if (!scale || !rotation || !position) {
3834
3888
  this.getMatrixAt(index, matrix).decompose(oldPosition, oldRotation, oldScale);
@@ -3844,7 +3898,7 @@ var init_SceneObject = __esm({
3844
3898
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3845
3899
  this.setPositionRotationScaleAt(index, position);
3846
3900
  }
3847
- getPositionAt(index, vector = new Vector35()) {
3901
+ getPositionAt(index, vector = new Vector36()) {
3848
3902
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3849
3903
  const matrix = this.getMatrixAt(index);
3850
3904
  vector.setFromMatrixPosition(matrix);
@@ -3854,17 +3908,17 @@ var init_SceneObject = __esm({
3854
3908
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3855
3909
  this.setPositionRotationScaleAt(index, void 0, rotation, void 0);
3856
3910
  }
3857
- getRotationAt(index, euler = new Euler3()) {
3911
+ getRotationAt(index, euler = new Euler4()) {
3858
3912
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3859
3913
  const rotation = new Quaternion3();
3860
- this.getMatrixAt(index).decompose(new Vector35(), rotation, new Vector35());
3914
+ this.getMatrixAt(index).decompose(new Vector36(), rotation, new Vector36());
3861
3915
  return euler.setFromQuaternion(rotation);
3862
3916
  }
3863
3917
  setScaleAt(index, scale) {
3864
3918
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3865
3919
  this.setPositionRotationScaleAt(index, void 0, void 0, scale);
3866
3920
  }
3867
- getScaleAt(index, vector = new Vector35()) {
3921
+ getScaleAt(index, vector = new Vector36()) {
3868
3922
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
3869
3923
  const matrix = this.getMatrixAt(index);
3870
3924
  vector.setFromMatrixScale(matrix);
@@ -3963,6 +4017,7 @@ var init_SceneObject = __esm({
3963
4017
  if (this._scene) this._scene.stats.instanceCount -= this.instanceReferences.size;
3964
4018
  this.instanceReferences.clear();
3965
4019
  this.freeInstanceIndices.length = 0;
4020
+ this.hiddenInstanceMatrices.clear();
3966
4021
  this._instanceCounter = 0;
3967
4022
  this.instanceMesh.count = 0;
3968
4023
  this.instanceMesh.dispose();
@@ -3989,7 +4044,7 @@ var init_SceneObject = __esm({
3989
4044
  });
3990
4045
 
3991
4046
  // src/entity/scene/EntityObject.ts
3992
- import { Color as Color3, Euler as Euler4, Matrix4 as Matrix45, Object3D as Object3D3 } from "three";
4047
+ import { Color as Color3, Euler as Euler5, Matrix4 as Matrix45, Object3D as Object3D3 } from "three";
3993
4048
  function isEntityObject(obj) {
3994
4049
  return obj.isEntityObject;
3995
4050
  }
@@ -4019,7 +4074,8 @@ var init_EntityObject = __esm({
4019
4074
  this.scrollMaterials = [];
4020
4075
  /** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
4021
4076
  this.age = 0;
4022
- this.animationPlayer = new EntityAnimationPlayer();
4077
+ this.animationPlayers = [];
4078
+ this.partPoses = /* @__PURE__ */ new Map();
4023
4079
  this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
4024
4080
  this.addEventListener("added", () => this.updateScrollSubscription());
4025
4081
  this.addEventListener("removed", () => this.updateScrollSubscription());
@@ -4039,7 +4095,8 @@ var init_EntityObject = __esm({
4039
4095
  for (const geometry of this.geometries) geometry.dispose();
4040
4096
  this.geometries.clear();
4041
4097
  for (const dispose of this.disposeWireframes.splice(0)) dispose();
4042
- this.animationPlayer.clear();
4098
+ for (const player of this.animationPlayers.splice(0)) player.clear();
4099
+ this.partPoses.clear();
4043
4100
  super.disposeAndRemoveAllChildren();
4044
4101
  }
4045
4102
  clearScrollMaterials() {
@@ -4071,36 +4128,61 @@ var init_EntityObject = __esm({
4071
4128
  this.notifyDirty();
4072
4129
  }
4073
4130
  //<editor-fold desc="ANIMATION">
4074
- /** The animation started by {@link playAnimation}, until {@link stopAnimation} or disposal. */
4131
+ /** The first active clip, until playback is stopped or the object is disposed. */
4075
4132
  get animation() {
4076
- return this.animationPlayer.animation;
4133
+ return this.animationPlayers[0]?.animation;
4134
+ }
4135
+ /** Clips playing together, each targeting a separate geometry layer. */
4136
+ get activeAnimations() {
4137
+ return this.animationPlayers.map((player) => player.animation);
4077
4138
  }
4078
4139
  /** Seconds since the animation started, before looping. */
4079
4140
  get animationTime() {
4080
- return this.animationPlayer.time;
4141
+ return this.animationPlayers[0]?.time ?? 0;
4081
4142
  }
4082
4143
  /**
4083
- * Poses the object from a keyframe animation of {@link Entities.getAnimations}, replacing the current one.
4084
- * Parts of every layer are matched by name and their current pose is the default the offsets add to.
4144
+ * Plays a clip from {@link Entities.getAnimations}, replacing all active clips.
4145
+ * Offsets apply to the baked pose in the clip's layer (`main` by default), including repeated draws of that layer.
4085
4146
  * The object owns no clock: call {@link advanceAnimation} per frame, or {@link setAnimationTime}.
4086
4147
  */
4087
4148
  playAnimation(animation, options) {
4149
+ this.playAnimations([animation], options);
4150
+ }
4151
+ /** Plays one clip per selected geometry layer, with a shared clock and no blending between clips. */
4152
+ playAnimations(animations, options) {
4153
+ const targets = /* @__PURE__ */ new Set();
4154
+ const selections = animations.map((animation) => {
4155
+ const layer = animation.layer ?? "main";
4156
+ if (targets.has(layer)) throw new Error(`Multiple animations target layer "${layer}"`);
4157
+ targets.add(layer);
4158
+ const names = Object.keys(this.entityLayers).filter((name) => name.split("#")[0] === layer);
4159
+ if (!names.length) throw new Error(`Entity ${this.entity.id} has no selected animation layer "${layer}"`);
4160
+ return { animation, names };
4161
+ });
4088
4162
  this.createMeshes();
4089
- const layers = Object.keys(this.entityLayers).map((name) => this.getLayerGroup(name)).filter((layer) => !!layer);
4090
- this.animationPlayer.play(layers, animation, options);
4163
+ this.stopAnimation();
4164
+ for (const { animation, names } of selections) {
4165
+ const player = new EntityAnimationPlayer();
4166
+ player.play(names.map((name) => this.getLayerGroup(name)), animation, options, this.partPoses);
4167
+ this.animationPlayers.push(player);
4168
+ }
4091
4169
  this.notifyDirty();
4092
4170
  }
4093
- /** Stops the animation and restores the default pose. */
4171
+ /** Stops all clips and restores the poses from before playback. */
4094
4172
  stopAnimation() {
4095
- if (this.animationPlayer.stop()) this.notifyDirty();
4173
+ const players = this.animationPlayers.splice(0);
4174
+ for (const player of players) player.stop();
4175
+ if (players.length) this.notifyDirty();
4096
4176
  }
4097
4177
  /** Poses the object at an explicit time in seconds. Has no effect without an animation. */
4098
4178
  setAnimationTime(seconds) {
4099
- if (this.animationPlayer.setTime(seconds)) this.notifyDirty();
4179
+ for (const player of this.animationPlayers) player.setTime(seconds);
4180
+ if (this.animationPlayers.length) this.notifyDirty();
4100
4181
  }
4101
4182
  /** Advances the animation by a frame delta in seconds, scaled by its speed. Has no effect without an animation. */
4102
4183
  advanceAnimation(deltaSeconds) {
4103
- if (this.animationPlayer.advance(deltaSeconds)) this.notifyDirty();
4184
+ for (const player of this.animationPlayers) player.advance(deltaSeconds);
4185
+ if (this.animationPlayers.length) this.notifyDirty();
4104
4186
  }
4105
4187
  //</editor-fold>
4106
4188
  getLayerGroup(name) {
@@ -4139,7 +4221,7 @@ var init_EntityObject = __esm({
4139
4221
  const matrix = new Matrix45();
4140
4222
  if ("scale" in op) matrix.makeScale(...op.scale);
4141
4223
  else if ("translate" in op) matrix.makeTranslation(...op.translate);
4142
- else matrix.makeRotationFromEuler(new Euler4(...op.rotate, "ZYX"));
4224
+ else matrix.makeRotationFromEuler(new Euler5(...op.rotate, "ZYX"));
4143
4225
  modelRoot.matrix.multiply(matrix);
4144
4226
  }
4145
4227
  modelRoot.matrixAutoUpdate = false;
@@ -4160,6 +4242,7 @@ var init_EntityObject = __esm({
4160
4242
  anchor.position.fromArray(part.pose.offset);
4161
4243
  anchor.rotation.set(...part.pose.rotation, "ZYX");
4162
4244
  anchor.scale.fromArray(part.pose.scale ?? [1, 1, 1]);
4245
+ this.partPoses.set(anchor, part.pose);
4163
4246
  parent.add(anchor);
4164
4247
  const size = part.texture ?? textureSize;
4165
4248
  for (const cube of part.cubes) {
@@ -4234,7 +4317,7 @@ import {
4234
4317
  TriangleFanDrawMode,
4235
4318
  TriangleStripDrawMode,
4236
4319
  TrianglesDrawMode,
4237
- Vector3 as Vector39
4320
+ Vector3 as Vector310
4238
4321
  } from "three";
4239
4322
  function computeTangents(geometry) {
4240
4323
  geometry.computeTangents();
@@ -4553,15 +4636,15 @@ function computeMorphedAttributes(object) {
4553
4636
  console.error("THREE.BufferGeometryUtils: Geometry is not of type BufferGeometry.");
4554
4637
  return null;
4555
4638
  }
4556
- const _vA = new Vector39();
4557
- const _vB = new Vector39();
4558
- const _vC = new Vector39();
4559
- const _tempA = new Vector39();
4560
- const _tempB = new Vector39();
4561
- const _tempC = new Vector39();
4562
- const _morphA = new Vector39();
4563
- const _morphB = new Vector39();
4564
- const _morphC = new Vector39();
4639
+ const _vA = new Vector310();
4640
+ const _vB = new Vector310();
4641
+ const _vC = new Vector310();
4642
+ const _tempA = new Vector310();
4643
+ const _tempB = new Vector310();
4644
+ const _tempC = new Vector310();
4645
+ const _morphA = new Vector310();
4646
+ const _morphB = new Vector310();
4647
+ const _morphC = new Vector310();
4565
4648
  function _calculateMorphedAttributeData(object2, material2, attribute, morphAttribute, morphTargetsRelative2, a2, b2, c2, modifiedAttributeArray) {
4566
4649
  _vA.fromBufferAttribute(attribute, a2);
4567
4650
  _vB.fromBufferAttribute(attribute, b2);
@@ -4771,7 +4854,7 @@ var init_BufferGeometryUtils = __esm({
4771
4854
  });
4772
4855
 
4773
4856
  // src/model/ModelCulling.ts
4774
- import { Vector3 as Vector310 } from "three";
4857
+ import { Vector3 as Vector311 } from "three";
4775
4858
  var ModelCulling;
4776
4859
  var init_ModelCulling = __esm({
4777
4860
  "src/model/ModelCulling.ts"() {
@@ -4780,7 +4863,7 @@ var init_ModelCulling = __esm({
4780
4863
  static toLocalMask(worldMask, rotation) {
4781
4864
  let localMask = 0;
4782
4865
  for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
4783
- const normal = new Vector310(...offset).applyEuler(rotation);
4866
+ const normal = new Vector311(...offset).applyEuler(rotation);
4784
4867
  const worldFace = CUBE_FACE_OFFSETS.findIndex(([x, y, z]) => Math.abs(normal.x - x) < 1e-6 && Math.abs(normal.y - y) < 1e-6 && Math.abs(normal.z - z) < 1e-6);
4785
4868
  if (worldFace < 0) return 0;
4786
4869
  if (worldMask & 1 << worldFace) localMask |= 1 << localFace;
@@ -5007,7 +5090,7 @@ var init_ItemTints = __esm({
5007
5090
  });
5008
5091
 
5009
5092
  // src/model/scene/ModelObject.ts
5010
- import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color8, Euler as Euler6, Matrix4 as Matrix49 } from "three";
5093
+ import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color8, Euler as Euler7, Matrix4 as Matrix49 } from "three";
5011
5094
  function isModelObject(obj) {
5012
5095
  return obj.isModelObject;
5013
5096
  }
@@ -5114,7 +5197,7 @@ var init_ModelObject = __esm({
5114
5197
  elGeo.clearGroups();
5115
5198
  }
5116
5199
  if (this.options.uvLockRotation) {
5117
- UVMapper.lockUvs(elGeo, el.faces, this.atlas, new Euler6(...this.options.uvLockRotation));
5200
+ UVMapper.lockUvs(elGeo, el.faces, this.atlas, new Euler7(...this.options.uvLockRotation));
5118
5201
  }
5119
5202
  if (this.options.tints) {
5120
5203
  const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
@@ -5735,7 +5818,7 @@ import {
5735
5818
  Color as Color4,
5736
5819
  Matrix3,
5737
5820
  Vector2 as Vector22,
5738
- Vector3 as Vector36
5821
+ Vector3 as Vector37
5739
5822
  } from "three";
5740
5823
  var OBJExporter = class {
5741
5824
  parse(object) {
@@ -5743,9 +5826,9 @@ var OBJExporter = class {
5743
5826
  let indexVertex = 0;
5744
5827
  let indexVertexUvs = 0;
5745
5828
  let indexNormals = 0;
5746
- const vertex = new Vector36();
5829
+ const vertex = new Vector37();
5747
5830
  const color = new Color4();
5748
- const normal = new Vector36();
5831
+ const normal = new Vector37();
5749
5832
  const uv = new Vector22();
5750
5833
  const face = [];
5751
5834
  function parseMesh(mesh) {
@@ -5874,7 +5957,7 @@ var OBJExporter = class {
5874
5957
  // ../../node_modules/three/examples/jsm/exporters/PLYExporter.js
5875
5958
  import {
5876
5959
  Matrix3 as Matrix32,
5877
- Vector3 as Vector37,
5960
+ Vector3 as Vector38,
5878
5961
  Color as Color5
5879
5962
  } from "three";
5880
5963
  var PLYExporter = class {
@@ -5967,7 +6050,7 @@ property list uchar int vertex_index
5967
6050
  `;
5968
6051
  }
5969
6052
  header += "end_header\n";
5970
- const vertex = new Vector37();
6053
+ const vertex = new Vector38();
5971
6054
  const normalMatrixWorld = new Matrix32();
5972
6055
  let result = null;
5973
6056
  if (options.binary === true) {
@@ -6166,7 +6249,7 @@ import {
6166
6249
  Source,
6167
6250
  SRGBColorSpace as SRGBColorSpace4,
6168
6251
  CompressedTexture,
6169
- Vector3 as Vector38,
6252
+ Vector3 as Vector39,
6170
6253
  Quaternion as Quaternion4
6171
6254
  } from "three";
6172
6255
 
@@ -6627,7 +6710,7 @@ var GLTFWriter = class {
6627
6710
  isNormalizedNormalAttribute(normal) {
6628
6711
  const cache = this.cache;
6629
6712
  if (cache.attributesNormalized.has(normal)) return false;
6630
- const v = new Vector38();
6713
+ const v = new Vector39();
6631
6714
  for (let i = 0, il = normal.count; i < il; i++) {
6632
6715
  if (Math.abs(v.fromBufferAttribute(normal, i).length() - 1) > 5e-4) return false;
6633
6716
  }
@@ -6644,7 +6727,7 @@ var GLTFWriter = class {
6644
6727
  const cache = this.cache;
6645
6728
  if (cache.attributesNormalized.has(normal)) return cache.attributesNormalized.get(normal);
6646
6729
  const attribute = normal.clone();
6647
- const v = new Vector38();
6730
+ const v = new Vector39();
6648
6731
  for (let i = 0, il = attribute.count; i < il; i++) {
6649
6732
  v.fromBufferAttribute(attribute, i);
6650
6733
  if (v.x === 0 && v.y === 0 && v.z === 0) {
@@ -7911,9 +7994,9 @@ var GLTFMeshGpuInstancing = class {
7911
7994
  const rotationAttr = new Float32Array(mesh.count * 4);
7912
7995
  const scaleAttr = new Float32Array(mesh.count * 3);
7913
7996
  const matrix = new Matrix46();
7914
- const position = new Vector38();
7997
+ const position = new Vector39();
7915
7998
  const quaternion = new Quaternion4();
7916
- const scale = new Vector38();
7999
+ const scale = new Vector39();
7917
8000
  for (let i = 0; i < mesh.count; i++) {
7918
8001
  mesh.getMatrixAt(i, matrix);
7919
8002
  matrix.decompose(position, quaternion, scale);
@@ -8906,7 +8989,7 @@ init_SpecialItems();
8906
8989
  init_BlockStates();
8907
8990
  init_MineRenderError();
8908
8991
  init_util();
8909
- import { Euler as Euler7 } from "three";
8992
+ import { Euler as Euler8 } from "three";
8910
8993
  function matchesCondition(condition, state) {
8911
8994
  return Object.entries(condition).every(([key, value]) => {
8912
8995
  if (Array.isArray(value)) {
@@ -8981,7 +9064,7 @@ var BlockStateResolver = class {
8981
9064
  return variants[variants.length - 1];
8982
9065
  }
8983
9066
  static rotation(variant) {
8984
- const rotation = new Euler7();
9067
+ const rotation = new Euler8();
8985
9068
  if (typeof variant.x !== "undefined") {
8986
9069
  rotation.x = toRadians(clampRotationDegrees(variant.x));
8987
9070
  }
@@ -9076,7 +9159,7 @@ var import_ts_deepmerge6 = __toESM(require_dist());
9076
9159
  init_MineRenderError();
9077
9160
  init_InstanceReference();
9078
9161
  init_AssetKey();
9079
- import { Euler as Euler8, Matrix4 as Matrix411, Quaternion as Quaternion5, Vector3 as Vector311 } from "three";
9162
+ import { Euler as Euler9, Matrix4 as Matrix411, Quaternion as Quaternion5, Vector3 as Vector312 } from "three";
9080
9163
  init_ModelCulling();
9081
9164
  init_FluidGeometry();
9082
9165
  init_Entities();
@@ -9144,6 +9227,21 @@ var BlockObject = class _BlockObject extends SceneObject {
9144
9227
  get blockEntities() {
9145
9228
  return this._entities;
9146
9229
  }
9230
+ /** Sets visibility for this block's model instances and block entities. */
9231
+ setVisible(visible) {
9232
+ this.visible = visible;
9233
+ for (const model of this._models) {
9234
+ if (isInstanceReference(model)) {
9235
+ model.setVisible(visible);
9236
+ } else {
9237
+ model.visible = visible;
9238
+ }
9239
+ }
9240
+ for (const entity of this._entities) {
9241
+ entity.visible = visible;
9242
+ }
9243
+ this.notifyDirty();
9244
+ }
9147
9245
  /**
9148
9246
  * Draws the block through the dataset's block-entity index. Returns false, leaving nothing behind,
9149
9247
  * when the block is not listed or one of its models cannot be loaded.
@@ -9177,6 +9275,7 @@ var BlockObject = class _BlockObject extends SceneObject {
9177
9275
  BlockEntities.matrix(resolved, this._entityPlacement);
9178
9276
  this._entities = created;
9179
9277
  this.placeEntities();
9278
+ this.setVisible(this.visible);
9180
9279
  return true;
9181
9280
  }
9182
9281
  placeEntities() {
@@ -9186,6 +9285,9 @@ var BlockObject = class _BlockObject extends SceneObject {
9186
9285
  }
9187
9286
  }
9188
9287
  get isOccluding() {
9288
+ if (!this.visible) {
9289
+ return false;
9290
+ }
9189
9291
  return this._models.some((model) => {
9190
9292
  const object = isInstanceReference(model) ? model.instanceable : model;
9191
9293
  return object.isOpaqueFullCube && this.getModelCullMask(model, 63) === 63;
@@ -9199,12 +9301,12 @@ var BlockObject = class _BlockObject extends SceneObject {
9199
9301
  getModelCullMask(model, worldMask) {
9200
9302
  const object = isInstanceReference(model) ? model.instanceable : model;
9201
9303
  if (object.options.displayPosition) return 0;
9202
- const position = new Vector311();
9304
+ const position = new Vector312();
9203
9305
  const rotation = new Quaternion5();
9204
- const scale = new Vector311();
9306
+ const scale = new Vector312();
9205
9307
  this.getModelMatrix(model).decompose(position, rotation, scale);
9206
- if (position.distanceToSquared(this.position) > 1e-10 || scale.distanceToSquared(new Vector311(1, 1, 1)) > 1e-10) return 0;
9207
- return ModelCulling.toLocalMask(worldMask, new Euler8().setFromQuaternion(rotation));
9308
+ if (position.distanceToSquared(this.position) > 1e-10 || scale.distanceToSquared(new Vector312(1, 1, 1)) > 1e-10) return 0;
9309
+ return ModelCulling.toLocalMask(worldMask, new Euler9().setFromQuaternion(rotation));
9208
9310
  }
9209
9311
  async setCullMask(worldMask) {
9210
9312
  worldMask &= 63;
@@ -9241,6 +9343,9 @@ var BlockObject = class _BlockObject extends SceneObject {
9241
9343
  this._models = replacements;
9242
9344
  this._cullMask = worldMask;
9243
9345
  this.removeModels(previous.filter((model) => !replacements.includes(model)));
9346
+ if (!this.visible) {
9347
+ this.setVisible(false);
9348
+ }
9244
9349
  this.notifyDirty();
9245
9350
  }
9246
9351
  get state() {
@@ -9276,6 +9381,9 @@ var BlockObject = class _BlockObject extends SceneObject {
9276
9381
  this._isInstanced ||= isInstanceReference(replacement);
9277
9382
  this._instanceCounter = this._isInstanced ? 1 : 0;
9278
9383
  if (previous) this.removeModels([previous]);
9384
+ if (!this.visible) {
9385
+ this.setVisible(false);
9386
+ }
9279
9387
  this.notifyDirty();
9280
9388
  }
9281
9389
  nextInstance() {
@@ -9304,6 +9412,7 @@ var BlockObject = class _BlockObject extends SceneObject {
9304
9412
  this._models.push(await this.createVariant(blockStateVariant));
9305
9413
  }
9306
9414
  await this.updateFluid(this._fluidSampler);
9415
+ this.setVisible(this.visible);
9307
9416
  }
9308
9417
  async hasGeometry(variant) {
9309
9418
  const modelKey = AssetKey.parse("models", variant.model);
@@ -12451,7 +12560,7 @@ function isMineRenderScene(obj) {
12451
12560
  }
12452
12561
 
12453
12562
  // src/renderer/Renderer.ts
12454
- import { AxesHelper as AxesHelper2, GridHelper, OrthographicCamera, PCFSoftShadowMap, PerspectiveCamera as PerspectiveCamera2, SRGBColorSpace as SRGBColorSpace6, Vector3 as Vector313, WebGLRenderer as WebGLRenderer2 } from "three";
12563
+ import { AxesHelper as AxesHelper2, GridHelper, OrthographicCamera, PCFSoftShadowMap, PerspectiveCamera as PerspectiveCamera2, SRGBColorSpace as SRGBColorSpace6, Vector3 as Vector314, WebGLRenderer as WebGLRenderer2 } from "three";
12455
12564
  var import_ts_deepmerge9 = __toESM(require_dist());
12456
12565
  init_util();
12457
12566
  init_Model();
@@ -12467,7 +12576,7 @@ import {
12467
12576
  Spherical,
12468
12577
  TOUCH,
12469
12578
  Vector2 as Vector25,
12470
- Vector3 as Vector312
12579
+ Vector3 as Vector313
12471
12580
  } from "three";
12472
12581
  var _changeEvent = { type: "change" };
12473
12582
  var _startEvent = { type: "start" };
@@ -12481,7 +12590,7 @@ var OrbitControls = class extends EventDispatcher {
12481
12590
  this.domElement = domElement;
12482
12591
  this.domElement.style.touchAction = "none";
12483
12592
  this.enabled = true;
12484
- this.target = new Vector312();
12593
+ this.target = new Vector313();
12485
12594
  this.minDistance = 0;
12486
12595
  this.maxDistance = Infinity;
12487
12596
  this.minZoom = 0;
@@ -12533,10 +12642,10 @@ var OrbitControls = class extends EventDispatcher {
12533
12642
  state = STATE.NONE;
12534
12643
  };
12535
12644
  this.update = function() {
12536
- const offset = new Vector312();
12537
- const quat = new Quaternion6().setFromUnitVectors(object.up, new Vector312(0, 1, 0));
12645
+ const offset = new Vector313();
12646
+ const quat = new Quaternion6().setFromUnitVectors(object.up, new Vector313(0, 1, 0));
12538
12647
  const quatInverse = quat.clone().invert();
12539
- const lastPosition = new Vector312();
12648
+ const lastPosition = new Vector313();
12540
12649
  const lastQuaternion = new Quaternion6();
12541
12650
  const twoPI = 2 * Math.PI;
12542
12651
  return function update() {
@@ -12626,7 +12735,7 @@ var OrbitControls = class extends EventDispatcher {
12626
12735
  const spherical = new Spherical();
12627
12736
  const sphericalDelta = new Spherical();
12628
12737
  let scale = 1;
12629
- const panOffset = new Vector312();
12738
+ const panOffset = new Vector313();
12630
12739
  let zoomChanged = false;
12631
12740
  const rotateStart = new Vector25();
12632
12741
  const rotateEnd = new Vector25();
@@ -12652,7 +12761,7 @@ var OrbitControls = class extends EventDispatcher {
12652
12761
  sphericalDelta.phi -= angle;
12653
12762
  }
12654
12763
  const panLeft = function() {
12655
- const v = new Vector312();
12764
+ const v = new Vector313();
12656
12765
  return function panLeft2(distance, objectMatrix) {
12657
12766
  v.setFromMatrixColumn(objectMatrix, 0);
12658
12767
  v.multiplyScalar(-distance);
@@ -12660,7 +12769,7 @@ var OrbitControls = class extends EventDispatcher {
12660
12769
  };
12661
12770
  }();
12662
12771
  const panUp = function() {
12663
- const v = new Vector312();
12772
+ const v = new Vector313();
12664
12773
  return function panUp2(distance, objectMatrix) {
12665
12774
  if (scope.screenSpacePanning === true) {
12666
12775
  v.setFromMatrixColumn(objectMatrix, 1);
@@ -12673,7 +12782,7 @@ var OrbitControls = class extends EventDispatcher {
12673
12782
  };
12674
12783
  }();
12675
12784
  const pan = function() {
12676
- const offset = new Vector312();
12785
+ const offset = new Vector313();
12677
12786
  return function pan2(deltaX, deltaY) {
12678
12787
  const element = scope.domElement;
12679
12788
  if (scope.object.isPerspectiveCamera) {
@@ -13164,8 +13273,8 @@ var Renderer = class _Renderer {
13164
13273
  top: void 0,
13165
13274
  bottom: void 0
13166
13275
  },
13167
- position: new Vector313(50, 50, 50),
13168
- lookingAt: new Vector313(0, 0, 0)
13276
+ position: new Vector314(50, 50, 50),
13277
+ lookingAt: new Vector314(0, 0, 0)
13169
13278
  },
13170
13279
  render: {
13171
13280
  fpsLimit: 60,
@@ -13957,13 +14066,13 @@ var AnvilParser = class {
13957
14066
  };
13958
14067
 
13959
14068
  // src/world/Chunk.ts
13960
- import { Vector3 as Vector316 } from "three";
14069
+ import { Vector3 as Vector317 } from "three";
13961
14070
  init_BlockStates();
13962
14071
  init_AssetKey();
13963
14072
 
13964
14073
  // src/world/MineRenderWorld.ts
13965
14074
  init_Model();
13966
- import { Vector3 as Vector315 } from "three";
14075
+ import { Vector3 as Vector316 } from "three";
13967
14076
  init_BatchedExecutor();
13968
14077
  init_AssetKey();
13969
14078
  init_BlockStates();
@@ -13973,7 +14082,7 @@ init_CubeFace();
13973
14082
  init_AssetKey();
13974
14083
  init_Models();
13975
14084
  init_CubeFace();
13976
- import { Matrix4 as Matrix412, Vector3 as Vector314 } from "three";
14085
+ import { Matrix4 as Matrix412, Vector3 as Vector315 } from "three";
13977
14086
  init_ModelCulling();
13978
14087
  init_ModelObject();
13979
14088
  init_UVMapper();
@@ -14041,7 +14150,7 @@ var SectionModels = class {
14041
14150
  const cullFaces = CUBE_FACES.map((face) => {
14042
14151
  const local = CUBE_FACES.findIndex((name) => name === atlas.model.elements[0].faces[face]?.cullface);
14043
14152
  if (local < 0) return 0;
14044
- const normal = new Vector314(...CUBE_FACE_OFFSETS[local]).applyEuler(rotation);
14153
+ const normal = new Vector315(...CUBE_FACE_OFFSETS[local]).applyEuler(rotation);
14045
14154
  const world = CUBE_FACE_OFFSETS.findIndex(([x, y, z]) => Math.abs(normal.x - x) < 1e-6 && Math.abs(normal.y - y) < 1e-6 && Math.abs(normal.z - z) < 1e-6);
14046
14155
  return 1 << world;
14047
14156
  });
@@ -14071,20 +14180,20 @@ var MineRenderWorld = class {
14071
14180
  }
14072
14181
  getBlockAt(posOrX, y, z) {
14073
14182
  if (typeof posOrX == "number") {
14074
- return this.getBlockAt(new Vector315(posOrX, y, z));
14183
+ return this.getBlockAt(new Vector316(posOrX, y, z));
14075
14184
  }
14076
14185
  if (isTripleArray(posOrX)) {
14077
- return this.getBlockAt(new Vector315(posOrX[0], posOrX[1], posOrX[2]));
14186
+ return this.getBlockAt(new Vector316(posOrX[0], posOrX[1], posOrX[2]));
14078
14187
  }
14079
14188
  this.validatePosBounds(posOrX);
14080
14189
  return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
14081
14190
  }
14082
14191
  async setBlockAt(posOrX, yOrBlock, z, block) {
14083
14192
  if (typeof posOrX == "number") {
14084
- return this.setBlockAt(new Vector315(posOrX, yOrBlock, z), block);
14193
+ return this.setBlockAt(new Vector316(posOrX, yOrBlock, z), block);
14085
14194
  }
14086
14195
  if (isTripleArray(posOrX)) {
14087
- return this.setBlockAt(new Vector315(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
14196
+ return this.setBlockAt(new Vector316(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
14088
14197
  }
14089
14198
  return this.placeBlock(posOrX, yOrBlock);
14090
14199
  }
@@ -14093,6 +14202,16 @@ var MineRenderWorld = class {
14093
14202
  const chunk = Chunk.isAir(value) ? this.getChunkAt(pos) : this.getOrCreateChunkAt(pos);
14094
14203
  return chunk?.setBlockInChunkAt(chunk.worldPosToChunkPos(pos), value, pos, onBlocksChanged);
14095
14204
  }
14205
+ async setBlockVisibleAt(posOrX, yOrVisible, z, visible) {
14206
+ if (typeof posOrX === "number") {
14207
+ return this.setBlockVisibleAt(new Vector316(posOrX, yOrVisible, z), visible);
14208
+ }
14209
+ if (isTripleArray(posOrX)) {
14210
+ return this.setBlockVisibleAt(new Vector316(...posOrX), yOrVisible);
14211
+ }
14212
+ this.validatePosBounds(posOrX);
14213
+ await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible);
14214
+ }
14096
14215
  async placeMultiBlock(multiblock, useBatches = true, executor) {
14097
14216
  const changes = /* @__PURE__ */ new Map();
14098
14217
  try {
@@ -14105,7 +14224,7 @@ var MineRenderWorld = class {
14105
14224
  const collect = async (positions2) => {
14106
14225
  for (const pos of positions2) changes.set(pos.toArray().join(","), pos);
14107
14226
  };
14108
- const place = (block) => this.placeBlock(new Vector315(...block.position), block, collect);
14227
+ const place = (block) => this.placeBlock(new Vector316(...block.position), block, collect);
14109
14228
  const keys = /* @__PURE__ */ new Map();
14110
14229
  for (const block of multiblock.blocks) {
14111
14230
  if (Chunk.isAir(block)) continue;
@@ -14183,13 +14302,13 @@ var MineRenderWorld = class {
14183
14302
  for (const pos of positions) {
14184
14303
  this.pendingCulling.set(pos.toArray().join(","), pos.clone());
14185
14304
  for (const offset of CUBE_FACE_OFFSETS) {
14186
- const neighbor = pos.clone().add(new Vector315(...offset));
14305
+ const neighbor = pos.clone().add(new Vector316(...offset));
14187
14306
  this.pendingCulling.set(neighbor.toArray().join(","), neighbor);
14188
14307
  }
14189
14308
  for (let y = -1; y <= 1; y++) {
14190
14309
  for (let z = -1; z <= 1; z++) {
14191
14310
  for (let x = -1; x <= 1; x++) {
14192
- const neighbor = pos.clone().add(new Vector315(x, y, z));
14311
+ const neighbor = pos.clone().add(new Vector316(x, y, z));
14193
14312
  if (this.getBlockAt(neighbor)?.object?.fluidKind) {
14194
14313
  this.pendingCulling.set(neighbor.toArray().join(","), neighbor);
14195
14314
  }
@@ -14208,12 +14327,14 @@ var MineRenderWorld = class {
14208
14327
  if (!chunk) continue;
14209
14328
  changed.add(chunk);
14210
14329
  const block = chunk.getBlockAt(pos);
14211
- if (!block) continue;
14330
+ if (!block || !chunk.isBlockVisibleAt(pos)) {
14331
+ continue;
14332
+ }
14212
14333
  if (block.object?.fluidKind) {
14213
14334
  await block.object.updateFluid((x, y, z) => {
14214
- const neighbor = pos.clone().add(new Vector315(x, y, z));
14335
+ const neighbor = pos.clone().add(new Vector316(x, y, z));
14215
14336
  const section = this.getChunkAt(neighbor);
14216
- const object = section?.getBlockAt(neighbor)?.object;
14337
+ const object = section?.isBlockVisibleAt(neighbor) ? section.getBlockAt(neighbor)?.object : void 0;
14217
14338
  return {
14218
14339
  fluid: object?.fluidKind,
14219
14340
  level: object?.fluidLevel,
@@ -14223,7 +14344,7 @@ var MineRenderWorld = class {
14223
14344
  }
14224
14345
  let mask = 0;
14225
14346
  for (const [face, offset] of CUBE_FACE_OFFSETS.entries()) {
14226
- const neighbor = pos.clone().add(new Vector315(...offset));
14347
+ const neighbor = pos.clone().add(new Vector316(...offset));
14227
14348
  if (this.getChunkAt(neighbor)?.isOccludingAt(neighbor)) {
14228
14349
  mask |= 1 << face;
14229
14350
  }
@@ -14257,14 +14378,14 @@ var MineRenderWorld = class {
14257
14378
  return this._chunks.get(this.worldPosToChunkKey(pos));
14258
14379
  }
14259
14380
  static worldToScenePosition(pos) {
14260
- return new Vector315(
14381
+ return new Vector316(
14261
14382
  pos.x * 16,
14262
14383
  pos.y * 16,
14263
14384
  pos.z * 16
14264
14385
  );
14265
14386
  }
14266
14387
  static sceneToWorldPosition(pos) {
14267
- return new Vector315(
14388
+ return new Vector316(
14268
14389
  pos.x / 16,
14269
14390
  pos.y / 16,
14270
14391
  pos.z / 16
@@ -14400,6 +14521,7 @@ var Chunk = class _Chunk {
14400
14521
  this.data = new ChunkData();
14401
14522
  this.renderedBlocks = /* @__PURE__ */ new Map();
14402
14523
  this.sectionBlocks = /* @__PURE__ */ new Map();
14524
+ this.hiddenBlocks = /* @__PURE__ */ new Set();
14403
14525
  this.meshDirty = false;
14404
14526
  this.scene = scene;
14405
14527
  this.x = x;
@@ -14408,10 +14530,10 @@ var Chunk = class _Chunk {
14408
14530
  }
14409
14531
  getBlockAt(posOrX, y, z) {
14410
14532
  if (typeof posOrX == "number") {
14411
- return this.getBlockAt(new Vector316(posOrX, y, z));
14533
+ return this.getBlockAt(new Vector317(posOrX, y, z));
14412
14534
  }
14413
14535
  if (isTripleArray(posOrX)) {
14414
- return this.getBlockAt(new Vector316(posOrX[0], posOrX[1], posOrX[2]));
14536
+ return this.getBlockAt(new Vector317(posOrX[0], posOrX[1], posOrX[2]));
14415
14537
  }
14416
14538
  const pos = this.worldPosToChunkPos(posOrX);
14417
14539
  const index = _Chunk.chunkPosToBlockIndex(pos);
@@ -14419,10 +14541,10 @@ var Chunk = class _Chunk {
14419
14541
  }
14420
14542
  async setBlockAt(posOrX, yOrBlock, z, block) {
14421
14543
  if (typeof posOrX == "number") {
14422
- return this.setBlockAt(new Vector316(posOrX, yOrBlock, z), block);
14544
+ return this.setBlockAt(new Vector317(posOrX, yOrBlock, z), block);
14423
14545
  }
14424
14546
  if (isTripleArray(posOrX)) {
14425
- return this.setBlockAt(new Vector316(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
14547
+ return this.setBlockAt(new Vector317(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
14426
14548
  }
14427
14549
  const worldPos = posOrX;
14428
14550
  const pos = this.worldPosToChunkPos(worldPos);
@@ -14437,6 +14559,7 @@ var Chunk = class _Chunk {
14437
14559
  worldPos = this.chunkPosToWorldPos(pos);
14438
14560
  }
14439
14561
  const index = _Chunk.chunkPosToBlockIndex(pos);
14562
+ this.hiddenBlocks.delete(index);
14440
14563
  this.data.set(index, block);
14441
14564
  const readBlock = this.data.snapshot(index);
14442
14565
  this.renderedBlocks.get(index)?.object?.removeFromScene();
@@ -14478,9 +14601,31 @@ var Chunk = class _Chunk {
14478
14601
  await onBlocksChanged?.([worldPos]);
14479
14602
  }
14480
14603
  }
14604
+ async setBlockVisibleAt(pos, visible) {
14605
+ const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
14606
+ const block = this.renderedBlocks.get(index);
14607
+ if (!block || visible === !this.hiddenBlocks.has(index)) {
14608
+ return;
14609
+ }
14610
+ if (visible) {
14611
+ this.hiddenBlocks.delete(index);
14612
+ } else {
14613
+ this.hiddenBlocks.add(index);
14614
+ }
14615
+ block.object?.setVisible(visible);
14616
+ if (this.sectionBlocks.has(index)) {
14617
+ this.meshDirty = true;
14618
+ }
14619
+ this.scene.dirty = true;
14620
+ await this.onBlocksChanged?.([pos]);
14621
+ }
14622
+ isBlockVisibleAt(pos) {
14623
+ const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
14624
+ return this.renderedBlocks.has(index) && !this.hiddenBlocks.has(index);
14625
+ }
14481
14626
  isOccludingAt(pos) {
14482
14627
  const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
14483
- return this.sectionBlocks.has(index) || (this.renderedBlocks.get(index)?.object?.isOccluding ?? false);
14628
+ return !this.hiddenBlocks.has(index) && (this.sectionBlocks.has(index) || (this.renderedBlocks.get(index)?.object?.isOccluding ?? false));
14484
14629
  }
14485
14630
  async setCullMaskAt(pos, mask) {
14486
14631
  const index = _Chunk.chunkPosToBlockIndex(this.worldPosToChunkPos(pos));
@@ -14496,7 +14641,10 @@ var Chunk = class _Chunk {
14496
14641
  }
14497
14642
  rebuildSectionMesh() {
14498
14643
  if (!this.meshDirty) return;
14499
- const next = this.sectionBlocks.size ? SectionMesh.build([...this.sectionBlocks.values()], this.sectionModels.maxAtlasSize) : void 0;
14644
+ const next = this.sectionBlocks.size ? SectionMesh.build(
14645
+ [...this.sectionBlocks.values()].filter((entry) => !this.hiddenBlocks.has(entry.index)),
14646
+ this.sectionModels.maxAtlasSize
14647
+ ) : void 0;
14500
14648
  this.sectionMesh?.dispose();
14501
14649
  this.sectionMesh = next;
14502
14650
  if (next) {
@@ -14508,7 +14656,7 @@ var Chunk = class _Chunk {
14508
14656
  }
14509
14657
  async clear(onBlocksChanged = this.onBlocksChanged) {
14510
14658
  const positions = [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
14511
- new Vector316(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
14659
+ new Vector317(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
14512
14660
  ));
14513
14661
  for (const info of this.renderedBlocks.values()) info.object?.removeFromScene();
14514
14662
  this.sectionBlocks.clear();
@@ -14516,6 +14664,7 @@ var Chunk = class _Chunk {
14516
14664
  this.sectionMesh = void 0;
14517
14665
  this.meshDirty = false;
14518
14666
  this.renderedBlocks.clear();
14667
+ this.hiddenBlocks.clear();
14519
14668
  this.data.clear();
14520
14669
  await onBlocksChanged?.(positions);
14521
14670
  }
@@ -14532,14 +14681,14 @@ var Chunk = class _Chunk {
14532
14681
  return pos.y * 16 * 16 + pos.z * 16 + pos.x;
14533
14682
  }
14534
14683
  worldPosToChunkPos(pos) {
14535
- return new Vector316(
14684
+ return new Vector317(
14536
14685
  pos.x - this.x * 16,
14537
14686
  pos.y - this.y * 16,
14538
14687
  pos.z - this.z * 16
14539
14688
  );
14540
14689
  }
14541
14690
  chunkPosToWorldPos(pos) {
14542
- return new Vector316(
14691
+ return new Vector317(
14543
14692
  this.x * 16 + pos.x,
14544
14693
  this.y * 16 + pos.y,
14545
14694
  this.z * 16 + pos.z