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/browser/index.mjs
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
17678
|
+
return this.getBlockAt(new Vector319(posOrX, y, z));
|
|
17597
17679
|
}
|
|
17598
17680
|
if (isTripleArray(posOrX)) {
|
|
17599
|
-
return this.getBlockAt(new
|
|
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
|
|
17606
|
-
if (isTripleArray(posOrX)) return this.getBiomeAt(new
|
|
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
|
|
17614
|
-
if (isTripleArray(posOrX)) return this.getLightAt(new
|
|
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
|
|
17714
|
+
return this.setBlockAt(new Vector319(posOrX, yOrBlock, z), block);
|
|
17633
17715
|
}
|
|
17634
17716
|
if (isTripleArray(posOrX)) {
|
|
17635
|
-
return this.setBlockAt(new
|
|
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
|
|
17728
|
+
return this.setBlockVisibleAt(new Vector319(posOrX, yOrVisible, z), visible);
|
|
17647
17729
|
}
|
|
17648
17730
|
if (isTripleArray(posOrX)) {
|
|
17649
|
-
return this.setBlockVisibleAt(new
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
18749
|
+
return this.getBlockAt(new Vector320(posOrX, y, z));
|
|
18591
18750
|
}
|
|
18592
18751
|
if (isTripleArray(posOrX)) {
|
|
18593
|
-
return this.getBlockAt(new
|
|
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
|
|
18601
|
-
if (isTripleArray(posOrX)) return this.getBiomeAt(new
|
|
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
|
|
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
|
|
18810
|
+
return this.setBlockAt(new Vector320(posOrX, yOrBlock, z), block);
|
|
18652
18811
|
}
|
|
18653
18812
|
if (isTripleArray(posOrX)) {
|
|
18654
|
-
return this.setBlockAt(new
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|