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/browser/index.d.mts +52 -1
- package/dist/browser/index.d.ts +52 -1
- package/dist/browser/index.js +219 -53
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +206 -40
- package/dist/browser/index.mjs.map +1 -1
- package/dist/browser/section.worker.js +5 -2
- package/dist/browser/section.worker.js.map +1 -1
- package/dist/browser/section.worker.mjs +5 -2
- package/dist/browser/section.worker.mjs.map +1 -1
- package/dist/bundle.js +184 -5
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +52 -1
- package/dist/node/index.d.ts +52 -1
- package/dist/node/index.js +219 -53
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +206 -40
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.mjs
CHANGED
|
@@ -12463,6 +12463,10 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
12463
12463
|
get blockEntities() {
|
|
12464
12464
|
return this._entities;
|
|
12465
12465
|
}
|
|
12466
|
+
/** Model placements drawn for this block, including its fluid surface. */
|
|
12467
|
+
get models() {
|
|
12468
|
+
return this._models;
|
|
12469
|
+
}
|
|
12466
12470
|
/** Sets visibility for this block's model instances and block entities. */
|
|
12467
12471
|
setVisible(visible) {
|
|
12468
12472
|
this.visible = visible;
|
|
@@ -17224,14 +17228,14 @@ var AnvilWorldSource = class {
|
|
|
17224
17228
|
};
|
|
17225
17229
|
|
|
17226
17230
|
// src/world/Chunk.ts
|
|
17227
|
-
import { Color as Color13, Vector3 as
|
|
17231
|
+
import { Color as Color13, Vector3 as Vector320 } from "three";
|
|
17228
17232
|
init_BlockStates();
|
|
17229
17233
|
init_AssetKey();
|
|
17230
17234
|
|
|
17231
17235
|
// src/world/MineRenderWorld.ts
|
|
17232
17236
|
init_Model();
|
|
17233
17237
|
init_util();
|
|
17234
|
-
import { Vector3 as
|
|
17238
|
+
import { Vector3 as Vector319 } from "three";
|
|
17235
17239
|
init_AssetKey();
|
|
17236
17240
|
init_BlockStates();
|
|
17237
17241
|
init_CubeFace();
|
|
@@ -17494,11 +17498,74 @@ function resolveSavedEntity(entity) {
|
|
|
17494
17498
|
|
|
17495
17499
|
// src/world/_entities/WorldEntities.ts
|
|
17496
17500
|
init_BannerPatterns();
|
|
17501
|
+
import { Vector3 as Vector318 } from "three";
|
|
17502
|
+
|
|
17503
|
+
// src/world/_picking/Picking.ts
|
|
17504
|
+
init_three();
|
|
17505
|
+
import { Matrix3 as Matrix33, Matrix4 as Matrix413 } from "three";
|
|
17506
|
+
function pickableMeshes(root, scene, raycaster) {
|
|
17507
|
+
const result = [];
|
|
17508
|
+
let attached = false;
|
|
17509
|
+
for (let parent = root; parent; parent = parent.parent) {
|
|
17510
|
+
if (!parent.visible) return result;
|
|
17511
|
+
if (parent === scene) attached = true;
|
|
17512
|
+
}
|
|
17513
|
+
if (!attached) return result;
|
|
17514
|
+
root.updateWorldMatrix(true, true);
|
|
17515
|
+
root.traverseVisible((object4) => {
|
|
17516
|
+
if (isMesh(object4) && raycaster.layers.test(object4.layers)) result.push(object4);
|
|
17517
|
+
});
|
|
17518
|
+
return result;
|
|
17519
|
+
}
|
|
17520
|
+
function visibleHits(raycaster, meshes) {
|
|
17521
|
+
return raycaster.intersectObjects(meshes, false).filter((hit) => {
|
|
17522
|
+
if (!hit.face) return false;
|
|
17523
|
+
const mesh = hit.object;
|
|
17524
|
+
const material = Array.isArray(mesh.material) ? mesh.material[hit.face.materialIndex] : mesh.material;
|
|
17525
|
+
return material?.visible;
|
|
17526
|
+
});
|
|
17527
|
+
}
|
|
17528
|
+
function hitNormal(hit) {
|
|
17529
|
+
const mesh = hit.object;
|
|
17530
|
+
const matrix = mesh.matrixWorld.clone();
|
|
17531
|
+
if (isInstancedMesh(mesh) && hit.instanceId !== void 0) {
|
|
17532
|
+
const instance = new Matrix413();
|
|
17533
|
+
mesh.getMatrixAt(hit.instanceId, instance);
|
|
17534
|
+
matrix.multiply(instance);
|
|
17535
|
+
}
|
|
17536
|
+
return hit.face.normal.clone().applyNormalMatrix(new Matrix33().getNormalMatrix(matrix));
|
|
17537
|
+
}
|
|
17538
|
+
|
|
17539
|
+
// src/world/_entities/WorldEntities.ts
|
|
17497
17540
|
var WorldEntities = class {
|
|
17498
17541
|
constructor(scene) {
|
|
17499
17542
|
this.scene = scene;
|
|
17500
17543
|
this.columns = /* @__PURE__ */ new Map();
|
|
17501
17544
|
}
|
|
17545
|
+
/** Finds the nearest visible triangle belonging to an entity owned by this world. */
|
|
17546
|
+
raycast(raycaster) {
|
|
17547
|
+
const owners = /* @__PURE__ */ new Map();
|
|
17548
|
+
for (const column of this.columns.values()) {
|
|
17549
|
+
for (const [object4, placement] of column) {
|
|
17550
|
+
for (const mesh of pickableMeshes(object4, this.scene, raycaster)) {
|
|
17551
|
+
owners.set(mesh, { object: object4, ...placement });
|
|
17552
|
+
}
|
|
17553
|
+
}
|
|
17554
|
+
}
|
|
17555
|
+
for (const hit of visibleHits(raycaster, [...owners.keys()])) {
|
|
17556
|
+
const mesh = hit.object;
|
|
17557
|
+
const owner = owners.get(mesh);
|
|
17558
|
+
return {
|
|
17559
|
+
type: owner.type,
|
|
17560
|
+
position: new Vector318(...owner.position),
|
|
17561
|
+
object: owner.object,
|
|
17562
|
+
point: hit.point.clone(),
|
|
17563
|
+
normal: hitNormal(hit),
|
|
17564
|
+
distance: hit.distance
|
|
17565
|
+
};
|
|
17566
|
+
}
|
|
17567
|
+
return void 0;
|
|
17568
|
+
}
|
|
17502
17569
|
/** Captures column ownership before asynchronous block or asset loading starts. */
|
|
17503
17570
|
prepare(entities = [], column) {
|
|
17504
17571
|
const placements = entities.flatMap((entity) => {
|
|
@@ -17507,7 +17574,7 @@ var WorldEntities = class {
|
|
|
17507
17574
|
const position = [...entity.position];
|
|
17508
17575
|
const key = column?.join(",") ?? `${Math.floor(position[0] / 16)},${Math.floor(position[2] / 16)}`;
|
|
17509
17576
|
let owner = this.columns.get(key);
|
|
17510
|
-
if (!owner) this.columns.set(key, owner = /* @__PURE__ */ new
|
|
17577
|
+
if (!owner) this.columns.set(key, owner = /* @__PURE__ */ new Map());
|
|
17511
17578
|
return [{ ...resolved, position, column: key, owner }];
|
|
17512
17579
|
});
|
|
17513
17580
|
return async () => {
|
|
@@ -17533,7 +17600,7 @@ var WorldEntities = class {
|
|
|
17533
17600
|
object4.rotation.y = placement.yaw;
|
|
17534
17601
|
await object4.init();
|
|
17535
17602
|
if (!current()) return;
|
|
17536
|
-
placement.owner.
|
|
17603
|
+
placement.owner.set(object4, { type: placement.key.toNamespacedString(), position: placement.position });
|
|
17537
17604
|
this.scene.add(object4);
|
|
17538
17605
|
} catch (error) {
|
|
17539
17606
|
console.warn(`Could not draw saved entity ${placement.key.toNamespacedString()}, skipping it`, error);
|
|
@@ -17548,7 +17615,7 @@ var WorldEntities = class {
|
|
|
17548
17615
|
const objects = this.columns.get(key);
|
|
17549
17616
|
this.columns.delete(key);
|
|
17550
17617
|
if (!objects) return;
|
|
17551
|
-
for (const object4 of objects) {
|
|
17618
|
+
for (const object4 of objects.keys()) {
|
|
17552
17619
|
object4.removeFromScene();
|
|
17553
17620
|
object4.dispose();
|
|
17554
17621
|
}
|
|
@@ -17609,6 +17676,21 @@ var MineRenderWorld = class {
|
|
|
17609
17676
|
if (options.sectionMeshing) this.sectionModels = new SectionModels(options.maxAtlasSize);
|
|
17610
17677
|
if (options.renderEntities) this.entities = new WorldEntities(scene);
|
|
17611
17678
|
}
|
|
17679
|
+
/**
|
|
17680
|
+
* Returns the nearest visible block geometry hit, respecting the raycaster's layers and near/far range.
|
|
17681
|
+
* Includes fluids and block entities; texture alpha does not change triangle intersections.
|
|
17682
|
+
*/
|
|
17683
|
+
raycast(raycaster) {
|
|
17684
|
+
return Chunk.raycast(this._chunks.values(), raycaster);
|
|
17685
|
+
}
|
|
17686
|
+
/**
|
|
17687
|
+
* Returns the nearest visible mob geometry hit when renderEntities is enabled.
|
|
17688
|
+
* Respects layers and near/far; compare its distance with raycast() to account for blocks.
|
|
17689
|
+
* Texture alpha does not change triangle intersections.
|
|
17690
|
+
*/
|
|
17691
|
+
raycastEntities(raycaster) {
|
|
17692
|
+
return this.entities?.raycast(raycaster);
|
|
17693
|
+
}
|
|
17612
17694
|
/** Whether neighboring opaque cubes shade block-face corners. Defaults to false. */
|
|
17613
17695
|
get ambientOcclusion() {
|
|
17614
17696
|
return this._ambientOcclusion;
|
|
@@ -17629,25 +17711,25 @@ var MineRenderWorld = class {
|
|
|
17629
17711
|
}
|
|
17630
17712
|
getBlockAt(posOrX, y, z) {
|
|
17631
17713
|
if (typeof posOrX == "number") {
|
|
17632
|
-
return this.getBlockAt(new
|
|
17714
|
+
return this.getBlockAt(new Vector319(posOrX, y, z));
|
|
17633
17715
|
}
|
|
17634
17716
|
if (isTripleArray(posOrX)) {
|
|
17635
|
-
return this.getBlockAt(new
|
|
17717
|
+
return this.getBlockAt(new Vector319(posOrX[0], posOrX[1], posOrX[2]));
|
|
17636
17718
|
}
|
|
17637
17719
|
this.validatePosBounds(posOrX);
|
|
17638
17720
|
return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
|
|
17639
17721
|
}
|
|
17640
17722
|
getBiomeAt(posOrX, y, z) {
|
|
17641
|
-
if (typeof posOrX === "number") return this.getBiomeAt(new
|
|
17642
|
-
if (isTripleArray(posOrX)) return this.getBiomeAt(new
|
|
17723
|
+
if (typeof posOrX === "number") return this.getBiomeAt(new Vector319(posOrX, y, z));
|
|
17724
|
+
if (isTripleArray(posOrX)) return this.getBiomeAt(new Vector319(...posOrX));
|
|
17643
17725
|
this.validatePosBounds(posOrX);
|
|
17644
17726
|
const cx = Math.floor(posOrX.x / 16), cy = Math.floor(posOrX.y / 16), cz = Math.floor(posOrX.z / 16);
|
|
17645
17727
|
const lx = posOrX.x - cx * 16, ly = posOrX.y - cy * 16, lz = posOrX.z - cz * 16;
|
|
17646
17728
|
return this.biomes.get(`${cx}_${cz}`)?.get(cy)?.[Math.floor(lx / 4) + Math.floor(lz / 4) * 4 + Math.floor(ly / 4) * 16];
|
|
17647
17729
|
}
|
|
17648
17730
|
getLightAt(posOrX, y, z) {
|
|
17649
|
-
if (typeof posOrX === "number") return this.getLightAt(new
|
|
17650
|
-
if (isTripleArray(posOrX)) return this.getLightAt(new
|
|
17731
|
+
if (typeof posOrX === "number") return this.getLightAt(new Vector319(posOrX, y, z));
|
|
17732
|
+
if (isTripleArray(posOrX)) return this.getLightAt(new Vector319(...posOrX));
|
|
17651
17733
|
this.validatePosBounds(posOrX);
|
|
17652
17734
|
const { x, y: py, z: pz } = posOrX;
|
|
17653
17735
|
const cx = Math.floor(x / 16), cy = Math.floor(py / 16), cz = Math.floor(pz / 16);
|
|
@@ -17665,10 +17747,10 @@ var MineRenderWorld = class {
|
|
|
17665
17747
|
}
|
|
17666
17748
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
17667
17749
|
if (typeof posOrX == "number") {
|
|
17668
|
-
return this.setBlockAt(new
|
|
17750
|
+
return this.setBlockAt(new Vector319(posOrX, yOrBlock, z), block);
|
|
17669
17751
|
}
|
|
17670
17752
|
if (isTripleArray(posOrX)) {
|
|
17671
|
-
return this.setBlockAt(new
|
|
17753
|
+
return this.setBlockAt(new Vector319(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
17672
17754
|
}
|
|
17673
17755
|
return this.placeBlock(posOrX, yOrBlock);
|
|
17674
17756
|
}
|
|
@@ -17679,10 +17761,10 @@ var MineRenderWorld = class {
|
|
|
17679
17761
|
}
|
|
17680
17762
|
async setBlockVisibleAt(posOrX, yOrVisible, z, visible) {
|
|
17681
17763
|
if (typeof posOrX === "number") {
|
|
17682
|
-
return this.setBlockVisibleAt(new
|
|
17764
|
+
return this.setBlockVisibleAt(new Vector319(posOrX, yOrVisible, z), visible);
|
|
17683
17765
|
}
|
|
17684
17766
|
if (isTripleArray(posOrX)) {
|
|
17685
|
-
return this.setBlockVisibleAt(new
|
|
17767
|
+
return this.setBlockVisibleAt(new Vector319(...posOrX), yOrVisible);
|
|
17686
17768
|
}
|
|
17687
17769
|
this.validatePosBounds(posOrX);
|
|
17688
17770
|
await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible);
|
|
@@ -17708,7 +17790,7 @@ var MineRenderWorld = class {
|
|
|
17708
17790
|
const collect = async (positions2) => {
|
|
17709
17791
|
for (const pos of positions2) changes.set(pos.toArray().join(","), pos);
|
|
17710
17792
|
};
|
|
17711
|
-
const place = (block) => this.placeBlock(new
|
|
17793
|
+
const place = (block) => this.placeBlock(new Vector319(...block.position), block, collect);
|
|
17712
17794
|
const keys = /* @__PURE__ */ new Map();
|
|
17713
17795
|
const types = /* @__PURE__ */ new Set();
|
|
17714
17796
|
for (const block of multiblock.blocks) {
|
|
@@ -17724,7 +17806,7 @@ var MineRenderWorld = class {
|
|
|
17724
17806
|
}
|
|
17725
17807
|
if (!executor) {
|
|
17726
17808
|
const groups2 = /* @__PURE__ */ new Map();
|
|
17727
|
-
const position = new
|
|
17809
|
+
const position = new Vector319();
|
|
17728
17810
|
for (const block of multiblock.blocks) {
|
|
17729
17811
|
const [x, y, z] = block.position;
|
|
17730
17812
|
this.validatePosBounds(position.set(x, y, z));
|
|
@@ -17764,7 +17846,7 @@ var MineRenderWorld = class {
|
|
|
17764
17846
|
try {
|
|
17765
17847
|
positions = await chunk.placeBlocks(blocks);
|
|
17766
17848
|
} finally {
|
|
17767
|
-
positions ??= blocks.map(({ index }) => new
|
|
17849
|
+
positions ??= blocks.map(({ index }) => new Vector319(
|
|
17768
17850
|
chunk.x * 16 + index % 16,
|
|
17769
17851
|
chunk.y * 16 + Math.floor(index / 256),
|
|
17770
17852
|
chunk.z * 16 + Math.floor(index / 16) % 16
|
|
@@ -17816,7 +17898,7 @@ var MineRenderWorld = class {
|
|
|
17816
17898
|
}
|
|
17817
17899
|
for (const section of chunk.sections) {
|
|
17818
17900
|
if (section.biomes) {
|
|
17819
|
-
const position = new
|
|
17901
|
+
const position = new Vector319(chunk.x * 16, section.y * 16, chunk.z * 16);
|
|
17820
17902
|
this.validatePosBounds(position);
|
|
17821
17903
|
const copy = [...section.biomes];
|
|
17822
17904
|
if (copy.length !== 64 || !copy.every((id) => typeof id === "string" && id.length > 0)) {
|
|
@@ -17832,7 +17914,7 @@ var MineRenderWorld = class {
|
|
|
17832
17914
|
for (const section of chunk.sections) {
|
|
17833
17915
|
if (!executor) {
|
|
17834
17916
|
if (!occupiedSections.has(section.y)) continue;
|
|
17835
|
-
const position = new
|
|
17917
|
+
const position = new Vector319(chunk.x * 16, section.y * 16, chunk.z * 16);
|
|
17836
17918
|
this.validatePosBounds(position);
|
|
17837
17919
|
const target = this.getOrCreateChunkAt(position);
|
|
17838
17920
|
try {
|
|
@@ -17936,7 +18018,7 @@ var MineRenderWorld = class {
|
|
|
17936
18018
|
this.sectionModels?.clear();
|
|
17937
18019
|
}
|
|
17938
18020
|
updateCulling(positions) {
|
|
17939
|
-
const neighbor = new
|
|
18021
|
+
const neighbor = new Vector319();
|
|
17940
18022
|
for (const pos of positions) {
|
|
17941
18023
|
const cx = Math.floor(pos.x / 16), cy = Math.floor(pos.y / 16), cz = Math.floor(pos.z / 16);
|
|
17942
18024
|
const chunk = this._chunks.get(`${cx}_${cy}_${cz}`);
|
|
@@ -18067,7 +18149,7 @@ var MineRenderWorld = class {
|
|
|
18067
18149
|
}
|
|
18068
18150
|
/** Converts block coordinates to scene units by multiplying each component by 16. */
|
|
18069
18151
|
static worldToScenePosition(pos) {
|
|
18070
|
-
return new
|
|
18152
|
+
return new Vector319(
|
|
18071
18153
|
pos.x * 16,
|
|
18072
18154
|
pos.y * 16,
|
|
18073
18155
|
pos.z * 16
|
|
@@ -18075,7 +18157,7 @@ var MineRenderWorld = class {
|
|
|
18075
18157
|
}
|
|
18076
18158
|
/** Converts scene units to block coordinates without rounding to an integer block. */
|
|
18077
18159
|
static sceneToWorldPosition(pos) {
|
|
18078
|
-
return new
|
|
18160
|
+
return new Vector319(
|
|
18079
18161
|
pos.x / 16,
|
|
18080
18162
|
pos.y / 16,
|
|
18081
18163
|
pos.z / 16
|
|
@@ -18100,7 +18182,7 @@ init_Model();
|
|
|
18100
18182
|
// src/world/SectionMesh.ts
|
|
18101
18183
|
init_CanvasCompat();
|
|
18102
18184
|
init_Materials();
|
|
18103
|
-
import { BufferGeometry as BufferGeometry9, Color as Color12, DoubleSide as DoubleSide8, Float32BufferAttribute as Float32BufferAttribute10, FrontSide as FrontSide4, Group as Group3, Mesh as
|
|
18185
|
+
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";
|
|
18104
18186
|
|
|
18105
18187
|
// src/world/SectionGeometry.ts
|
|
18106
18188
|
init_FluidQuads();
|
|
@@ -18283,6 +18365,7 @@ function buildSectionGeometry(input) {
|
|
|
18283
18365
|
const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);
|
|
18284
18366
|
const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);
|
|
18285
18367
|
const outputIndices = new Uint32Array(faces * 6);
|
|
18368
|
+
const blockIndices = new Uint16Array(faces);
|
|
18286
18369
|
let vertex = 0, indexOffset = 0;
|
|
18287
18370
|
for (const entry of page.entries) {
|
|
18288
18371
|
const template = templateData[templates[entry]];
|
|
@@ -18297,6 +18380,7 @@ function buildSectionGeometry(input) {
|
|
|
18297
18380
|
const ambientMask = ambientOcclusion && template.ambientOcclusion !== false ? sectionAmbientOcclusionMask(ambientOcclusion, lightIndex) : 0;
|
|
18298
18381
|
for (let quad = 0; quad < template.quads; quad++) {
|
|
18299
18382
|
if (cullMasks[entry] & template.cullFaces[quad]) continue;
|
|
18383
|
+
blockIndices[indexOffset / 6] = indices[entry];
|
|
18300
18384
|
if (ambientMask) quadAmbientOcclusion(template.positions, template.normals, quad, ambientMask, cornerBrightness2);
|
|
18301
18385
|
const brightness = light ? lightBrightness(light[lightIndex + LIGHT_SAMPLE_OFFSETS[quadLightIndex(template.positions, template.normals, quad)]], ambientLight) : 1;
|
|
18302
18386
|
const start = vertex;
|
|
@@ -18329,6 +18413,7 @@ function buildSectionGeometry(input) {
|
|
|
18329
18413
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
18330
18414
|
const lightIndex = (y + 1) * 324 + (z + 1) * 18 + x + 1;
|
|
18331
18415
|
for (let quad = 0; quad < quads.sprites.length; quad++) {
|
|
18416
|
+
blockIndices[indexOffset / 6] = x + z * 16 + y * 256;
|
|
18332
18417
|
const rect = quads.sprites[quad] === 0 ? data.still : data.flow;
|
|
18333
18418
|
const brightness = light ? lightBrightness(fluidLightLevel(
|
|
18334
18419
|
light[lightIndex],
|
|
@@ -18359,11 +18444,11 @@ function buildSectionGeometry(input) {
|
|
|
18359
18444
|
indexOffset += 6;
|
|
18360
18445
|
}
|
|
18361
18446
|
}
|
|
18362
|
-
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices };
|
|
18447
|
+
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices, blockIndices };
|
|
18363
18448
|
});
|
|
18364
18449
|
}
|
|
18365
18450
|
function sectionGeometryTransferables(pages) {
|
|
18366
|
-
return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer]);
|
|
18451
|
+
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]);
|
|
18367
18452
|
}
|
|
18368
18453
|
|
|
18369
18454
|
// src/world/SectionWorker.ts
|
|
@@ -18522,6 +18607,12 @@ var SectionMesh = class _SectionMesh extends Group3 {
|
|
|
18522
18607
|
constructor() {
|
|
18523
18608
|
super(...arguments);
|
|
18524
18609
|
this.ownedMeshes = [];
|
|
18610
|
+
this.blockIndices = /* @__PURE__ */ new Map();
|
|
18611
|
+
}
|
|
18612
|
+
/** Returns the owning section cell for a triangle hit on this mesh's merged geometry. */
|
|
18613
|
+
getBlockIndex(hit) {
|
|
18614
|
+
if (hit.faceIndex === void 0 || hit.faceIndex === null) return void 0;
|
|
18615
|
+
return this.blockIndices.get(hit.object)?.[Math.floor(hit.faceIndex / 2)];
|
|
18525
18616
|
}
|
|
18526
18617
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
18527
18618
|
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
@@ -18562,8 +18653,9 @@ var SectionMesh = class _SectionMesh extends Group3 {
|
|
|
18562
18653
|
}
|
|
18563
18654
|
material.vertexColors = true;
|
|
18564
18655
|
const texture = material.uniforms?.map?.value ?? material.map;
|
|
18565
|
-
const mesh = new
|
|
18656
|
+
const mesh = new Mesh12(geometry, material);
|
|
18566
18657
|
section.add(mesh);
|
|
18658
|
+
section.blockIndices.set(mesh, page.blockIndices);
|
|
18567
18659
|
const unsubscribe = [];
|
|
18568
18660
|
for (const { atlas: id, x, y } of page.placements) {
|
|
18569
18661
|
const atlas = atlases[id];
|
|
@@ -18589,6 +18681,7 @@ var SectionMesh = class _SectionMesh extends Group3 {
|
|
|
18589
18681
|
mesh.material.dispose();
|
|
18590
18682
|
texture?.dispose();
|
|
18591
18683
|
}
|
|
18684
|
+
this.blockIndices.clear();
|
|
18592
18685
|
this.removeFromParent();
|
|
18593
18686
|
super.dispose();
|
|
18594
18687
|
}
|
|
@@ -18598,6 +18691,7 @@ var SectionMesh = class _SectionMesh extends Group3 {
|
|
|
18598
18691
|
init_FluidGeometry();
|
|
18599
18692
|
init_FluidQuads();
|
|
18600
18693
|
init_CubeFace();
|
|
18694
|
+
init_InstanceReference();
|
|
18601
18695
|
var WATER_TINT2 = new Color13(4159204).toArray();
|
|
18602
18696
|
var Chunk = class _Chunk {
|
|
18603
18697
|
constructor(scene, x, y, z, onBlocksChanged, sectionModels, neighborCell, biomeAt, onBiomesChanged, lightAt, onLightCleared, ambientLight = 0) {
|
|
@@ -18611,10 +18705,11 @@ var Chunk = class _Chunk {
|
|
|
18611
18705
|
this.ambientLight = ambientLight;
|
|
18612
18706
|
this.data = new ChunkData();
|
|
18613
18707
|
this.renderedBlocks = /* @__PURE__ */ new Map();
|
|
18708
|
+
this.objectBlocks = /* @__PURE__ */ new Set();
|
|
18614
18709
|
this.sectionBlocks = /* @__PURE__ */ new Map();
|
|
18615
18710
|
this.hiddenBlocks = /* @__PURE__ */ new Set();
|
|
18616
18711
|
this.fluidCells = new Uint8Array(4096);
|
|
18617
|
-
this.blockPosition = new
|
|
18712
|
+
this.blockPosition = new Vector320();
|
|
18618
18713
|
this.meshDirty = false;
|
|
18619
18714
|
this.meshGeneration = 0;
|
|
18620
18715
|
this.scene = scene;
|
|
@@ -18622,20 +18717,84 @@ var Chunk = class _Chunk {
|
|
|
18622
18717
|
this.y = y;
|
|
18623
18718
|
this.z = z;
|
|
18624
18719
|
}
|
|
18720
|
+
/** Finds the nearest owned block hit across sections, testing each shared mesh once. */
|
|
18721
|
+
static raycast(chunks, raycaster) {
|
|
18722
|
+
const roots = /* @__PURE__ */ new Map();
|
|
18723
|
+
const targets = /* @__PURE__ */ new Map();
|
|
18724
|
+
const meshes = (root, scene) => {
|
|
18725
|
+
const cached2 = roots.get(root);
|
|
18726
|
+
if (cached2) return cached2;
|
|
18727
|
+
const result = pickableMeshes(root, scene, raycaster);
|
|
18728
|
+
roots.set(root, result);
|
|
18729
|
+
return result;
|
|
18730
|
+
};
|
|
18731
|
+
const add = (root, owner, reference) => {
|
|
18732
|
+
for (const mesh of meshes(root, owner.chunk.scene)) {
|
|
18733
|
+
if (reference && reference.instanceable.getInstanceReference(mesh, reference.index) !== reference) continue;
|
|
18734
|
+
let entry = targets.get(mesh);
|
|
18735
|
+
if (!entry) targets.set(mesh, entry = { owners: /* @__PURE__ */ new Map() });
|
|
18736
|
+
entry.owners.set(reference?.index, owner);
|
|
18737
|
+
}
|
|
18738
|
+
};
|
|
18739
|
+
for (const chunk of chunks) {
|
|
18740
|
+
for (const index of chunk.objectBlocks) {
|
|
18741
|
+
const block = chunk.renderedBlocks.get(index).object;
|
|
18742
|
+
if (!block || !block.visible || chunk.hiddenBlocks.has(index)) continue;
|
|
18743
|
+
const owner = { chunk, index };
|
|
18744
|
+
for (const model of block.models) {
|
|
18745
|
+
if (isInstanceReference(model)) {
|
|
18746
|
+
if (model.instanceable.isInstanceActive(model.index, model)) add(model.instanceable, owner, model);
|
|
18747
|
+
} else {
|
|
18748
|
+
add(model, owner);
|
|
18749
|
+
}
|
|
18750
|
+
}
|
|
18751
|
+
for (const entity of block.blockEntities) add(entity, owner);
|
|
18752
|
+
}
|
|
18753
|
+
if (chunk.sectionMesh) {
|
|
18754
|
+
for (const mesh of meshes(chunk.sectionMesh, chunk.scene)) {
|
|
18755
|
+
targets.set(mesh, { owners: /* @__PURE__ */ new Map(), section: { chunk, mesh: chunk.sectionMesh } });
|
|
18756
|
+
}
|
|
18757
|
+
}
|
|
18758
|
+
}
|
|
18759
|
+
for (const hit of visibleHits(raycaster, [...targets.keys()])) {
|
|
18760
|
+
const mesh = hit.object;
|
|
18761
|
+
const entry = targets.get(mesh);
|
|
18762
|
+
let owner = entry.owners.get(hit.instanceId) ?? entry.owners.get(void 0);
|
|
18763
|
+
if (entry.section) {
|
|
18764
|
+
const index = entry.section.mesh.getBlockIndex(hit);
|
|
18765
|
+
if (index !== void 0) owner = { chunk: entry.section.chunk, index };
|
|
18766
|
+
}
|
|
18767
|
+
if (!owner || owner.chunk.hiddenBlocks.has(owner.index)) continue;
|
|
18768
|
+
const info = owner.chunk.renderedBlocks.get(owner.index);
|
|
18769
|
+
if (!info) continue;
|
|
18770
|
+
return {
|
|
18771
|
+
position: new Vector320(
|
|
18772
|
+
owner.chunk.x * 16 + owner.index % 16,
|
|
18773
|
+
owner.chunk.y * 16 + Math.floor(owner.index / 256),
|
|
18774
|
+
owner.chunk.z * 16 + Math.floor(owner.index / 16) % 16
|
|
18775
|
+
),
|
|
18776
|
+
block: info.block,
|
|
18777
|
+
point: hit.point.clone(),
|
|
18778
|
+
normal: hitNormal(hit),
|
|
18779
|
+
distance: hit.distance
|
|
18780
|
+
};
|
|
18781
|
+
}
|
|
18782
|
+
return void 0;
|
|
18783
|
+
}
|
|
18625
18784
|
getBlockAt(posOrX, y, z) {
|
|
18626
18785
|
if (typeof posOrX == "number") {
|
|
18627
|
-
return this.getBlockAt(new
|
|
18786
|
+
return this.getBlockAt(new Vector320(posOrX, y, z));
|
|
18628
18787
|
}
|
|
18629
18788
|
if (isTripleArray(posOrX)) {
|
|
18630
|
-
return this.getBlockAt(new
|
|
18789
|
+
return this.getBlockAt(new Vector320(posOrX[0], posOrX[1], posOrX[2]));
|
|
18631
18790
|
}
|
|
18632
18791
|
const pos = this.blockPosition.set(posOrX.x - this.x * 16, posOrX.y - this.y * 16, posOrX.z - this.z * 16);
|
|
18633
18792
|
const index = _Chunk.chunkPosToBlockIndex(pos);
|
|
18634
18793
|
return this.renderedBlocks.get(index);
|
|
18635
18794
|
}
|
|
18636
18795
|
getBiomeAt(posOrX, y, z) {
|
|
18637
|
-
if (typeof posOrX === "number") return this.getBiomeAt(new
|
|
18638
|
-
if (isTripleArray(posOrX)) return this.getBiomeAt(new
|
|
18796
|
+
if (typeof posOrX === "number") return this.getBiomeAt(new Vector320(posOrX, y, z));
|
|
18797
|
+
if (isTripleArray(posOrX)) return this.getBiomeAt(new Vector320(...posOrX));
|
|
18639
18798
|
const pos = this.worldPosToChunkPos(posOrX);
|
|
18640
18799
|
_Chunk.chunkPosToBlockIndex(pos);
|
|
18641
18800
|
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];
|
|
@@ -18678,17 +18837,17 @@ var Chunk = class _Chunk {
|
|
|
18678
18837
|
this.hiddenBlocks.add(index);
|
|
18679
18838
|
this.renderedBlocks.get(index)?.object?.setVisible(false);
|
|
18680
18839
|
}
|
|
18681
|
-
const positions = blocks.map(({ index }) => new
|
|
18840
|
+
const positions = blocks.map(({ index }) => new Vector320(...this.positionAt(index)));
|
|
18682
18841
|
if (this.onBlocksChanged) await this.onBlocksChanged(positions);
|
|
18683
18842
|
else await this.rebuildSectionMesh();
|
|
18684
18843
|
}
|
|
18685
18844
|
}
|
|
18686
18845
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
18687
18846
|
if (typeof posOrX == "number") {
|
|
18688
|
-
return this.setBlockAt(new
|
|
18847
|
+
return this.setBlockAt(new Vector320(posOrX, yOrBlock, z), block);
|
|
18689
18848
|
}
|
|
18690
18849
|
if (isTripleArray(posOrX)) {
|
|
18691
|
-
return this.setBlockAt(new
|
|
18850
|
+
return this.setBlockAt(new Vector320(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
18692
18851
|
}
|
|
18693
18852
|
const worldPos = posOrX;
|
|
18694
18853
|
const pos = this.worldPosToChunkPos(worldPos);
|
|
@@ -18742,7 +18901,8 @@ var Chunk = class _Chunk {
|
|
|
18742
18901
|
if (this.fluidCells[index]) this.meshDirty = true;
|
|
18743
18902
|
this.fluidCells[index] = 0;
|
|
18744
18903
|
this.renderedBlocks.delete(index);
|
|
18745
|
-
|
|
18904
|
+
this.objectBlocks.delete(index);
|
|
18905
|
+
const worldPos = new Vector320(
|
|
18746
18906
|
this.x * 16 + index % 16,
|
|
18747
18907
|
this.y * 16 + Math.floor(index / 256),
|
|
18748
18908
|
this.z * 16 + Math.floor(index / 16) % 16
|
|
@@ -18784,6 +18944,7 @@ var Chunk = class _Chunk {
|
|
|
18784
18944
|
this.renderedBlocks.set(index, { get block() {
|
|
18785
18945
|
return readBlock();
|
|
18786
18946
|
}, object: object4 });
|
|
18947
|
+
if (object4) this.objectBlocks.add(index);
|
|
18787
18948
|
} catch (error) {
|
|
18788
18949
|
this.data.assign(index, 0);
|
|
18789
18950
|
this.fluidCells[index] = 0;
|
|
@@ -18802,6 +18963,7 @@ var Chunk = class _Chunk {
|
|
|
18802
18963
|
this.fluidCells.fill(0);
|
|
18803
18964
|
this.waterTints = void 0;
|
|
18804
18965
|
this.renderedBlocks.clear();
|
|
18966
|
+
this.objectBlocks.clear();
|
|
18805
18967
|
this.hiddenBlocks.clear();
|
|
18806
18968
|
this.meshDirty = true;
|
|
18807
18969
|
this.data.copyFrom(data);
|
|
@@ -18851,6 +19013,7 @@ var Chunk = class _Chunk {
|
|
|
18851
19013
|
this.renderedBlocks.set(index, { get block() {
|
|
18852
19014
|
return readBlock();
|
|
18853
19015
|
}, object: void 0 });
|
|
19016
|
+
this.objectBlocks.delete(index);
|
|
18854
19017
|
} catch (error) {
|
|
18855
19018
|
this.data.assign(index, 0);
|
|
18856
19019
|
this.fluidCells[index] = 0;
|
|
@@ -18870,16 +19033,18 @@ var Chunk = class _Chunk {
|
|
|
18870
19033
|
biome,
|
|
18871
19034
|
biomePosition: this.biomePosition(index, blockState3, this.data.stateAt(this.data.idAt(index)))
|
|
18872
19035
|
});
|
|
18873
|
-
object4.setPosition(new
|
|
19036
|
+
object4.setPosition(new Vector320(
|
|
18874
19037
|
this.x * 256 + index % 16 * 16,
|
|
18875
19038
|
this.y * 256 + Math.floor(index / 256) * 16,
|
|
18876
19039
|
this.z * 256 + Math.floor(index / 16) % 16 * 16
|
|
18877
19040
|
));
|
|
18878
19041
|
this.renderedBlocks.get(index).object = object4;
|
|
19042
|
+
this.objectBlocks.add(index);
|
|
18879
19043
|
} catch (error) {
|
|
18880
19044
|
this.data.assign(index, 0);
|
|
18881
19045
|
this.fluidCells[index] = 0;
|
|
18882
19046
|
this.renderedBlocks.delete(index);
|
|
19047
|
+
this.objectBlocks.delete(index);
|
|
18883
19048
|
object4?.removeFromScene();
|
|
18884
19049
|
if (!failed) failure = error;
|
|
18885
19050
|
failed = true;
|
|
@@ -19131,7 +19296,7 @@ var Chunk = class _Chunk {
|
|
|
19131
19296
|
/** Removes stored blocks and render objects. Set `notify` to false to skip the owning world's update. */
|
|
19132
19297
|
async clear(notify = true) {
|
|
19133
19298
|
const positions = notify && this.onBlocksChanged ? [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
|
|
19134
|
-
new
|
|
19299
|
+
new Vector320(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
|
|
19135
19300
|
)) : [];
|
|
19136
19301
|
for (const info of this.renderedBlocks.values()) info.object?.removeFromScene();
|
|
19137
19302
|
this.sectionBlocks.clear();
|
|
@@ -19140,6 +19305,7 @@ var Chunk = class _Chunk {
|
|
|
19140
19305
|
this.sectionMesh = void 0;
|
|
19141
19306
|
this.meshDirty = false;
|
|
19142
19307
|
this.renderedBlocks.clear();
|
|
19308
|
+
this.objectBlocks.clear();
|
|
19143
19309
|
this.hiddenBlocks.clear();
|
|
19144
19310
|
this.fluidCells.fill(0);
|
|
19145
19311
|
this.waterTints = void 0;
|
|
@@ -19166,14 +19332,14 @@ var Chunk = class _Chunk {
|
|
|
19166
19332
|
return pos.y * 16 * 16 + pos.z * 16 + pos.x;
|
|
19167
19333
|
}
|
|
19168
19334
|
worldPosToChunkPos(pos) {
|
|
19169
|
-
return new
|
|
19335
|
+
return new Vector320(
|
|
19170
19336
|
pos.x - this.x * 16,
|
|
19171
19337
|
pos.y - this.y * 16,
|
|
19172
19338
|
pos.z - this.z * 16
|
|
19173
19339
|
);
|
|
19174
19340
|
}
|
|
19175
19341
|
chunkPosToWorldPos(pos) {
|
|
19176
|
-
return new
|
|
19342
|
+
return new Vector320(
|
|
19177
19343
|
this.x * 16 + pos.x,
|
|
19178
19344
|
this.y * 16 + pos.y,
|
|
19179
19345
|
this.z * 16 + pos.z
|