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.
package/dist/bundle.js CHANGED
@@ -100712,6 +100712,10 @@ property list uchar int vertex_index
100712
100712
  get blockEntities() {
100713
100713
  return this._entities;
100714
100714
  }
100715
+ /** Model placements drawn for this block, including its fluid surface. */
100716
+ get models() {
100717
+ return this._models;
100718
+ }
100715
100719
  /** Sets visibility for this block's model instances and block entities. */
100716
100720
  setVisible(visible) {
100717
100721
  this.visible = visible;
@@ -107849,11 +107853,77 @@ gl_FragDepth=readDepth(vUv);
107849
107853
 
107850
107854
  // src/world/_entities/WorldEntities.ts
107851
107855
  init_BannerPatterns();
107856
+ init_three_module();
107857
+
107858
+ // src/world/_picking/Picking.ts
107859
+ init_dirname();
107860
+ init_buffer2();
107861
+ init_process2();
107862
+ init_three_module();
107863
+ init_three();
107864
+ function pickableMeshes(root, scene, raycaster) {
107865
+ const result = [];
107866
+ let attached = false;
107867
+ for (let parent = root; parent; parent = parent.parent) {
107868
+ if (!parent.visible) return result;
107869
+ if (parent === scene) attached = true;
107870
+ }
107871
+ if (!attached) return result;
107872
+ root.updateWorldMatrix(true, true);
107873
+ root.traverseVisible((object4) => {
107874
+ if (isMesh(object4) && raycaster.layers.test(object4.layers)) result.push(object4);
107875
+ });
107876
+ return result;
107877
+ }
107878
+ function visibleHits(raycaster, meshes) {
107879
+ return raycaster.intersectObjects(meshes, false).filter((hit) => {
107880
+ if (!hit.face) return false;
107881
+ const mesh = hit.object;
107882
+ const material = Array.isArray(mesh.material) ? mesh.material[hit.face.materialIndex] : mesh.material;
107883
+ return material?.visible;
107884
+ });
107885
+ }
107886
+ function hitNormal(hit) {
107887
+ const mesh = hit.object;
107888
+ const matrix = mesh.matrixWorld.clone();
107889
+ if (isInstancedMesh(mesh) && hit.instanceId !== void 0) {
107890
+ const instance = new Matrix4();
107891
+ mesh.getMatrixAt(hit.instanceId, instance);
107892
+ matrix.multiply(instance);
107893
+ }
107894
+ return hit.face.normal.clone().applyNormalMatrix(new Matrix3().getNormalMatrix(matrix));
107895
+ }
107896
+
107897
+ // src/world/_entities/WorldEntities.ts
107852
107898
  var WorldEntities = class {
107853
107899
  constructor(scene) {
107854
107900
  this.scene = scene;
107855
107901
  this.columns = /* @__PURE__ */ new Map();
107856
107902
  }
107903
+ /** Finds the nearest visible triangle belonging to an entity owned by this world. */
107904
+ raycast(raycaster) {
107905
+ const owners = /* @__PURE__ */ new Map();
107906
+ for (const column of this.columns.values()) {
107907
+ for (const [object4, placement] of column) {
107908
+ for (const mesh of pickableMeshes(object4, this.scene, raycaster)) {
107909
+ owners.set(mesh, { object: object4, ...placement });
107910
+ }
107911
+ }
107912
+ }
107913
+ for (const hit of visibleHits(raycaster, [...owners.keys()])) {
107914
+ const mesh = hit.object;
107915
+ const owner = owners.get(mesh);
107916
+ return {
107917
+ type: owner.type,
107918
+ position: new Vector3(...owner.position),
107919
+ object: owner.object,
107920
+ point: hit.point.clone(),
107921
+ normal: hitNormal(hit),
107922
+ distance: hit.distance
107923
+ };
107924
+ }
107925
+ return void 0;
107926
+ }
107857
107927
  /** Captures column ownership before asynchronous block or asset loading starts. */
107858
107928
  prepare(entities = [], column) {
107859
107929
  const placements = entities.flatMap((entity) => {
@@ -107862,7 +107932,7 @@ gl_FragDepth=readDepth(vUv);
107862
107932
  const position = [...entity.position];
107863
107933
  const key = column?.join(",") ?? `${Math.floor(position[0] / 16)},${Math.floor(position[2] / 16)}`;
107864
107934
  let owner = this.columns.get(key);
107865
- if (!owner) this.columns.set(key, owner = /* @__PURE__ */ new Set());
107935
+ if (!owner) this.columns.set(key, owner = /* @__PURE__ */ new Map());
107866
107936
  return [{ ...resolved, position, column: key, owner }];
107867
107937
  });
107868
107938
  return async () => {
@@ -107888,7 +107958,7 @@ gl_FragDepth=readDepth(vUv);
107888
107958
  object4.rotation.y = placement.yaw;
107889
107959
  await object4.init();
107890
107960
  if (!current()) return;
107891
- placement.owner.add(object4);
107961
+ placement.owner.set(object4, { type: placement.key.toNamespacedString(), position: placement.position });
107892
107962
  this.scene.add(object4);
107893
107963
  } catch (error2) {
107894
107964
  console.warn(`Could not draw saved entity ${placement.key.toNamespacedString()}, skipping it`, error2);
@@ -107903,7 +107973,7 @@ gl_FragDepth=readDepth(vUv);
107903
107973
  const objects = this.columns.get(key);
107904
107974
  this.columns.delete(key);
107905
107975
  if (!objects) return;
107906
- for (const object4 of objects) {
107976
+ for (const object4 of objects.keys()) {
107907
107977
  object4.removeFromScene();
107908
107978
  object4.dispose();
107909
107979
  }
@@ -107967,6 +108037,21 @@ gl_FragDepth=readDepth(vUv);
107967
108037
  if (options.sectionMeshing) this.sectionModels = new SectionModels(options.maxAtlasSize);
107968
108038
  if (options.renderEntities) this.entities = new WorldEntities(scene);
107969
108039
  }
108040
+ /**
108041
+ * Returns the nearest visible block geometry hit, respecting the raycaster's layers and near/far range.
108042
+ * Includes fluids and block entities; texture alpha does not change triangle intersections.
108043
+ */
108044
+ raycast(raycaster) {
108045
+ return Chunk.raycast(this._chunks.values(), raycaster);
108046
+ }
108047
+ /**
108048
+ * Returns the nearest visible mob geometry hit when renderEntities is enabled.
108049
+ * Respects layers and near/far; compare its distance with raycast() to account for blocks.
108050
+ * Texture alpha does not change triangle intersections.
108051
+ */
108052
+ raycastEntities(raycaster) {
108053
+ return this.entities?.raycast(raycaster);
108054
+ }
107970
108055
  /** Whether neighboring opaque cubes shade block-face corners. Defaults to false. */
107971
108056
  get ambientOcclusion() {
107972
108057
  return this._ambientOcclusion;
@@ -108653,6 +108738,7 @@ gl_FragDepth=readDepth(vUv);
108653
108738
  const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);
108654
108739
  const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);
108655
108740
  const outputIndices = new Uint32Array(faces * 6);
108741
+ const blockIndices = new Uint16Array(faces);
108656
108742
  let vertex2 = 0, indexOffset = 0;
108657
108743
  for (const entry of page.entries) {
108658
108744
  const template = templateData[templates[entry]];
@@ -108667,6 +108753,7 @@ gl_FragDepth=readDepth(vUv);
108667
108753
  const ambientMask = ambientOcclusion && template.ambientOcclusion !== false ? sectionAmbientOcclusionMask(ambientOcclusion, lightIndex) : 0;
108668
108754
  for (let quad = 0; quad < template.quads; quad++) {
108669
108755
  if (cullMasks[entry] & template.cullFaces[quad]) continue;
108756
+ blockIndices[indexOffset / 6] = indices[entry];
108670
108757
  if (ambientMask) quadAmbientOcclusion(template.positions, template.normals, quad, ambientMask, cornerBrightness2);
108671
108758
  const brightness = light ? lightBrightness(light[lightIndex + LIGHT_SAMPLE_OFFSETS[quadLightIndex(template.positions, template.normals, quad)]], ambientLight) : 1;
108672
108759
  const start = vertex2;
@@ -108699,6 +108786,7 @@ gl_FragDepth=readDepth(vUv);
108699
108786
  const mapV = (v5) => 1 - (placement.y + (1 - v5) * atlas.height) / page.height;
108700
108787
  const lightIndex = (y5 + 1) * 324 + (z4 + 1) * 18 + x4 + 1;
108701
108788
  for (let quad = 0; quad < quads.sprites.length; quad++) {
108789
+ blockIndices[indexOffset / 6] = x4 + z4 * 16 + y5 * 256;
108702
108790
  const rect = quads.sprites[quad] === 0 ? data.still : data.flow;
108703
108791
  const brightness = light ? lightBrightness(fluidLightLevel(
108704
108792
  light[lightIndex],
@@ -108729,11 +108817,11 @@ gl_FragDepth=readDepth(vUv);
108729
108817
  indexOffset += 6;
108730
108818
  }
108731
108819
  }
108732
- return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices };
108820
+ return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices, blockIndices };
108733
108821
  });
108734
108822
  }
108735
108823
  function sectionGeometryTransferables(pages) {
108736
- return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer]);
108824
+ 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]);
108737
108825
  }
