minerender 2.1.0-alpha.121 → 2.1.0-alpha.123

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.
@@ -12425,6 +12425,10 @@ var _BlockObject = class _BlockObject extends SceneObject {
12425
12425
  get blockEntities() {
12426
12426
  return this._entities;
12427
12427
  }
12428
+ /** Model placements drawn for this block, including its fluid surface. */
12429
+ get models() {
12430
+ return this._models;
12431
+ }
12428
12432
  /** Sets visibility for this block's model instances and block entities. */
12429
12433
  setVisible(visible) {
12430
12434
  this.visible = visible;
@@ -17188,14 +17192,14 @@ var AnvilWorldSource = class {
17188
17192
  };
17189
17193
 
17190
17194
  // src/world/Chunk.ts
17191
- import { Color as Color13, Vector3 as Vector318 } from "three";
17195
+ import { Color as Color13, Vector3 as Vector320 } from "three";
17192
17196
  init_BlockStates();
17193
17197
  init_AssetKey();
17194
17198
 
17195
17199
  // src/world/MineRenderWorld.ts
17196
17200
  init_Model();
17197
17201
  init_util();
17198
- import { Vector3 as Vector317 } from "three";
17202
+ import { Vector3 as Vector319 } from "three";
17199
17203
  init_AssetKey();
17200
17204
  init_BlockStates();
17201
17205
  init_CubeFace();
@@ -17458,11 +17462,74 @@ function resolveSavedEntity(entity) {
17458
17462
 
17459
17463
  // src/world/_entities/WorldEntities.ts
17460
17464
  init_BannerPatterns();
17465
+ import { Vector3 as Vector318 } from "three";
17466
+
17467
+ // src/world/_picking/Picking.ts
17468
+ init_three();
17469
+ import { Matrix3 as Matrix33, Matrix4 as Matrix413 } from "three";
17470
+ function pickableMeshes(root, scene, raycaster) {
17471
+ const result = [];
17472
+ let attached = false;
17473
+ for (let parent = root; parent; parent = parent.parent) {
17474
+ if (!parent.visible) return result;
17475
+ if (parent === scene) attached = true;
17476
+ }
17477
+ if (!attached) return result;
17478
+ root.updateWorldMatrix(true, true);
17479
+ root.traverseVisible((object4) => {
17480
+ if (isMesh(object4) && raycaster.layers.test(object4.layers)) result.push(object4);
17481
+ });
17482
+ return result;
17483
+ }
17484
+ function visibleHits(raycaster, meshes) {
17485
+ return raycaster.intersectObjects(meshes, false).filter((hit) => {
17486
+ if (!hit.face) return false;
17487
+ const mesh = hit.object;
17488
+ const material = Array.isArray(mesh.material) ? mesh.material[hit.face.materialIndex] : mesh.material;
17489
+ return material?.visible;
17490
+ });
17491
+ }
17492
+ function hitNormal(hit) {
17493
+ const mesh = hit.object;
17494
+ const matrix = mesh.matrixWorld.clone();
17495
+ if (isInstancedMesh(mesh) && hit.instanceId !== void 0) {
17496
+ const instance = new Matrix413();
17497
+ mesh.getMatrixAt(hit.instanceId, instance);
17498
+ matrix.multiply(instance);
17499
+ }
17500
+ return hit.face.normal.clone().applyNormalMatrix(new Matrix33().getNormalMatrix(matrix));
17501
+ }
17502
+
17503
+ // src/world/_entities/WorldEntities.ts
17461
17504
  var WorldEntities = class {
17462
17505
  constructor(scene) {
17463
17506
  this.scene = scene;
17464
17507
  this.columns = /* @__PURE__ */ new Map();
17465
17508
  }
17509
+ /** Finds the nearest visible triangle belonging to an entity owned by this world. */
17510
+ raycast(raycaster) {
17511
+ const owners = /* @__PURE__ */ new Map();
17512
+ for (const column of this.columns.values()) {
17513
+ for (const [object4, placement] of column) {
17514
+ for (const mesh of pickableMeshes(object4, this.scene, raycaster)) {
17515
+ owners.set(mesh, { object: object4, ...placement });
17516
+ }
17517
+ }
17518
+ }
17519
+ for (const hit of visibleHits(raycaster, [...owners.keys()])) {
17520
+ const mesh = hit.object;
17521
+ const owner = owners.get(mesh);
17522
+ return {
17523
+ type: owner.type,
17524
+ position: new Vector318(...owner.position),
17525
+ object: owner.object,
17526
+ point: hit.point.clone(),
17527
+ normal: hitNormal(hit),
17528
+ distance: hit.distance
17529
+ };
17530
+ }
17531
+ return void 0;
17532
+ }
17466
17533
  /** Captures column ownership before asynchronous block or asset loading starts. */
17467
17534
  prepare(entities = [], column) {
17468
17535
  const placements = entities.flatMap((entity) => {
@@ -17471,7 +17538,7 @@ var WorldEntities = class {
17471
17538
  const position = [...entity.position];
17472
17539
  const key = column?.join(",") ?? `${Math.floor(position[0] / 16)},${Math.floor(position[2] / 16)}`;
17473
17540
  let owner = this.columns.get(key);
17474
- if (!owner) this.columns.set(key, owner = /* @__PURE__ */ new Set());
17541
+ if (!owner) this.columns.set(key, owner = /* @__PURE__ */ new Map());
17475
17542
  return [{ ...resolved, position, column: key, owner }];
17476
17543
  });
17477
17544
  return async () => {
@@ -17497,7 +17564,7 @@ var WorldEntities = class {
17497
17564
  object4.rotation.y = placement.yaw;
17498
17565
  await object4.init();
17499
17566
  if (!current()) return;
17500
- placement.owner.add(object4);
17567
+ placement.owner.set(object4, { type: placement.key.toNamespacedString(), position: placement.position });
17501
17568
  this.scene.add(object4);
17502
17569
  } catch (error) {
17503
17570
  console.warn(`Could not draw saved entity ${placement.key.toNamespacedString()}, skipping it`, error);
@@ -17512,7 +17579,7 @@ var WorldEntities = class {
17512
17579
  const objects = this.columns.get(key);
17513
17580
  this.columns.delete(key);
17514
17581
  if (!objects) return;
17515
- for (const object4 of objects) {
17582
+ for (const object4 of objects.keys()) {
17516
17583
  object4.removeFromScene();
17517
17584
  object4.dispose();
17518
17585
  }
@@ -17573,6 +17640,21 @@ var MineRenderWorld = class {
17573
17640
  if (options.sectionMeshing) this.sectionModels = new SectionModels(options.maxAtlasSize);
17574
17641
  if (options.renderEntities) this.entities = new WorldEntities(scene);
17575
17642
  }
17643
+ /**
17644
+ * Returns the nearest visible block geometry hit, respecting the raycaster's layers and near/far range.
17645
+ * Includes fluids and block entities; texture alpha does not change triangle intersections.
17646
+ */
17647
+ raycast(raycaster) {
17648
+ return Chunk.raycast(this._chunks.values(), raycaster);
17649
+ }
17650
+ /**
17651
+ * Returns the nearest visible mob geometry hit when renderEntities is enabled.
17652
+ * Respects layers and near/far; compare its distance with raycast() to account for blocks.
17653
+ * Texture alpha does not change triangle intersections.
17654
+ */
17655
+ raycastEntities(raycaster) {
17656
+ return this.entities?.raycast(raycaster);
17657
+ }
17576
17658
  /** Whether neighboring opaque cubes shade block-face corners. Defaults to false. */
17577
17659
  get ambientOcclusion() {
17578
17660
  return this._ambientOcclusion;
@@ -17593,25 +17675,25 @@ var MineRenderWorld = class {
17593
17675
  }
17594
17676
  getBlockAt(posOrX, y, z) {
17595
17677
  if (typeof posOrX == "number") {
17596
- return this.getBlockAt(new Vector317(posOrX, y, z));
17678
+ return this.getBlockAt(new Vector319(posOrX, y, z));
17597
17679
  }
17598
17680
  if (isTripleArray(posOrX)) {
17599
- return this.getBlockAt(new Vector317(posOrX[0], posOrX[1], posOrX[2]));
17681
+ return this.getBlockAt(new Vector319(posOrX[0], posOrX[1], posOrX[2]));
17600
17682
  }
17601
17683
  this.validatePosBounds(posOrX);
17602
17684
  return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
17603
17685
  }
17604
17686
  getBiomeAt(posOrX, y, z) {
17605
- if (typeof posOrX === "number") return this.getBiomeAt(new Vector317(posOrX, y, z));
17606
- if (isTripleArray(posOrX)) return this.getBiomeAt(new Vector317(...posOrX));
17687
+ if (typeof posOrX === "number") return this.getBiomeAt(new Vector319(posOrX, y, z));
17688
+ if (isTripleArray(posOrX)) return this.getBiomeAt(new Vector319(...posOrX));
17607
17689
  this.validatePosBounds(posOrX);
17608
17690
  const cx = Math.floor(posOrX.x / 16), cy = Math.floor(posOrX.y / 16), cz = Math.floor(posOrX.z / 16);
17609
17691
  const lx = posOrX.x - cx * 16, ly = posOrX.y - cy * 16, lz = posOrX.z - cz * 16;
17610
17692
  return this.biomes.get(`${cx}_${cz}`)?.get(cy)?.[Math.floor(lx / 4) + Math.floor(lz / 4) * 4 + Math.floor(ly / 4) * 16];
17611
17693
  }
17612
17694
  getLightAt(posOrX, y, z) {
17613
- if (typeof posOrX === "number") return this.getLightAt(new Vector317(posOrX, y, z));
17614
- if (isTripleArray(posOrX)) return this.getLightAt(new Vector317(...posOrX));
17695
+ if (typeof posOrX === "number") return this.getLightAt(new Vector319(posOrX, y, z));
17696
+ if (isTripleArray(posOrX)) return this.getLightAt(new Vector319(...posOrX));
17615
17697
  this.validatePosBounds(posOrX);
17616
17698
  const { x, y: py, z: pz } = posOrX;
17617
17699
  const cx = Math.floor(x / 16), cy = Math.floor(py / 16), cz = Math.floor(pz / 16);
@@ -17629,10 +17711,10 @@ var MineRenderWorld = class {
17629
17711
  }
17630
17712
  async setBlockAt(posOrX, yOrBlock, z, block) {
17631
17713
  if (typeof posOrX == "number") {
17632
- return this.setBlockAt(new Vector317(posOrX, yOrBlock, z), block);
17714
+ return this.setBlockAt(new Vector319(posOrX, yOrBlock, z), block);
17633
17715
  }
17634
17716
  if (isTripleArray(posOrX)) {
17635
- return this.setBlockAt(new Vector317(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
17717
+ return this.setBlockAt(new Vector319(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
17636
17718
  }
17637
17719
  return this.placeBlock(posOrX, yOrBlock);
17638
17720
  }
@@ -17643,10 +17725,10 @@ var MineRenderWorld = class {
17643
17725
  }
17644
17726
  async setBlockVisibleAt(posOrX, yOrVisible, z, visible) {
17645
17727
  if (typeof posOrX === "number") {
17646
- return this.setBlockVisibleAt(new Vector317(posOrX, yOrVisible, z), visible);
17728
+ return this.setBlockVisibleAt(new Vector319(posOrX, yOrVisible, z), visible);
17647
17729
  }
17648
17730
  if (isTripleArray(posOrX)) {
17649
- return this.setBlockVisibleAt(new Vector317(...posOrX), yOrVisible);
17731
+ return this.setBlockVisibleAt(new Vector319(...posOrX), yOrVisible);
17650
17732
  }
17651
17733
  this.validatePosBounds(posOrX);
17652
17734
  await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible);
@@ -17672,7 +17754,7 @@ var MineRenderWorld = class {
17672
17754
  const collect = async (positions2) => {
17673
17755
  for (const pos of positions2) changes.set(pos.toArray().join(","), pos);
17674
17756
  };
17675
- const place = (block) => this.placeBlock(new Vector317(...block.position), block, collect);
17757
+ const place = (block) => this.placeBlock(new Vector319(...block.position), block, collect);
17676
17758
  const keys = /* @__PURE__ */ new Map();
17677
17759
  const types = /* @__PURE__ */ new Set();
17678
17760
  for (const block of multiblock.blocks) {
@@ -17688,7 +17770,7 @@ var MineRenderWorld = class {
17688
17770
  }
17689
17771
  if (!executor) {
17690
17772
  const groups2 = /* @__PURE__ */ new Map();
17691
- const position = new Vector317();
17773
+ const position = new Vector319();
17692
17774
  for (const block of multiblock.blocks) {
17693
17775
  const [x, y, z] = block.position;
17694
17776
  this.validatePosBounds(position.set(x, y, z));
@@ -17728,7 +17810,7 @@ var MineRenderWorld = class {
17728
17810
  try {
17729
17811
  positions = await chunk.placeBlocks(blocks);
17730
17812
  } finally {
17731
- positions ?? (positions = blocks.map(({ index }) => new Vector317(
17813
+ positions ?? (positions = blocks.map(({ index }) => new Vector319(
17732
17814
  chunk.x * 16 + index % 16,
17733
17815
  chunk.y * 16 + Math.floor(index / 256),
17734
17816
  chunk.z * 16 + Math.floor(index / 16) % 16
@@ -17780,7 +17862,7 @@ var MineRenderWorld = class {
17780
17862
  }
17781
17863
  for (const section of chunk.sections) {
17782
17864
  if (section.biomes) {
17783
- const position = new Vector317(chunk.x * 16, section.y * 16, chunk.z * 16);
17865
+ const position = new Vector319(chunk.x * 16, section.y * 16, chunk.z * 16);
17784
17866
  this.validatePosBounds(position);
17785
17867
  const copy = [...section.biomes];
17786
17868
  if (copy.length !== 64 || !copy.every((id) => typeof id === "string" && id.length > 0)) {
@@ -17796,7 +17878,7 @@ var MineRenderWorld = class {
17796
17878
  for (const section of chunk.sections) {
17797
17879
  if (!executor) {
17798
17880
  if (!occupiedSections.has(section.y)) continue;
17799
- const position = new Vector317(chunk.x * 16, section.y * 16, chunk.z * 16);
17881
+ const position = new Vector319(chunk.x * 16, section.y * 16, chunk.z * 16);
17800
17882
  this.validatePosBounds(position);
17801
17883
  const target = this.getOrCreateChunkAt(position);
17802
17884
  try {
@@ -17900,7 +17982,7 @@ var MineRenderWorld = class {
17900
17982
  this.sectionModels?.clear();
17901
17983
  }
17902
17984
  updateCulling(positions) {
17903
- const neighbor = new Vector317();
17985
+ const neighbor = new Vector319();
17904
17986
  for (const pos of positions) {
17905
17987
  const cx = Math.floor(pos.x / 16), cy = Math.floor(pos.y / 16), cz = Math.floor(pos.z / 16);
17906
17988
  const chunk = this._chunks.get(`${cx}_${cy}_${cz}`);
@@ -18031,7 +18113,7 @@ var MineRenderWorld = class {
18031
18113
  }
18032
18114
  /** Converts block coordinates to scene units by multiplying each component by 16. */
18033
18115
  static worldToScenePosition(pos) {
18034
- return new Vector317(
18116
+ return new Vector319(
18035
18117
  pos.x * 16,
18036
18118
  pos.y * 16,
18037
18119
  pos.z * 16
@@ -18039,7 +18121,7 @@ var MineRenderWorld = class {
18039
18121
  }
18040
18122
  /** Converts scene units to block coordinates without rounding to an integer block. */
18041
18123
  static sceneToWorldPosition(pos) {
18042
- return new Vector317(
18124
+ return new Vector319(
18043
18125
  pos.x / 16,
18044
18126
  pos.y / 16,
18045
18127
  pos.z / 16
@@ -18064,7 +18146,7 @@ init_Model();
18064
18146
  // src/world/SectionMesh.ts
18065
18147
  init_CanvasCompat();
18066
18148
  init_Materials();
18067
- import { BufferGeometry as BufferGeometry9, Color as Color12, DoubleSide as DoubleSide8, Float32BufferAttribute as Float32BufferAttribute10, FrontSide as FrontSide4, Group as Group3, Mesh as Mesh10, Uint32BufferAttribute } from "three";
18149
+ import { BufferGeometry as BufferGeometry9, Color as Color12, DoubleSide as DoubleSide8, Float32BufferAttribute as Float32BufferAttribute10, FrontSide as FrontSide4, Group as Group3, Mesh as Mesh12, Uint32BufferAttribute } from "three";
18068
18150
 
18069
18151
  // src/world/SectionGeometry.ts
18070
18152
  init_FluidQuads();
@@ -18247,6 +18329,7 @@ function buildSectionGeometry(input) {
18247
18329
  const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);
18248
18330
  const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);
18249
18331
  const outputIndices = new Uint32Array(faces * 6);
18332
+ const blockIndices = new Uint16Array(faces);
18250
18333
  let vertex = 0, indexOffset = 0;
18251
18334
  for (const entry of page.entries) {
18252
18335
  const template = templateData[templates[entry]];
@@ -18261,6 +18344,7 @@ function buildSectionGeometry(input) {
18261
18344
  const ambientMask = ambientOcclusion && template.ambientOcclusion !== false ? sectionAmbientOcclusionMask(ambientOcclusion, lightIndex) : 0;
18262
18345
  for (let quad = 0; quad < template.quads; quad++) {
18263
18346
  if (cullMasks[entry] & template.cullFaces[quad]) continue;
18347
+ blockIndices[indexOffset / 6] = indices[entry];
18264
18348
  if (ambientMask) quadAmbientOcclusion(template.positions, template.normals, quad, ambientMask, cornerBrightness2);
18265
18349
  const brightness = light ? lightBrightness(light[lightIndex + LIGHT_SAMPLE_OFFSETS[quadLightIndex(template.positions, template.normals, quad)]], ambientLight) : 1;
18266
18350
  const start = vertex;
@@ -18293,6 +18377,7 @@ function buildSectionGeometry(input) {
18293
18377
  const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
18294
18378
  const lightIndex = (y + 1) * 324 + (z + 1) * 18 + x + 1;
18295
18379
  for (let quad = 0; quad < quads.sprites.length; quad++) {
18380
+ blockIndices[indexOffset / 6] = x + z * 16 + y * 256;
18296
18381
  const rect = quads.sprites[quad] === 0 ? data.still : data.flow;
18297
18382
  const brightness = light ? lightBrightness(fluidLightLevel(
18298
18383
  light[lightIndex],
@@ -18323,11 +18408,11 @@ function buildSectionGeometry(input) {
18323
18408
  indexOffset += 6;
18324
18409
  }
18325
18410
  }
18326
- return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices };
18411
+ return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices, blockIndices };
18327
18412
  });
18328
18413
  }
18329
18414
  function sectionGeometryTransferables(pages) {
18330
- return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer]);
18415
+ return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer, page.blockIndices.buffer]);
18331
18416
  }
18332
18417
 
18333
18418
  // src/world/SectionWorker.ts
@@ -18485,6 +18570,12 @@ var SectionMesh = class _SectionMesh extends Group3 {
18485
18570
  constructor() {
18486
18571
  super(...arguments);
18487
18572
  this.ownedMeshes = [];
18573
+ this.blockIndices = /* @__PURE__ */ new Map();
18574
+ }
18575
+ /** Returns the owning section cell for a triangle hit on this mesh's merged geometry. */
18576
+ getBlockIndex(hit) {
18577
+ if (hit.faceIndex === void 0 || hit.faceIndex === null) return void 0;
18578
+ return this.blockIndices.get(hit.object)?.[Math.floor(hit.faceIndex / 2)];
18488
18579
  }
18489
18580
  /** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
18490
18581
  static build(entries, maxAtlasSize = 2048, fluids, lighting) {
@@ -18525,8 +18616,9 @@ var SectionMesh = class _SectionMesh extends Group3 {
18525
18616
  }
18526
18617
  material.vertexColors = true;
18527
18618
  const texture = material.uniforms?.map?.value ?? material.map;
18528
- const mesh = new Mesh10(geometry, material);
18619
+ const mesh = new Mesh12(geometry, material);
18529
18620
  section.add(mesh);
18621
+ section.blockIndices.set(mesh, page.blockIndices);
18530
18622
  const unsubscribe = [];
18531
18623
  for (const { atlas: id, x, y } of page.placements) {
18532
18624
  const atlas = atlases[id];
@@ -18552,6 +18644,7 @@ var SectionMesh = class _SectionMesh extends Group3 {
18552
18644
  mesh.material.dispose();
18553
18645
  texture?.dispose();
18554
18646
  }
18647
+ this.blockIndices.clear();
18555
18648
  this.removeFromParent();
18556
18649
  super.dispose();
18557
18650
  }
@@ -18561,6 +18654,7 @@ var SectionMesh = class _SectionMesh extends Group3 {
18561
18654
  init_FluidGeometry();
18562
18655
  init_FluidQuads();
18563
18656
  init_CubeFace();
18657
+ init_InstanceReference();
18564
18658
  var WATER_TINT2 = new Color13(4159204).toArray();
18565
18659
  var Chunk = class _Chunk {
18566
18660
  constructor(scene, x, y, z, onBlocksChanged, sectionModels, neighborCell, biomeAt, onBiomesChanged, lightAt, onLightCleared, ambientLight = 0) {
@@ -18574,10 +18668,11 @@ var Chunk = class _Chunk {
18574
18668
  this.ambientLight = ambientLight;
18575
18669
  this.data = new ChunkData();
18576
18670
  this.renderedBlocks = /* @__PURE__ */ new Map();
18671
+ this.objectBlocks = /* @__PURE__ */ new Set();
18577
18672
  this.sectionBlocks = /* @__PURE__ */ new Map();
18578
18673
  this.hiddenBlocks = /* @__PURE__ */ new Set();
18579
18674
  this.fluidCells = new Uint8Array(4096);
18580
- this.blockPosition = new Vector318();
18675
+ this.blockPosition = new Vector320();
18581
18676
  this.meshDirty = false;
18582
18677
  this.meshGeneration = 0;
18583
18678
  this.scene = scene;
@@ -18585,20 +18680,84 @@ var Chunk = class _Chunk {
18585
18680
  this.y = y;
18586
18681
  this.z = z;
18587
18682
  }
18683
+ /** Finds the nearest owned block hit across sections, testing each shared mesh once. */
18684
+ static raycast(chunks, raycaster) {
18685
+ const roots = /* @__PURE__ */ new Map();
18686
+ const targets = /* @__PURE__ */ new Map();
18687
+ const meshes = (root, scene) => {
18688
+ const cached2 = roots.get(root);
18689
+ if (cached2) return cached2;
18690
+ const result = pickableMeshes(root, scene, raycaster);
18691
+ roots.set(root, result);
18692
+ return result;
18693
+ };
18694
+ const add = (root, owner, reference) => {
18695
+ for (const mesh of meshes(root, owner.chunk.scene)) {
18696
+ if (reference && reference.instanceable.getInstanceReference(mesh, reference.index) !== reference) continue;
18697
+ let entry = targets.get(mesh);
18698
+ if (!entry) targets.set(mesh, entry = { owners: /* @__PURE__ */ new Map() });
18699
+ entry.owners.set(reference?.index, owner);
18700
+ }
18701
+ };
18702
+ for (const chunk of chunks) {
18703
+ for (const index of chunk.objectBlocks) {
18704
+ const block = chunk.renderedBlocks.get(index).object;
18705
+ if (!block || !block.visible || chunk.hiddenBlocks.has(index)) continue;
18706
+ const owner = { chunk, index };
18707
+ for (const model of block.models) {
18708
+ if (isInstanceReference(model)) {
18709
+ if (model.instanceable.isInstanceActive(model.index, model)) add(model.instanceable, owner, model);
18710
+ } else {
18711
+ add(model, owner);
18712
+ }
18713
+ }
18714
+ for (const entity of block.blockEntities) add(entity, owner);
18715
+ }
18716
+ if (chunk.sectionMesh) {
18717
+ for (const mesh of meshes(chunk.sectionMesh, chunk.scene)) {
18718
+ targets.set(mesh, { owners: /* @__PURE__ */ new Map(), section: { chunk, mesh: chunk.sectionMesh } });
18719
+ }
18720
+ }
18721
+ }
18722
+ for (const hit of visibleHits(raycaster, [...targets.keys()])) {
18723
+ const mesh = hit.object;
18724
+ const entry = targets.get(mesh);
18725
+ let owner = entry.owners.get(hit.instanceId) ?? entry.owners.get(void 0);
18726
+ if (entry.section) {
18727
+ const index = entry.section.mesh.getBlockIndex(hit);
18728
+ if (index !== void 0) owner = { chunk: entry.section.chunk, index };
18729
+ }
18730
+ if (!owner || owner.chunk.hiddenBlocks.has(owner.index)) continue;
18731
+ const info = owner.chunk.renderedBlocks.get(owner.index);
18732
+ if (!info) continue;
18733
+ return {
18734
+ position: new Vector320(
18735
+ owner.chunk.x * 16 + owner.index % 16,
18736
+ owner.chunk.y * 16 + Math.floor(owner.index / 256),
18737
+ owner.chunk.z * 16 + Math.floor(owner.index / 16) % 16
18738
+ ),
18739
+ block: info.block,
18740
+ point: hit.point.clone(),
18741
+ normal: hitNormal(hit),
18742
+ distance: hit.distance
18743
+ };
18744
+ }
18745
+ return void 0;
18746
+ }
18588
18747
  getBlockAt(posOrX, y, z) {
18589
18748
  if (typeof posOrX == "number") {
18590
- return this.getBlockAt(new Vector318(posOrX, y, z));
18749
+ return this.getBlockAt(new Vector320(posOrX, y, z));
18591
18750
  }
18592
18751
  if (isTripleArray(posOrX)) {
18593
- return this.getBlockAt(new Vector318(posOrX[0], posOrX[1], posOrX[2]));
18752
+ return this.getBlockAt(new Vector320(posOrX[0], posOrX[1], posOrX[2]));
18594
18753
  }
18595
18754
  const pos = this.blockPosition.set(posOrX.x - this.x * 16, posOrX.y - this.y * 16, posOrX.z - this.z * 16);
18596
18755
  const index = _Chunk.chunkPosToBlockIndex(pos);
18597
18756
  return this.renderedBlocks.get(index);
18598
18757
  }
18599
18758
  getBiomeAt(posOrX, y, z) {
18600
- if (typeof posOrX === "number") return this.getBiomeAt(new Vector318(posOrX, y, z));
18601
- if (isTripleArray(posOrX)) return this.getBiomeAt(new Vector318(...posOrX));
18759
+ if (typeof posOrX === "number") return this.getBiomeAt(new Vector320(posOrX, y, z));
18760
+ if (isTripleArray(posOrX)) return this.getBiomeAt(new Vector320(...posOrX));
18602
18761
  const pos = this.worldPosToChunkPos(posOrX);
18603
18762
  _Chunk.chunkPosToBlockIndex(pos);
18604
18763
  return this.biomeAt ? this.biomeAt(posOrX.x, posOrX.y, posOrX.z) : this.biomes?.[Math.floor(pos.x / 4) + Math.floor(pos.z / 4) * 4 + Math.floor(pos.y / 4) * 16];
@@ -18641,17 +18800,17 @@ var Chunk = class _Chunk {
18641
18800
  this.hiddenBlocks.add(index);
18642
18801
  this.renderedBlocks.get(index)?.object?.setVisible(false);
18643
18802
  }
18644
- const positions = blocks.map(({ index }) => new Vector318(...this.positionAt(index)));
18803
+ const positions = blocks.map(({ index }) => new Vector320(...this.positionAt(index)));
18645
18804
  if (this.onBlocksChanged) await this.onBlocksChanged(positions);
18646
18805
  else await this.rebuildSectionMesh();
18647
18806
  }
18648
18807
  }
18649
18808
  async setBlockAt(posOrX, yOrBlock, z, block) {
18650
18809
  if (typeof posOrX == "number") {
18651
- return this.setBlockAt(new Vector318(posOrX, yOrBlock, z), block);
18810
+ return this.setBlockAt(new Vector320(posOrX, yOrBlock, z), block);
18652
18811
  }
18653
18812
  if (isTripleArray(posOrX)) {
18654
- return this.setBlockAt(new Vector318(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
18813
+ return this.setBlockAt(new Vector320(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
18655
18814
  }
18656
18815
  const worldPos = posOrX;
18657
18816
  const pos = this.worldPosToChunkPos(worldPos);
@@ -18705,7 +18864,8 @@ var Chunk = class _Chunk {
18705
18864
  if (this.fluidCells[index]) this.meshDirty = true;
18706
18865
  this.fluidCells[index] = 0;
18707
18866
  this.renderedBlocks.delete(index);
18708
- const worldPos = new Vector318(
18867
+ this.objectBlocks.delete(index);
18868
+ const worldPos = new Vector320(
18709
18869
  this.x * 16 + index % 16,
18710
18870
  this.y * 16 + Math.floor(index / 256),
18711
18871
  this.z * 16 + Math.floor(index / 16) % 16
@@ -18747,6 +18907,7 @@ var Chunk = class _Chunk {
18747
18907
  this.renderedBlocks.set(index, { get block() {
18748
18908
  return readBlock();
18749
18909
  }, object: object4 });
18910
+ if (object4) this.objectBlocks.add(index);
18750
18911
  } catch (error) {
18751
18912
  this.data.assign(index, 0);
18752
18913
  this.fluidCells[index] = 0;
@@ -18765,6 +18926,7 @@ var Chunk = class _Chunk {
18765
18926
  this.fluidCells.fill(0);
18766
18927
  this.waterTints = void 0;
18767
18928
  this.renderedBlocks.clear();
18929
+ this.objectBlocks.clear();
18768
18930
  this.hiddenBlocks.clear();
18769
18931
  this.meshDirty = true;
18770
18932
  this.data.copyFrom(data);
@@ -18814,6 +18976,7 @@ var Chunk = class _Chunk {
18814
18976
  this.renderedBlocks.set(index, { get block() {
18815
18977
  return readBlock();
18816
18978
  }, object: void 0 });
18979
+ this.objectBlocks.delete(index);
18817
18980
  } catch (error) {
18818
18981
  this.data.assign(index, 0);
18819
18982
  this.fluidCells[index] = 0;
@@ -18833,16 +18996,18 @@ var Chunk = class _Chunk {
18833
18996
  biome,
18834
18997
  biomePosition: this.biomePosition(index, blockState3, this.data.stateAt(this.data.idAt(index)))
18835
18998
  });
18836
- object4.setPosition(new Vector318(
18999
+ object4.setPosition(new Vector320(
18837
19000
  this.x * 256 + index % 16 * 16,
18838
19001
  this.y * 256 + Math.floor(index / 256) * 16,
18839
19002
  this.z * 256 + Math.floor(index / 16) % 16 * 16
18840
19003
  ));
18841
19004
  this.renderedBlocks.get(index).object = object4;
19005
+ this.objectBlocks.add(index);
18842
19006
  } catch (error) {
18843
19007
  this.data.assign(index, 0);
18844
19008
  this.fluidCells[index] = 0;
18845
19009
  this.renderedBlocks.delete(index);
19010
+ this.objectBlocks.delete(index);
18846
19011
  object4?.removeFromScene();
18847
19012
  if (!failed) failure = error;
18848
19013
  failed = true;
@@ -19094,7 +19259,7 @@ var Chunk = class _Chunk {
19094
19259
  /** Removes stored blocks and render objects. Set `notify` to false to skip the owning world's update. */
19095
19260
  async clear(notify = true) {
19096
19261
  const positions = notify && this.onBlocksChanged ? [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
19097
- new Vector318(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
19262
+ new Vector320(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
19098
19263
  )) : [];
19099
19264
  for (const info of this.renderedBlocks.values()) info.object?.removeFromScene();
19100
19265
  this.sectionBlocks.clear();
@@ -19103,6 +19268,7 @@ var Chunk = class _Chunk {
19103
19268
  this.sectionMesh = void 0;
19104
19269
  this.meshDirty = false;
19105
19270
  this.renderedBlocks.clear();
19271
+ this.objectBlocks.clear();
19106
19272
  this.hiddenBlocks.clear();
19107
19273
  this.fluidCells.fill(0);
19108
19274
  this.waterTints = void 0;
@@ -19129,14 +19295,14 @@ var Chunk = class _Chunk {
19129
19295
  return pos.y * 16 * 16 + pos.z * 16 + pos.x;
19130
19296
  }
19131
19297
  worldPosToChunkPos(pos) {
19132
- return new Vector318(
19298
+ return new Vector320(
19133
19299
  pos.x - this.x * 16,
19134
19300
  pos.y - this.y * 16,
19135
19301
  pos.z - this.z * 16
19136
19302
  );
19137
19303
  }
19138
19304
  chunkPosToWorldPos(pos) {
19139
- return new Vector318(
19305
+ return new Vector320(
19140
19306
  this.x * 16 + pos.x,
19141
19307
  this.y * 16 + pos.y,
19142
19308
  this.z * 16 + pos.z