minerender 2.1.0-alpha.37 → 2.1.0-alpha.38

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.
@@ -142,6 +142,7 @@ __export(index_node_exports, {
142
142
  BlockTints: () => BlockTints,
143
143
  BrowserArchiveProxy: () => BrowserArchiveProxy,
144
144
  CUBE_FACES: () => CUBE_FACES,
145
+ CUBE_FACE_OFFSETS: () => CUBE_FACE_OFFSETS,
145
146
  Caching: () => Caching,
146
147
  CanvasImage: () => CanvasImage,
147
148
  Chunk: () => Chunk,
@@ -175,6 +176,7 @@ __export(index_node_exports, {
175
176
  MineRenderWorld: () => MineRenderWorld,
176
177
  MinecraftCubeTexture: () => MinecraftCubeTexture,
177
178
  MinecraftFaceUV: () => MinecraftFaceUV,
179
+ ModelCulling: () => ModelCulling,
178
180
  ModelGenerator: () => ModelGenerator,
179
181
  ModelMerger: () => ModelMerger,
180
182
  ModelObject: () => ModelObject,
@@ -436,6 +438,14 @@ var CubeFaceIndex = /* @__PURE__ */ ((CubeFaceIndex2) => {
436
438
  return CubeFaceIndex2;
437
439
  })(CubeFaceIndex || {});
438
440
  var CUBE_FACES = Object.values(CubeFace);
441
+ var CUBE_FACE_OFFSETS = [
442
+ [1, 0, 0],
443
+ [-1, 0, 0],
444
+ [0, 1, 0],
445
+ [0, -1, 0],
446
+ [0, 0, 1],
447
+ [0, 0, -1]
448
+ ];
439
449
 
440
450
  // src/Disposable.ts
441
451
  function isDisposable(obj) {
@@ -4007,6 +4017,42 @@ function isQuadArray(obj) {
4007
4017
  return Array.isArray(obj) && obj.length === 4;
4008
4018
  }
4009
4019
 
4020
+ // src/model/ModelCulling.ts
4021
+ var import_three16 = require("three");
4022
+ var ModelCulling = class {
4023
+ static toLocalMask(worldMask, rotation) {
4024
+ let localMask = 0;
4025
+ for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
4026
+ const normal = new import_three16.Vector3(...offset).applyEuler(rotation);
4027
+ 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);
4028
+ if (worldFace < 0) return 0;
4029
+ if (worldMask & 1 << worldFace) localMask |= 1 << localFace;
4030
+ }
4031
+ return localMask;
4032
+ }
4033
+ static isOpaqueFullCube(atlas) {
4034
+ if (!atlas || atlas.hasTransparency !== false || atlas.model.elements?.length !== 1) return false;
4035
+ const element = atlas.model.elements[0];
4036
+ if (element.from.length !== 3 || !element.from.every((value) => value === 0) || element.to.length !== 3 || !element.to.every((value) => value === 16) || element.rotation && element.rotation.angle !== 0 || element.mappedUv?.length !== 48 || !element.mappedUv.every(Number.isFinite)) return false;
4037
+ if (!(atlas.image.width > 0 && atlas.image.height > 0)) return false;
4038
+ return CUBE_FACES.every((face, faceIndex) => {
4039
+ const texture = element.faces[face]?.texture;
4040
+ if (!texture?.startsWith("#")) return false;
4041
+ const key = texture.slice(1);
4042
+ const position = atlas.positions[key];
4043
+ const size = atlas.sizes[key];
4044
+ if (position?.length !== 2 || !position.every(Number.isFinite) || size?.length !== 2 || !size.every((value) => value > 0 && Number.isFinite(value))) return false;
4045
+ for (let vertex = 0; vertex < 4; vertex++) {
4046
+ const uvIndex = (faceIndex * 4 + vertex) * 2;
4047
+ const x = element.mappedUv[uvIndex] * atlas.image.width;
4048
+ const y = (1 - element.mappedUv[uvIndex + 1]) * atlas.image.height;
4049
+ if (x < position[0] - 1e-6 || x > position[0] + size[0] + 1e-6 || y < position[1] - 1e-6 || y > position[1] + size[1] + 1e-6) return false;
4050
+ }
4051
+ return true;
4052
+ });
4053
+ }
4054
+ };
4055
+
4010
4056
  // src/model/block/blockTints.json
4011
4057
  var blockTints_default = {
4012
4058
  "minecraft:large_fern": { source: "grass" },
@@ -4093,10 +4139,10 @@ var BlockTints = class {
4093
4139
  };
4094
4140
 
4095
4141
  // src/model/scene/ModelObject.ts
4096
- var import_three17 = require("three");
4142
+ var import_three18 = require("three");
4097
4143
 
4098
4144
  // src/three/BufferGeometryUtils.js
4099
- var import_three16 = require("three");
4145
+ var import_three17 = require("three");
4100
4146
  function computeTangents(geometry) {
4101
4147
  geometry.computeTangents();
4102
4148
  console.warn("THREE.BufferGeometryUtils: .computeTangents() has been removed. Use BufferGeometry.computeTangents() instead.");
@@ -4108,7 +4154,7 @@ function mergeBufferGeometries(geometries, useGroups = false) {
4108
4154
  const attributes = {};
4109
4155
  const morphAttributes = {};
4110
4156
  const morphTargetsRelative = geometries[0].morphTargetsRelative;
4111
- const mergedGeometry = new import_three16.BufferGeometry();
4157
+ const mergedGeometry = new import_three17.BufferGeometry();
4112
4158
  let offset = 0;
4113
4159
  for (let i = 0; i < geometries.length; ++i) {
4114
4160
  const geometry = geometries[i];
@@ -4232,7 +4278,7 @@ function mergeBufferAttributes(attributes) {
4232
4278
  array.set(attributes[i].array, offset);
4233
4279
  offset += attributes[i].array.length;
4234
4280
  }
4235
- return new import_three16.BufferAttribute(array, itemSize, normalized);
4281
+ return new import_three17.BufferAttribute(array, itemSize, normalized);
4236
4282
  }
4237
4283
  function interleaveAttributes(attributes) {
4238
4284
  let TypedArray;
@@ -4248,7 +4294,7 @@ function interleaveAttributes(attributes) {
4248
4294
  arrayLength += attribute.array.length;
4249
4295
  stride += attribute.itemSize;
4250
4296
  }
4251
- const interleavedBuffer = new import_three16.InterleavedBuffer(new TypedArray(arrayLength), stride);
4297
+ const interleavedBuffer = new import_three17.InterleavedBuffer(new TypedArray(arrayLength), stride);
4252
4298
  let offset = 0;
4253
4299
  const res = [];
4254
4300
  const getters = ["getX", "getY", "getZ", "getW"];
@@ -4257,7 +4303,7 @@ function interleaveAttributes(attributes) {
4257
4303
  const attribute = attributes[j];
4258
4304
  const itemSize = attribute.itemSize;
4259
4305
  const count = attribute.count;
4260
- const iba = new import_three16.InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, attribute.normalized);
4306
+ const iba = new import_three17.InterleavedBufferAttribute(interleavedBuffer, itemSize, offset, attribute.normalized);
4261
4307
  res.push(iba);
4262
4308
  offset += itemSize;
4263
4309
  for (let c = 0; c < count; c++) {
@@ -4341,13 +4387,13 @@ function mergeVertices(geometry, tolerance = 1e-4) {
4341
4387
  const name = attributeNames[i];
4342
4388
  const oldAttribute = geometry.getAttribute(name);
4343
4389
  const buffer = new oldAttribute.array.constructor(attrArrays[name]);
4344
- const attribute = new import_three16.BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
4390
+ const attribute = new import_three17.BufferAttribute(buffer, oldAttribute.itemSize, oldAttribute.normalized);
4345
4391
  result.setAttribute(name, attribute);
4346
4392
  if (name in morphAttrsArrays) {
4347
4393
  for (let j = 0; j < morphAttrsArrays[name].length; j++) {
4348
4394
  const oldMorphAttribute = geometry.morphAttributes[name][j];
4349
4395
  const buffer2 = new oldMorphAttribute.array.constructor(morphAttrsArrays[name][j]);
4350
- const morphAttribute = new import_three16.BufferAttribute(buffer2, oldMorphAttribute.itemSize, oldMorphAttribute.normalized);
4396
+ const morphAttribute = new import_three17.BufferAttribute(buffer2, oldMorphAttribute.itemSize, oldMorphAttribute.normalized);
4351
4397
  result.morphAttributes[name][j] = morphAttribute;
4352
4398
  }
4353
4399
  }
@@ -4356,11 +4402,11 @@ function mergeVertices(geometry, tolerance = 1e-4) {
4356
4402
  return result;
4357
4403
  }
4358
4404
  function toTrianglesDrawMode(geometry, drawMode) {
4359
- if (drawMode === import_three16.TrianglesDrawMode) {
4405
+ if (drawMode === import_three17.TrianglesDrawMode) {
4360
4406
  console.warn("THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.");
4361
4407
  return geometry;
4362
4408
  }
4363
- if (drawMode === import_three16.TriangleFanDrawMode || drawMode === import_three16.TriangleStripDrawMode) {
4409
+ if (drawMode === import_three17.TriangleFanDrawMode || drawMode === import_three17.TriangleStripDrawMode) {
4364
4410
  let index = geometry.getIndex();
4365
4411
  if (index === null) {
4366
4412
  const indices = [];
@@ -4378,7 +4424,7 @@ function toTrianglesDrawMode(geometry, drawMode) {
4378
4424
  }
4379
4425
  const numberOfTriangles = index.count - 2;
4380
4426
  const newIndices = [];
4381
- if (drawMode === import_three16.TriangleFanDrawMode) {
4427
+ if (drawMode === import_three17.TriangleFanDrawMode) {
4382
4428
  for (let i = 1; i <= numberOfTriangles; i++) {
4383
4429
  newIndices.push(index.getX(0));
4384
4430
  newIndices.push(index.getX(i));
@@ -4414,15 +4460,15 @@ function computeMorphedAttributes(object) {
4414
4460
  console.error("THREE.BufferGeometryUtils: Geometry is not of type BufferGeometry.");
4415
4461
  return null;
4416
4462
  }
4417
- const _vA = new import_three16.Vector3();
4418
- const _vB = new import_three16.Vector3();
4419
- const _vC = new import_three16.Vector3();
4420
- const _tempA = new import_three16.Vector3();
4421
- const _tempB = new import_three16.Vector3();
4422
- const _tempC = new import_three16.Vector3();
4423
- const _morphA = new import_three16.Vector3();
4424
- const _morphB = new import_three16.Vector3();
4425
- const _morphC = new import_three16.Vector3();
4463
+ const _vA = new import_three17.Vector3();
4464
+ const _vB = new import_three17.Vector3();
4465
+ const _vC = new import_three17.Vector3();
4466
+ const _tempA = new import_three17.Vector3();
4467
+ const _tempB = new import_three17.Vector3();
4468
+ const _tempC = new import_three17.Vector3();
4469
+ const _morphA = new import_three17.Vector3();
4470
+ const _morphB = new import_three17.Vector3();
4471
+ const _morphC = new import_three17.Vector3();
4426
4472
  function _calculateMorphedAttributeData(object2, material2, attribute, morphAttribute, morphTargetsRelative2, a2, b2, c2, modifiedAttributeArray) {
4427
4473
  _vA.fromBufferAttribute(attribute, a2);
4428
4474
  _vB.fromBufferAttribute(attribute, b2);
@@ -4617,8 +4663,8 @@ function computeMorphedAttributes(object) {
4617
4663
  }
4618
4664
  }
4619
4665
  }
4620
- const morphedPositionAttribute = new import_three16.Float32BufferAttribute(modifiedPosition, 3);
4621
- const morphedNormalAttribute = new import_three16.Float32BufferAttribute(modifiedNormal, 3);
4666
+ const morphedPositionAttribute = new import_three17.Float32BufferAttribute(modifiedPosition, 3);
4667
+ const morphedNormalAttribute = new import_three17.Float32BufferAttribute(modifiedNormal, 3);
4622
4668
  return {
4623
4669
  positionAttribute,
4624
4670
  normalAttribute,
@@ -4651,6 +4697,9 @@ var ModelObject = class _ModelObject extends SceneObject {
4651
4697
  get textureAtlas() {
4652
4698
  return this.atlas;
4653
4699
  }
4700
+ get isOpaqueFullCube() {
4701
+ return !this.options.displayPosition && ModelCulling.isOpaqueFullCube(this.atlas);
4702
+ }
4654
4703
  //TODO: support for replacing textures
4655
4704
  async loadTextures() {
4656
4705
  this.atlas = await UVMapper.getAtlas(this.originalModel);
@@ -4664,8 +4713,17 @@ var ModelObject = class _ModelObject extends SceneObject {
4664
4713
  if (this.atlas.model.elements) {
4665
4714
  this.atlas.model.elements?.forEach((el) => {
4666
4715
  const elGeo = this._getBoxGeometryFromElement(el).clone();
4716
+ if (this.options.cullMask) {
4717
+ const indices = Array.from(elGeo.getIndex().array);
4718
+ elGeo.setIndex(indices.filter((_, index) => {
4719
+ const face = CUBE_FACES[Math.floor(index / 6)];
4720
+ const direction = CUBE_FACES.findIndex((name) => name === el.faces[face]?.cullface);
4721
+ return direction < 0 || !(this.options.cullMask & 1 << direction);
4722
+ }));
4723
+ elGeo.clearGroups();
4724
+ }
4667
4725
  if (this.options.uvLockRotation) {
4668
- UVMapper.lockUvs(elGeo, el.faces, this.atlas, new import_three17.Euler(...this.options.uvLockRotation));
4726
+ UVMapper.lockUvs(elGeo, el.faces, this.atlas, new import_three18.Euler(...this.options.uvLockRotation));
4669
4727
  }
4670
4728
  if (this.options.tints) {
4671
4729
  const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
@@ -4674,19 +4732,19 @@ var ModelObject = class _ModelObject extends SceneObject {
4674
4732
  if (tintIndex === void 0 || tintIndex < 0) continue;
4675
4733
  const tint = this.options.tints[tintIndex];
4676
4734
  if (tint === void 0) continue;
4677
- const color = new import_three17.Color(tint);
4735
+ const color = new import_three18.Color(tint);
4678
4736
  for (let vertex = 0; vertex < 4; vertex++) {
4679
4737
  color.toArray(colors, (faceIndex * 4 + vertex) * 3);
4680
4738
  }
4681
4739
  }
4682
- elGeo.setAttribute("color", new import_three17.BufferAttribute(colors, 3));
4740
+ elGeo.setAttribute("color", new import_three18.BufferAttribute(colors, 3));
4683
4741
  }
4684
- elGeo.applyMatrix4(new import_three17.Matrix4().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4685
- elGeo.applyMatrix4(new import_three17.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
4742
+ elGeo.applyMatrix4(new import_three18.Matrix4().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4743
+ elGeo.applyMatrix4(new import_three18.Matrix4().makeTranslation(el.from[0], el.from[1], el.from[2]));
4686
4744
  if (el.rotation) {
4687
4745
  applyElementRotation(el.rotation, elGeo);
4688
4746
  }
4689
- elGeo.applyMatrix4(new import_three17.Matrix4().makeTranslation(-8, -8, -8));
4747
+ elGeo.applyMatrix4(new import_three18.Matrix4().makeTranslation(-8, -8, -8));
4690
4748
  if (displayTransform) DisplayTransforms.apply(elGeo, displayTransform);
4691
4749
  if (this.options.mergeMeshes) {
4692
4750
  allGeos.push(elGeo);
@@ -4708,7 +4766,7 @@ var ModelObject = class _ModelObject extends SceneObject {
4708
4766
  if (allGeos.length > 0) {
4709
4767
  combinedGeo = mergeBufferGeometries(allGeos);
4710
4768
  } else {
4711
- combinedGeo = new import_three17.BoxGeometry(16, 16, 16);
4769
+ combinedGeo = new import_three18.BoxGeometry(16, 16, 16);
4712
4770
  if (displayTransform) DisplayTransforms.apply(combinedGeo, displayTransform);
4713
4771
  }
4714
4772
  combinedGeo.computeBoundingBox();
@@ -4761,7 +4819,7 @@ function isModelObject(obj) {
4761
4819
 
4762
4820
  // src/model/block/scene/BlockObject.ts
4763
4821
  var import_ts_deepmerge6 = __toESM(require_dist());
4764
- var import_three18 = require("three");
4822
+ var import_three19 = require("three");
4765
4823
  var p10 = prefix("BlockObject");
4766
4824
  function matchesCondition(condition, state) {
4767
4825
  return Object.entries(condition).every(([key, value]) => {
@@ -4786,6 +4844,7 @@ var BlockObject = class _BlockObject extends SceneObject {
4786
4844
  this._instanceModel = [];
4787
4845
  this._variants = [];
4788
4846
  this._models = [];
4847
+ this._cullMask = 0;
4789
4848
  this.options = (0, import_ts_deepmerge6.default)({}, _BlockObject.DEFAULT_OPTIONS, options ?? {});
4790
4849
  }
4791
4850
  static {
@@ -4824,12 +4883,69 @@ var BlockObject = class _BlockObject extends SceneObject {
4824
4883
  super.removeFromScene();
4825
4884
  }
4826
4885
  clearModels() {
4827
- for (const model of this._models.splice(0)) {
4886
+ this.removeModels(this._models.splice(0));
4887
+ this._isInstanced = false;
4888
+ this._instanceCounter = 0;
4889
+ }
4890
+ removeModels(models) {
4891
+ for (const model of models) {
4828
4892
  model.removeFromScene();
4829
4893
  if (!isInstanceReference(model)) model.dispose();
4830
4894
  }
4831
- this._isInstanced = false;
4832
- this._instanceCounter = 0;
4895
+ }
4896
+ get isOccluding() {
4897
+ return this._models.some((model) => {
4898
+ const object = isInstanceReference(model) ? model.instanceable : model;
4899
+ return object.isOpaqueFullCube && this.getModelCullMask(model, 63) === 63;
4900
+ });
4901
+ }
4902
+ getModelMatrix(model) {
4903
+ if (isInstanceReference(model)) return model.getMatrix();
4904
+ if (model.matrixAutoUpdate) model.updateMatrix();
4905
+ return model.matrix.clone();
4906
+ }
4907
+ getModelCullMask(model, worldMask) {
4908
+ const object = isInstanceReference(model) ? model.instanceable : model;
4909
+ if (object.options.displayPosition) return 0;
4910
+ const position = new import_three19.Vector3();
4911
+ const rotation = new import_three19.Quaternion();
4912
+ const scale = new import_three19.Vector3();
4913
+ this.getModelMatrix(model).decompose(position, rotation, scale);
4914
+ if (position.distanceToSquared(this.position) > 1e-10 || scale.distanceToSquared(new import_three19.Vector3(1, 1, 1)) > 1e-10) return 0;
4915
+ return ModelCulling.toLocalMask(worldMask, new import_three19.Euler().setFromQuaternion(rotation));
4916
+ }
4917
+ async setCullMask(worldMask) {
4918
+ worldMask &= 63;
4919
+ const replacements = [];
4920
+ try {
4921
+ for (const model of this._models) {
4922
+ const object = isInstanceReference(model) ? model.instanceable : model;
4923
+ const cullMask = this.getModelCullMask(model, worldMask);
4924
+ if (cullMask === (object.options.cullMask ?? 0)) {
4925
+ replacements.push(model);
4926
+ continue;
4927
+ }
4928
+ const matrix = this.getModelMatrix(model);
4929
+ const replacement = await this.scene.addModel(object.originalModel, { ...object.options, cullMask });
4930
+ replacements.push(replacement);
4931
+ if (isInstanceReference(replacement)) {
4932
+ replacement.setMatrix(matrix);
4933
+ } else {
4934
+ replacement.matrix.copy(matrix);
4935
+ matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);
4936
+ replacement.matrixAutoUpdate = object.matrixAutoUpdate;
4937
+ replacement.visible = object.visible;
4938
+ }
4939
+ }
4940
+ } catch (error) {
4941
+ this.removeModels(replacements.filter((model) => !this._models.includes(model)));
4942
+ throw error;
4943
+ }
4944
+ const previous = this._models;
4945
+ this._models = replacements;
4946
+ this._cullMask = worldMask;
4947
+ this.removeModels(previous.filter((model) => !replacements.includes(model)));
4948
+ this.notifyDirty();
4833
4949
  }
4834
4950
  get state() {
4835
4951
  return this._state;
@@ -4909,7 +5025,7 @@ var BlockObject = class _BlockObject extends SceneObject {
4909
5025
  await this.createVariant(variant);
4910
5026
  }
4911
5027
  async createVariant(variant) {
4912
- const rotation = new import_three18.Euler();
5028
+ const rotation = new import_three19.Euler();
4913
5029
  if (typeof variant.x !== "undefined") {
4914
5030
  rotation.x = toRadians(clampRotationDegrees(variant.x));
4915
5031
  }
@@ -4922,7 +5038,8 @@ var BlockObject = class _BlockObject extends SceneObject {
4922
5038
  const options = {
4923
5039
  ...this.options,
4924
5040
  tints: model ? await BlockTints.get(this.blockState.key, this.state, model, this.options.tints) : this.options.tints,
4925
- uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0) ? [rotation.x, rotation.y, rotation.z] : void 0
5041
+ uvLockRotation: variant.uvlock && (rotation.x !== 0 || rotation.y !== 0) ? [rotation.x, rotation.y, rotation.z] : void 0,
5042
+ cullMask: this.options.displayPosition ? 0 : ModelCulling.toLocalMask(this._cullMask, rotation)
4926
5043
  };
4927
5044
  const obj = await this.scene.addModel(model, options);
4928
5045
  if (isInstanceReference(obj) || obj.isInstanced) {
@@ -4999,7 +5116,7 @@ var BlockObject = class _BlockObject extends SceneObject {
4999
5116
  setPositionRotationScaleAt(index, position, rotation, scale) {
5000
5117
  super.setPositionRotationScaleAt(index, position, rotation, scale);
5001
5118
  }
5002
- getMatrixAt(index, matrix = new import_three18.Matrix4()) {
5119
+ getMatrixAt(index, matrix = new import_three19.Matrix4()) {
5003
5120
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
5004
5121
  const child = this._models[0];
5005
5122
  if (child && isModelObject(child)) {
@@ -5074,7 +5191,7 @@ var StructureParser = class {
5074
5191
  };
5075
5192
 
5076
5193
  // src/renderer/MineRenderScene.ts
5077
- var import_three20 = require("three");
5194
+ var import_three21 = require("three");
5078
5195
  var import_ts_deepmerge8 = __toESM(require_dist());
5079
5196
 
5080
5197
  // src/skin/SkinPart.ts
@@ -5799,7 +5916,7 @@ var slimSkinGeometries = {
5799
5916
  var import_ts_deepmerge7 = __toESM(require_dist());
5800
5917
 
5801
5918
  // src/skin/SkinTextures.ts
5802
- var import_three19 = require("three");
5919
+ var import_three20 = require("three");
5803
5920
 
5804
5921
  // src/skin/SkinImage.ts
5805
5922
  var SkinImage = class {
@@ -5876,11 +5993,11 @@ var SkinTextures = class {
5876
5993
  });
5877
5994
  }
5878
5995
  static createMaterial(pixels, width, height, transparent = true) {
5879
- const texture = Textures.initTextureProps(new import_three19.DataTexture(pixels, width, height));
5880
- texture.colorSpace = import_three19.SRGBColorSpace;
5996
+ const texture = Textures.initTextureProps(new import_three20.DataTexture(pixels, width, height));
5997
+ texture.colorSpace = import_three20.SRGBColorSpace;
5881
5998
  texture.flipY = true;
5882
5999
  texture.needsUpdate = true;
5883
- return new import_three19.MeshBasicMaterial({ map: texture, transparent, side: transparent ? import_three19.DoubleSide : import_three19.FrontSide, alphaTest: transparent ? 0.1 : 0 });
6000
+ return new import_three20.MeshBasicMaterial({ map: texture, transparent, side: transparent ? import_three20.DoubleSide : import_three20.FrontSide, alphaTest: transparent ? 0.1 : 0 });
5884
6001
  }
5885
6002
  static isSlim(image, scale) {
5886
6003
  for (const [x, y] of [[46, 52], [54, 20]]) {
@@ -6107,7 +6224,7 @@ var SkinObject = class extends SceneObject {
6107
6224
  };
6108
6225
 
6109
6226
  // src/renderer/MineRenderScene.ts
6110
- var MineRenderScene = class _MineRenderScene extends import_three20.Scene {
6227
+ var MineRenderScene = class _MineRenderScene extends import_three21.Scene {
6111
6228
  constructor(options) {
6112
6229
  super();
6113
6230
  this.isMineRenderScene = true;
@@ -6183,11 +6300,12 @@ var MineRenderScene = class _MineRenderScene extends import_three20.Scene {
6183
6300
  console.log("instanceMeshes + key");
6184
6301
  let key = asset.key.serialize();
6185
6302
  if (isModelObject(obj)) {
6186
- const { displayPosition, uvLockRotation, tints } = obj.options;
6303
+ const { displayPosition, uvLockRotation, tints, cullMask } = obj.options;
6187
6304
  if (displayPosition) key += `|display:${displayPosition}`;
6188
6305
  if (uvLockRotation) key += `|uvlock:${uvLockRotation.join(",")}`;
6189
6306
  const palette = Object.entries(tints ?? {}).sort(([a], [b]) => Number(a) - Number(b));
6190
6307
  if (palette.length) key += `|tints:${JSON.stringify(palette)}`;
6308
+ if (cullMask) key += `|cull:${cullMask}`;
6191
6309
  }
6192
6310
  return this.instanceManager.getOrCreate(key, async () => {
6193
6311
  obj.scene = this;
@@ -6231,17 +6349,17 @@ function isMineRenderScene(obj) {
6231
6349
  }
6232
6350
 
6233
6351
  // src/renderer/Renderer.ts
6234
- var import_three22 = require("three");
6352
+ var import_three23 = require("three");
6235
6353
  var import_ts_deepmerge9 = __toESM(require_dist());
6236
6354
  var import_stats = __toESM(require("stats.js"));
6237
6355
  var import_postprocessing = require("postprocessing");
6238
6356
 
6239
6357
  // src/three/OrbitControls.js
6240
- var import_three21 = require("three");
6358
+ var import_three22 = require("three");
6241
6359
  var _changeEvent = { type: "change" };
6242
6360
  var _startEvent = { type: "start" };
6243
6361
  var _endEvent = { type: "end" };
6244
- var OrbitControls = class extends import_three21.EventDispatcher {
6362
+ var OrbitControls = class extends import_three22.EventDispatcher {
6245
6363
  constructor(object, domElement) {
6246
6364
  super();
6247
6365
  if (domElement === void 0) console.warn('THREE.OrbitControls: The second parameter "domElement" is now mandatory.');
@@ -6250,7 +6368,7 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6250
6368
  this.domElement = domElement;
6251
6369
  this.domElement.style.touchAction = "none";
6252
6370
  this.enabled = true;
6253
- this.target = new import_three21.Vector3();
6371
+ this.target = new import_three22.Vector3();
6254
6372
  this.minDistance = 0;
6255
6373
  this.maxDistance = Infinity;
6256
6374
  this.minZoom = 0;
@@ -6272,8 +6390,8 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6272
6390
  this.autoRotate = false;
6273
6391
  this.autoRotateSpeed = 2;
6274
6392
  this.keys = { LEFT: "ArrowLeft", UP: "ArrowUp", RIGHT: "ArrowRight", BOTTOM: "ArrowDown" };
6275
- this.mouseButtons = { LEFT: import_three21.MOUSE.ROTATE, MIDDLE: import_three21.MOUSE.DOLLY, RIGHT: import_three21.MOUSE.PAN };
6276
- this.touches = { ONE: import_three21.TOUCH.ROTATE, TWO: import_three21.TOUCH.DOLLY_PAN };
6393
+ this.mouseButtons = { LEFT: import_three22.MOUSE.ROTATE, MIDDLE: import_three22.MOUSE.DOLLY, RIGHT: import_three22.MOUSE.PAN };
6394
+ this.touches = { ONE: import_three22.TOUCH.ROTATE, TWO: import_three22.TOUCH.DOLLY_PAN };
6277
6395
  this.target0 = this.target.clone();
6278
6396
  this.position0 = this.object.position.clone();
6279
6397
  this.zoom0 = this.object.zoom;
@@ -6302,11 +6420,11 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6302
6420
  state = STATE.NONE;
6303
6421
  };
6304
6422
  this.update = function() {
6305
- const offset = new import_three21.Vector3();
6306
- const quat = new import_three21.Quaternion().setFromUnitVectors(object.up, new import_three21.Vector3(0, 1, 0));
6423
+ const offset = new import_three22.Vector3();
6424
+ const quat = new import_three22.Quaternion().setFromUnitVectors(object.up, new import_three22.Vector3(0, 1, 0));
6307
6425
  const quatInverse = quat.clone().invert();
6308
- const lastPosition = new import_three21.Vector3();
6309
- const lastQuaternion = new import_three21.Quaternion();
6426
+ const lastPosition = new import_three22.Vector3();
6427
+ const lastQuaternion = new import_three22.Quaternion();
6310
6428
  const twoPI = 2 * Math.PI;
6311
6429
  return function update() {
6312
6430
  const position = scope.object.position;
@@ -6392,20 +6510,20 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6392
6510
  };
6393
6511
  let state = STATE.NONE;
6394
6512
  const EPS = 1e-6;
6395
- const spherical = new import_three21.Spherical();
6396
- const sphericalDelta = new import_three21.Spherical();
6513
+ const spherical = new import_three22.Spherical();
6514
+ const sphericalDelta = new import_three22.Spherical();
6397
6515
  let scale = 1;
6398
- const panOffset = new import_three21.Vector3();
6516
+ const panOffset = new import_three22.Vector3();
6399
6517
  let zoomChanged = false;
6400
- const rotateStart = new import_three21.Vector2();
6401
- const rotateEnd = new import_three21.Vector2();
6402
- const rotateDelta = new import_three21.Vector2();
6403
- const panStart = new import_three21.Vector2();
6404
- const panEnd = new import_three21.Vector2();
6405
- const panDelta = new import_three21.Vector2();
6406
- const dollyStart = new import_three21.Vector2();
6407
- const dollyEnd = new import_three21.Vector2();
6408
- const dollyDelta = new import_three21.Vector2();
6518
+ const rotateStart = new import_three22.Vector2();
6519
+ const rotateEnd = new import_three22.Vector2();
6520
+ const rotateDelta = new import_three22.Vector2();
6521
+ const panStart = new import_three22.Vector2();
6522
+ const panEnd = new import_three22.Vector2();
6523
+ const panDelta = new import_three22.Vector2();
6524
+ const dollyStart = new import_three22.Vector2();
6525
+ const dollyEnd = new import_three22.Vector2();
6526
+ const dollyDelta = new import_three22.Vector2();
6409
6527
  const pointers = [];
6410
6528
  const pointerPositions = {};
6411
6529
  function getAutoRotationAngle() {
@@ -6421,7 +6539,7 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6421
6539
  sphericalDelta.phi -= angle;
6422
6540
  }
6423
6541
  const panLeft = function() {
6424
- const v = new import_three21.Vector3();
6542
+ const v = new import_three22.Vector3();
6425
6543
  return function panLeft2(distance, objectMatrix) {
6426
6544
  v.setFromMatrixColumn(objectMatrix, 0);
6427
6545
  v.multiplyScalar(-distance);
@@ -6429,7 +6547,7 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6429
6547
  };
6430
6548
  }();
6431
6549
  const panUp = function() {
6432
- const v = new import_three21.Vector3();
6550
+ const v = new import_three22.Vector3();
6433
6551
  return function panUp2(distance, objectMatrix) {
6434
6552
  if (scope.screenSpacePanning === true) {
6435
6553
  v.setFromMatrixColumn(objectMatrix, 1);
@@ -6442,7 +6560,7 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6442
6560
  };
6443
6561
  }();
6444
6562
  const pan = function() {
6445
- const offset = new import_three21.Vector3();
6563
+ const offset = new import_three22.Vector3();
6446
6564
  return function pan2(deltaX, deltaY) {
6447
6565
  const element = scope.domElement;
6448
6566
  if (scope.object.isPerspectiveCamera) {
@@ -6691,12 +6809,12 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6691
6809
  mouseAction = -1;
6692
6810
  }
6693
6811
  switch (mouseAction) {
6694
- case import_three21.MOUSE.DOLLY:
6812
+ case import_three22.MOUSE.DOLLY:
6695
6813
  if (scope.enableZoom === false) return;
6696
6814
  handleMouseDownDolly(event);
6697
6815
  state = STATE.DOLLY;
6698
6816
  break;
6699
- case import_three21.MOUSE.ROTATE:
6817
+ case import_three22.MOUSE.ROTATE:
6700
6818
  if (event.ctrlKey || event.metaKey || event.shiftKey) {
6701
6819
  if (scope.enablePan === false) return;
6702
6820
  handleMouseDownPan(event);
@@ -6707,7 +6825,7 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6707
6825
  state = STATE.ROTATE;
6708
6826
  }
6709
6827
  break;
6710
- case import_three21.MOUSE.PAN:
6828
+ case import_three22.MOUSE.PAN:
6711
6829
  if (event.ctrlKey || event.metaKey || event.shiftKey) {
6712
6830
  if (scope.enableRotate === false) return;
6713
6831
  handleMouseDownRotate(event);
@@ -6763,12 +6881,12 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6763
6881
  switch (pointers.length) {
6764
6882
  case 1:
6765
6883
  switch (scope.touches.ONE) {
6766
- case import_three21.TOUCH.ROTATE:
6884
+ case import_three22.TOUCH.ROTATE:
6767
6885
  if (scope.enableRotate === false) return;
6768
6886
  handleTouchStartRotate();
6769
6887
  state = STATE.TOUCH_ROTATE;
6770
6888
  break;
6771
- case import_three21.TOUCH.PAN:
6889
+ case import_three22.TOUCH.PAN:
6772
6890
  if (scope.enablePan === false) return;
6773
6891
  handleTouchStartPan();
6774
6892
  state = STATE.TOUCH_PAN;
@@ -6779,12 +6897,12 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6779
6897
  break;
6780
6898
  case 2:
6781
6899
  switch (scope.touches.TWO) {
6782
- case import_three21.TOUCH.DOLLY_PAN:
6900
+ case import_three22.TOUCH.DOLLY_PAN:
6783
6901
  if (scope.enableZoom === false && scope.enablePan === false) return;
6784
6902
  handleTouchStartDollyPan();
6785
6903
  state = STATE.TOUCH_DOLLY_PAN;
6786
6904
  break;
6787
- case import_three21.TOUCH.DOLLY_ROTATE:
6905
+ case import_three22.TOUCH.DOLLY_ROTATE:
6788
6906
  if (scope.enableZoom === false && scope.enableRotate === false) return;
6789
6907
  handleTouchStartDollyRotate();
6790
6908
  state = STATE.TOUCH_DOLLY_ROTATE;
@@ -6851,7 +6969,7 @@ var OrbitControls = class extends import_three21.EventDispatcher {
6851
6969
  function trackPointer(event) {
6852
6970
  let position = pointerPositions[event.pointerId];
6853
6971
  if (position === void 0) {
6854
- position = new import_three21.Vector2();
6972
+ position = new import_three22.Vector2();
6855
6973
  pointerPositions[event.pointerId] = position;
6856
6974
  }
6857
6975
  position.set(event.pageX, event.pageY);
@@ -6871,10 +6989,10 @@ var MapControls = class extends OrbitControls {
6871
6989
  constructor(object, domElement) {
6872
6990
  super(object, domElement);
6873
6991
  this.screenSpacePanning = false;
6874
- this.mouseButtons.LEFT = import_three21.MOUSE.PAN;
6875
- this.mouseButtons.RIGHT = import_three21.MOUSE.ROTATE;
6876
- this.touches.ONE = import_three21.TOUCH.PAN;
6877
- this.touches.TWO = import_three21.TOUCH.DOLLY_ROTATE;
6992
+ this.mouseButtons.LEFT = import_three22.MOUSE.PAN;
6993
+ this.mouseButtons.RIGHT = import_three22.MOUSE.ROTATE;
6994
+ this.touches.ONE = import_three22.TOUCH.PAN;
6995
+ this.touches.TWO = import_three22.TOUCH.DOLLY_ROTATE;
6878
6996
  }
6879
6997
  };
6880
6998
 
@@ -6919,8 +7037,8 @@ var Renderer = class _Renderer {
6919
7037
  top: void 0,
6920
7038
  bottom: void 0
6921
7039
  },
6922
- position: new import_three22.Vector3(50, 50, 50),
6923
- lookingAt: new import_three22.Vector3(0, 0, 0)
7040
+ position: new import_three23.Vector3(50, 50, 50),
7041
+ lookingAt: new import_three23.Vector3(0, 0, 0)
6924
7042
  },
6925
7043
  render: {
6926
7044
  fpsLimit: 60,
@@ -6950,14 +7068,14 @@ var Renderer = class _Renderer {
6950
7068
  switch (this.options.camera.type) {
6951
7069
  case "perspective":
6952
7070
  default:
6953
- return new import_three22.PerspectiveCamera(
7071
+ return new import_three23.PerspectiveCamera(
6954
7072
  this.options.camera.perspective.fov,
6955
7073
  this.options.camera.perspective.aspect ?? this.viewWidth / this.viewHeight,
6956
7074
  this.options.camera.near,
6957
7075
  this.options.camera.far
6958
7076
  );
6959
7077
  case "orthographic":
6960
- return new import_three22.OrthographicCamera(
7078
+ return new import_three23.OrthographicCamera(
6961
7079
  this.options.camera.orthographic.left ?? this.viewWidth / -2,
6962
7080
  this.options.camera.orthographic.right ?? this.viewWidth / 2,
6963
7081
  this.options.camera.orthographic.top ?? this.viewHeight / 2,
@@ -6968,7 +7086,7 @@ var Renderer = class _Renderer {
6968
7086
  }
6969
7087
  }
6970
7088
  createRenderer() {
6971
- const renderer = new import_three22.WebGLRenderer({
7089
+ const renderer = new import_three23.WebGLRenderer({
6972
7090
  antialias: this.options.render.antialias,
6973
7091
  alpha: true,
6974
7092
  powerPreference: "high-performance",
@@ -6976,8 +7094,8 @@ var Renderer = class _Renderer {
6976
7094
  });
6977
7095
  renderer.setClearColor(0, 0);
6978
7096
  renderer.shadowMap.enabled = true;
6979
- renderer.shadowMap.type = import_three22.PCFSoftShadowMap;
6980
- renderer.outputColorSpace = import_three22.SRGBColorSpace;
7097
+ renderer.shadowMap.type = import_three23.PCFSoftShadowMap;
7098
+ renderer.outputColorSpace = import_three23.SRGBColorSpace;
6981
7099
  renderer.setSize(this.viewWidth, this.viewHeight);
6982
7100
  return renderer;
6983
7101
  }
@@ -7011,20 +7129,20 @@ var Renderer = class _Renderer {
7011
7129
  window["__THREE_DEVTOOLS__"].dispatchEvent(new CustomEvent("observe", { detail: this.scene }));
7012
7130
  }
7013
7131
  if (this.options.debug.grid) {
7014
- const gridHelper = new import_three22.GridHelper(128, 16);
7132
+ const gridHelper = new import_three23.GridHelper(128, 16);
7015
7133
  this._debugHelpers.push(gridHelper);
7016
7134
  this.scene.add(gridHelper);
7017
- const gridHelper2 = new import_three22.GridHelper(128, 16);
7135
+ const gridHelper2 = new import_three23.GridHelper(128, 16);
7018
7136
  this._debugHelpers.push(gridHelper2);
7019
7137
  gridHelper2.rotation.x = 90 * (Math.PI / 180);
7020
7138
  this.scene.add(gridHelper2);
7021
- const gridHelper3 = new import_three22.GridHelper(128, 16);
7139
+ const gridHelper3 = new import_three23.GridHelper(128, 16);
7022
7140
  this._debugHelpers.push(gridHelper3);
7023
7141
  gridHelper3.rotation.z = 90 * (Math.PI / 180);
7024
7142
  this.scene.add(gridHelper3);
7025
7143
  }
7026
7144
  if (this.options.debug.axes) {
7027
- const axesHelper = new import_three22.AxesHelper(64);
7145
+ const axesHelper = new import_three23.AxesHelper(64);
7028
7146
  this._debugHelpers.push(axesHelper);
7029
7147
  this.scene.add(axesHelper);
7030
7148
  }
@@ -7379,7 +7497,7 @@ var Skins = class {
7379
7497
  };
7380
7498
 
7381
7499
  // src/world/Chunk.ts
7382
- var import_three25 = require("three");
7500
+ var import_three26 = require("three");
7383
7501
 
7384
7502
  // src/world/ChunkData.ts
7385
7503
  var ChunkData = class _ChunkData {
@@ -7463,28 +7581,29 @@ var ChunkData = class _ChunkData {
7463
7581
  };
7464
7582
 
7465
7583
  // src/world/MineRenderWorld.ts
7466
- var import_three24 = require("three");
7584
+ var import_three25 = require("three");
7467
7585
  var MineRenderWorld = class {
7468
7586
  constructor(scene) {
7469
7587
  this._chunks = /* @__PURE__ */ new Map();
7588
+ this.pendingCulling = /* @__PURE__ */ new Map();
7470
7589
  this.scene = scene;
7471
7590
  }
7472
7591
  getBlockAt(posOrX, y, z) {
7473
7592
  if (typeof posOrX == "number") {
7474
- return this.getBlockAt(new import_three24.Vector3(posOrX, y, z));
7593
+ return this.getBlockAt(new import_three25.Vector3(posOrX, y, z));
7475
7594
  }
7476
7595
  if (isTripleArray(posOrX)) {
7477
- return this.getBlockAt(new import_three24.Vector3(posOrX[0], posOrX[1], posOrX[2]));
7596
+ return this.getBlockAt(new import_three25.Vector3(posOrX[0], posOrX[1], posOrX[2]));
7478
7597
  }
7479
7598
  this.validatePosBounds(posOrX);
7480
7599
  return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
7481
7600
  }
7482
7601
  async setBlockAt(posOrX, yOrBlock, z, block) {
7483
7602
  if (typeof posOrX == "number") {
7484
- return this.setBlockAt(new import_three24.Vector3(posOrX, yOrBlock, z), block);
7603
+ return this.setBlockAt(new import_three25.Vector3(posOrX, yOrBlock, z), block);
7485
7604
  }
7486
7605
  if (isTripleArray(posOrX)) {
7487
- return this.setBlockAt(new import_three24.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
7606
+ return this.setBlockAt(new import_three25.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
7488
7607
  }
7489
7608
  this.validatePosBounds(posOrX);
7490
7609
  const value = yOrBlock;
@@ -7527,16 +7646,54 @@ var MineRenderWorld = class {
7527
7646
  }
7528
7647
  }
7529
7648
  async clear() {
7530
- for (const chunk of this._chunks.values()) {
7649
+ await this.culling;
7650
+ const chunks = [...this._chunks.values()];
7651
+ this._chunks.clear();
7652
+ for (const chunk of chunks) {
7531
7653
  await chunk.dispose();
7532
7654
  }
7533
- this._chunks.clear();
7655
+ }
7656
+ updateCulling(positions) {
7657
+ for (const pos of positions) {
7658
+ this.pendingCulling.set(pos.toArray().join(","), pos.clone());
7659
+ for (const offset of CUBE_FACE_OFFSETS) {
7660
+ const neighbor = pos.clone().add(new import_three25.Vector3(...offset));
7661
+ this.pendingCulling.set(neighbor.toArray().join(","), neighbor);
7662
+ }
7663
+ }
7664
+ return this.culling ??= Promise.resolve().then(async () => {
7665
+ try {
7666
+ while (this.pendingCulling.size) {
7667
+ const batch = [...this.pendingCulling.values()];
7668
+ this.pendingCulling.clear();
7669
+ for (const pos of batch) {
7670
+ const block = this.getBlockAt(pos)?.object;
7671
+ if (!block) continue;
7672
+ let mask = 0;
7673
+ for (const [face, offset] of CUBE_FACE_OFFSETS.entries()) {
7674
+ if (this.getBlockAt(pos.clone().add(new import_three25.Vector3(...offset)))?.object.isOccluding) {
7675
+ mask |= 1 << face;
7676
+ }
7677
+ }
7678
+ await block.setCullMask(mask);
7679
+ }
7680
+ }
7681
+ } finally {
7682
+ this.culling = void 0;
7683
+ }
7684
+ });
7534
7685
  }
7535
7686
  getOrCreateChunkAt(pos) {
7536
7687
  const key = this.worldPosToChunkKey(pos);
7537
7688
  let chunk = this._chunks.get(key);
7538
7689
  if (typeof chunk === "undefined") {
7539
- chunk = new Chunk(this.scene, Math.floor(pos.x / 16), Math.floor(pos.y / 16), Math.floor(pos.z / 16));
7690
+ chunk = new Chunk(
7691
+ this.scene,
7692
+ Math.floor(pos.x / 16),
7693
+ Math.floor(pos.y / 16),
7694
+ Math.floor(pos.z / 16),
7695
+ (positions) => this.updateCulling(positions)
7696
+ );
7540
7697
  this._chunks.set(key, chunk);
7541
7698
  }
7542
7699
  return chunk;
@@ -7545,14 +7702,14 @@ var MineRenderWorld = class {
7545
7702
  return this._chunks.get(this.worldPosToChunkKey(pos));
7546
7703
  }
7547
7704
  static worldToScenePosition(pos) {
7548
- return new import_three24.Vector3(
7705
+ return new import_three25.Vector3(
7549
7706
  pos.x * 16,
7550
7707
  pos.y * 16,
7551
7708
  pos.z * 16
7552
7709
  );
7553
7710
  }
7554
7711
  static sceneToWorldPosition(pos) {
7555
- return new import_three24.Vector3(
7712
+ return new import_three25.Vector3(
7556
7713
  pos.x / 16,
7557
7714
  pos.y / 16,
7558
7715
  pos.z / 16
@@ -7573,7 +7730,8 @@ var MineRenderWorld = class {
7573
7730
 
7574
7731
  // src/world/Chunk.ts
7575
7732
  var Chunk = class _Chunk {
7576
- constructor(scene, x, y, z) {
7733
+ constructor(scene, x, y, z, onBlocksChanged) {
7734
+ this.onBlocksChanged = onBlocksChanged;
7577
7735
  this.data = new ChunkData();
7578
7736
  this.renderedBlocks = /* @__PURE__ */ new Map();
7579
7737
  this.scene = scene;
@@ -7583,10 +7741,10 @@ var Chunk = class _Chunk {
7583
7741
  }
7584
7742
  getBlockAt(posOrX, y, z) {
7585
7743
  if (typeof posOrX == "number") {
7586
- return this.getBlockAt(new import_three25.Vector3(posOrX, y, z));
7744
+ return this.getBlockAt(new import_three26.Vector3(posOrX, y, z));
7587
7745
  }
7588
7746
  if (isTripleArray(posOrX)) {
7589
- return this.getBlockAt(new import_three25.Vector3(posOrX[0], posOrX[1], posOrX[2]));
7747
+ return this.getBlockAt(new import_three26.Vector3(posOrX[0], posOrX[1], posOrX[2]));
7590
7748
  }
7591
7749
  const pos = this.worldPosToChunkPos(posOrX);
7592
7750
  const index = _Chunk.chunkPosToBlockIndex(pos);
@@ -7594,10 +7752,10 @@ var Chunk = class _Chunk {
7594
7752
  }
7595
7753
  async setBlockAt(posOrX, yOrBlock, z, block) {
7596
7754
  if (typeof posOrX == "number") {
7597
- return this.setBlockAt(new import_three25.Vector3(posOrX, yOrBlock, z), block);
7755
+ return this.setBlockAt(new import_three26.Vector3(posOrX, yOrBlock, z), block);
7598
7756
  }
7599
7757
  if (isTripleArray(posOrX)) {
7600
- return this.setBlockAt(new import_three25.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
7758
+ return this.setBlockAt(new import_three26.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
7601
7759
  }
7602
7760
  const worldPos = posOrX;
7603
7761
  const pos = this.worldPosToChunkPos(worldPos);
@@ -7616,10 +7774,10 @@ var Chunk = class _Chunk {
7616
7774
  const readBlock = this.data.snapshot(index);
7617
7775
  this.renderedBlocks.get(index)?.object.removeFromScene();
7618
7776
  this.renderedBlocks.delete(index);
7619
- if (!readBlock) return void 0;
7620
- const stored = readBlock();
7621
7777
  let object;
7622
7778
  try {
7779
+ if (!readBlock) return void 0;
7780
+ const stored = readBlock();
7623
7781
  const blockState = await BlockStates.get(AssetKey.parse("blockstates", stored.type));
7624
7782
  if (!blockState) {
7625
7783
  this.data.set(index, void 0);
@@ -7641,12 +7799,18 @@ var Chunk = class _Chunk {
7641
7799
  this.data.set(index, void 0);
7642
7800
  object?.removeFromScene();
7643
7801
  throw error;
7802
+ } finally {
7803
+ await this.onBlocksChanged?.([worldPos]);
7644
7804
  }
7645
7805
  }
7646
7806
  async clear() {
7807
+ const positions = [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
7808
+ new import_three26.Vector3(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
7809
+ ));
7647
7810
  for (const info of this.renderedBlocks.values()) info.object.removeFromScene();
7648
7811
  this.renderedBlocks.clear();
7649
7812
  this.data.clear();
7813
+ await this.onBlocksChanged?.(positions);
7650
7814
  }
7651
7815
  async dispose() {
7652
7816
  await this.clear();
@@ -7661,14 +7825,14 @@ var Chunk = class _Chunk {
7661
7825
  return pos.y * 16 * 16 + pos.z * 16 + pos.x;
7662
7826
  }
7663
7827
  worldPosToChunkPos(pos) {
7664
- return new import_three25.Vector3(
7828
+ return new import_three26.Vector3(
7665
7829
  pos.x - this.x * 16,
7666
7830
  pos.y - this.y * 16,
7667
7831
  pos.z - this.z * 16
7668
7832
  );
7669
7833
  }
7670
7834
  chunkPosToWorldPos(pos) {
7671
- return new import_three25.Vector3(
7835
+ return new import_three26.Vector3(
7672
7836
  this.x * 16 + pos.x,
7673
7837
  this.y * 16 + pos.y,
7674
7838
  this.z * 16 + pos.z
@@ -7695,6 +7859,7 @@ var Chunk = class _Chunk {
7695
7859
  BlockTints,
7696
7860
  BrowserArchiveProxy,
7697
7861
  CUBE_FACES,
7862
+ CUBE_FACE_OFFSETS,
7698
7863
  Caching,
7699
7864
  CanvasImage,
7700
7865
  Chunk,
@@ -7728,6 +7893,7 @@ var Chunk = class _Chunk {
7728
7893
  MineRenderWorld,
7729
7894
  MinecraftCubeTexture,
7730
7895
  MinecraftFaceUV,
7896
+ ModelCulling,
7731
7897
  ModelGenerator,
7732
7898
  ModelMerger,
7733
7899
  ModelObject,