108738
108826
 
108739
108827
  // src/world/SectionWorker.ts
@@ -108894,6 +108982,12 @@ gl_FragDepth=readDepth(vUv);
108894
108982
  constructor() {
108895
108983
  super(...arguments);
108896
108984
  this.ownedMeshes = [];
108985
+ this.blockIndices = /* @__PURE__ */ new Map();
108986
+ }
108987
+ /** Returns the owning section cell for a triangle hit on this mesh's merged geometry. */
108988
+ getBlockIndex(hit) {
108989
+ if (hit.faceIndex === void 0 || hit.faceIndex === null) return void 0;
108990
+ return this.blockIndices.get(hit.object)?.[Math.floor(hit.faceIndex / 2)];
108897
108991
  }
108898
108992
  /** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
108899
108993
  static build(entries, maxAtlasSize = 2048, fluids, lighting) {
@@ -108936,6 +109030,7 @@ gl_FragDepth=readDepth(vUv);
108936
109030
  const texture = material.uniforms?.map?.value ?? material.map;
108937
109031
  const mesh = new Mesh(geometry, material);
108938
109032
  section.add(mesh);
109033
+ section.blockIndices.set(mesh, page.blockIndices);
108939
109034
  const unsubscribe = [];
108940
109035
  for (const { atlas: id, x: x4, y: y5 } of page.placements) {
108941
109036
  const atlas = atlases[id];
@@ -108961,6 +109056,7 @@ gl_FragDepth=readDepth(vUv);
108961
109056
  mesh.material.dispose();
108962
109057
  texture?.dispose();
108963
109058
  }
109059
+ this.blockIndices.clear();
108964
109060
  this.removeFromParent();
108965
109061
  super.dispose();
108966
109062
  }
@@ -108970,6 +109066,7 @@ gl_FragDepth=readDepth(vUv);
108970
109066
  init_FluidGeometry();
108971
109067
  init_FluidQuads();
108972
109068
  init_CubeFace();
109069
+ init_InstanceReference();
108973
109070
  var WATER_TINT2 = new Color(4159204).toArray();
108974
109071
  var Chunk = class _Chunk {
108975
109072
  constructor(scene, x4, y5, z4, onBlocksChanged, sectionModels, neighborCell, biomeAt, onBiomesChanged, lightAt, onLightCleared, ambientLight = 0) {
@@ -108983,6 +109080,7 @@ gl_FragDepth=readDepth(vUv);
108983
109080
  this.ambientLight = ambientLight;
108984
109081
  this.data = new ChunkData();
108985
109082
  this.renderedBlocks = /* @__PURE__ */ new Map();
109083
+ this.objectBlocks = /* @__PURE__ */ new Set();
108986
109084
  this.sectionBlocks = /* @__PURE__ */ new Map();
108987
109085
  this.hiddenBlocks = /* @__PURE__ */ new Set();
108988
109086
  this.fluidCells = new Uint8Array(4096);
@@ -108994,6 +109092,70 @@ gl_FragDepth=readDepth(vUv);
108994
109092
  this.y = y5;
108995
109093
  this.z = z4;
108996
109094
  }
109095
+ /** Finds the nearest owned block hit across sections, testing each shared mesh once. */
109096
+ static raycast(chunks, raycaster) {
109097
+ const roots = /* @__PURE__ */ new Map();
109098
+ const targets = /* @__PURE__ */ new Map();
109099
+ const meshes = (root, scene) => {
109100
+ const cached2 = roots.get(root);
109101
+ if (cached2) return cached2;
109102
+ const result = pickableMeshes(root, scene, raycaster);
109103
+ roots.set(root, result);
109104
+ return result;
109105
+ };
109106
+ const add = (root, owner, reference) => {
109107
+ for (const mesh of meshes(root, owner.chunk.scene)) {
109108
+ if (reference && reference.instanceable.getInstanceReference(mesh, reference.index) !== reference) continue;
109109
+ let entry = targets.get(mesh);
109110
+ if (!entry) targets.set(mesh, entry = { owners: /* @__PURE__ */ new Map() });
109111
+ entry.owners.set(reference?.index, owner);
109112
+ }
109113
+ };
109114
+ for (const chunk of chunks) {
109115
+ for (const index of chunk.objectBlocks) {
109116
+ const block = chunk.renderedBlocks.get(index).object;
109117
+ if (!block || !block.visible || chunk.hiddenBlocks.has(index)) continue;
109118
+ const owner = { chunk, index };
109119
+ for (const model of block.models) {
109120
+ if (isInstanceReference(model)) {
109121
+ if (model.instanceable.isInstanceActive(model.index, model)) add(model.instanceable, owner, model);
109122
+ } else {
109123
+ add(model, owner);
109124
+ }
109125
+ }
109126
+ for (const entity of block.blockEntities) add(entity, owner);
109127
+ }
109128
+ if (chunk.sectionMesh) {
109129
+ for (const mesh of meshes(chunk.sectionMesh, chunk.scene)) {
109130
+ targets.set(mesh, { owners: /* @__PURE__ */ new Map(), section: { chunk, mesh: chunk.sectionMesh } });
109131
+ }
109132
+ }
109133
+ }
109134
+ for (const hit of visibleHits(raycaster, [...targets.keys()])) {
109135
+ const mesh = hit.object;
109136
+ const entry = targets.get(mesh);
109137
+ let owner = entry.owners.get(hit.instanceId) ?? entry.owners.get(void 0);
109138
+ if (entry.section) {
109139
+ const index = entry.section.mesh.getBlockIndex(hit);
109140
+ if (index !== void 0) owner = { chunk: entry.section.chunk, index };
109141
+ }
109142
+ if (!owner || owner.chunk.hiddenBlocks.has(owner.index)) continue;
109143
+ const info = owner.chunk.renderedBlocks.get(owner.index);
109144
+ if (!info) continue;
109145
+ return {
109146
+ position: new Vector3(
109147
+ owner.chunk.x * 16 + owner.index % 16,
109148
+ owner.chunk.y * 16 + Math.floor(owner.index / 256),
109149
+ owner.chunk.z * 16 + Math.floor(owner.index / 16) % 16
109150
+ ),
109151
+ block: info.block,
109152
+ point: hit.point.clone(),
109153
+ normal: hitNormal(hit),
109154
+ distance: hit.distance
109155
+ };
109156
+ }
109157
+ return void 0;
109158
+ }
108997
109159
  getBlockAt(posOrX, y5, z4) {
108998
109160
  if (typeof posOrX == "number") {
108999
109161
  return this.getBlockAt(new Vector3(posOrX, y5, z4));
@@ -109114,6 +109276,7 @@ gl_FragDepth=readDepth(vUv);
109114
109276
  if (this.fluidCells[index]) this.meshDirty = true;
109115
109277
  this.fluidCells[index] = 0;
109116
109278
  this.renderedBlocks.delete(index);
109279
+ this.objectBlocks.delete(index);
109117
109280
  const worldPos = new Vector3(
109118
109281
  this.x * 16 + index % 16,
109119
109282
  this.y * 16 + Math.floor(index / 256),
@@ -109156,6 +109319,7 @@ gl_FragDepth=readDepth(vUv);
109156
109319
  this.renderedBlocks.set(index, { get block() {
109157
109320
  return readBlock();
109158
109321
  }, object: object4 });
109322
+ if (object4) this.objectBlocks.add(index);
109159
109323
  } catch (error2) {
109160
109324
  this.data.assign(index, 0);
109161
109325
  this.fluidCells[index] = 0;
@@ -109174,6 +109338,7 @@ gl_FragDepth=readDepth(vUv);
109174
109338
  this.fluidCells.fill(0);
109175
109339
  this.waterTints = void 0;
109176
109340
  this.renderedBlocks.clear();
109341
+ this.objectBlocks.clear();
109177
109342
  this.hiddenBlocks.clear();
109178
109343
  this.meshDirty = true;
109179
109344
  this.data.copyFrom(data);
@@ -109223,6 +109388,7 @@ gl_FragDepth=readDepth(vUv);
109223
109388
  this.renderedBlocks.set(index, { get block() {
109224
109389
  return readBlock();
109225
109390
  }, object: void 0 });
109391
+ this.objectBlocks.delete(index);
109226
109392
  } catch (error2) {
109227
109393
  this.data.assign(index, 0);
109228
109394
  this.fluidCells[index] = 0;
@@ -109248,10 +109414,12 @@ gl_FragDepth=readDepth(vUv);
109248
109414
  this.z * 256 + Math.floor(index / 16) % 16 * 16
109249
109415
  ));
109250
109416
  this.renderedBlocks.get(index).object = object4;
109417
+ this.objectBlocks.add(index);
109251
109418
  } catch (error2) {
109252
109419
  this.data.assign(index, 0);
109253
109420
  this.fluidCells[index] = 0;
109254
109421
  this.renderedBlocks.delete(index);
109422
+ this.objectBlocks.delete(index);
109255
109423
  object4?.removeFromScene();
109256
109424
  if (!failed) failure = error2;
109257
109425
  failed = true;
@@ -109512,6 +109680,7 @@ gl_FragDepth=readDepth(vUv);
109512
109680
  this.sectionMesh = void 0;
109513
109681
  this.meshDirty = false;
109514
109682
  this.renderedBlocks.clear();
109683
+ this.objectBlocks.clear();
109515
109684
  this.hiddenBlocks.clear();
109516
109685
  this.fluidCells.fill(0);
109517
109686
  this.waterTints = void 0;
@@ -109553,11 +109722,21 @@ gl_FragDepth=readDepth(vUv);
109553
109722
  }
109554
109723
  };
109555
109724
 
109725
+ // src/world/WorldBlockIntersection.ts
109726
+ init_dirname();
109727
+ init_buffer2();
109728
+ init_process2();
109729
+
109556
109730
  // src/world/WorldChunkSource.ts
109557
109731
  init_dirname();
109558
109732
  init_buffer2();
109559
109733
  init_process2();
109560
109734
 
109735
+ // src/world/WorldEntityIntersection.ts
109736
+ init_dirname();
109737
+ init_buffer2();
109738
+ init_process2();
109739
+
109561
109740
  // src/world/WorldStreamer.ts
109562
109741
  init_dirname();
109563
109742
  init_buffer2();