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.js
CHANGED
|
@@ -12633,6 +12633,10 @@ var BlockObject = class _BlockObject extends SceneObject {
|
|
|
12633
12633
|
get blockEntities() {
|
|
12634
12634
|
return this._entities;
|
|
12635
12635
|
}
|
|
12636
|
+
/** Model placements drawn for this block, including its fluid surface. */
|
|
12637
|
+
get models() {
|
|
12638
|
+
return this._models;
|
|
12639
|
+
}
|
|
12636
12640
|
/** Sets visibility for this block's model instances and block entities. */
|
|
12637
12641
|
setVisible(visible) {
|
|
12638
12642
|
this.visible = visible;
|
|
@@ -17386,12 +17390,12 @@ var AnvilWorldSource = class {
|
|
|
17386
17390
|
};
|
|
17387
17391
|
|
|
17388
17392
|
// src/world/Chunk.ts
|
|
17389
|
-
var
|
|
17393
|
+
var import_three47 = require("three");
|
|
17390
17394
|
init_BlockStates();
|
|
17391
17395
|
init_AssetKey();
|
|
17392
17396
|
|
|
17393
17397
|
// src/world/MineRenderWorld.ts
|
|
17394
|
-
var
|
|
17398
|
+
var import_three45 = require("three");
|
|
17395
17399
|
init_Model();
|
|
17396
17400
|
init_util();
|
|
17397
17401
|
init_AssetKey();
|
|
@@ -17656,11 +17660,74 @@ function resolveSavedEntity(entity) {
|
|
|
17656
17660
|
|
|
17657
17661
|
// src/world/_entities/WorldEntities.ts
|
|
17658
17662
|
init_BannerPatterns();
|
|
17663
|
+
var import_three44 = require("three");
|
|
17664
|
+
|
|
17665
|
+
// src/world/_picking/Picking.ts
|
|
17666
|
+
var import_three42 = require("three");
|
|
17667
|
+
init_three();
|
|
17668
|
+
function pickableMeshes(root, scene, raycaster) {
|
|
17669
|
+
const result = [];
|
|
17670
|
+
let attached = false;
|
|
17671
|
+
for (let parent = root; parent; parent = parent.parent) {
|
|
17672
|
+
if (!parent.visible) return result;
|
|
17673
|
+
if (parent === scene) attached = true;
|
|
17674
|
+
}
|
|
17675
|
+
if (!attached) return result;
|
|
17676
|
+
root.updateWorldMatrix(true, true);
|
|
17677
|
+
root.traverseVisible((object4) => {
|
|
17678
|
+
if (isMesh(object4) && raycaster.layers.test(object4.layers)) result.push(object4);
|
|
17679
|
+
});
|
|
17680
|
+
return result;
|
|
17681
|
+
}
|
|
17682
|
+
function visibleHits(raycaster, meshes) {
|
|
17683
|
+
return raycaster.intersectObjects(meshes, false).filter((hit) => {
|
|
17684
|
+
if (!hit.face) return false;
|
|
17685
|
+
const mesh = hit.object;
|
|
17686
|
+
const material = Array.isArray(mesh.material) ? mesh.material[hit.face.materialIndex] : mesh.material;
|
|
17687
|
+
return material?.visible;
|
|
17688
|
+
});
|
|
17689
|
+
}
|
|
17690
|
+
function hitNormal(hit) {
|
|
17691
|
+
const mesh = hit.object;
|
|
17692
|
+
const matrix = mesh.matrixWorld.clone();
|
|
17693
|
+
if (isInstancedMesh(mesh) && hit.instanceId !== void 0) {
|
|
17694
|
+
const instance = new import_three42.Matrix4();
|
|
17695
|
+
mesh.getMatrixAt(hit.instanceId, instance);
|
|
17696
|
+
matrix.multiply(instance);
|
|
17697
|
+
}
|
|
17698
|
+
return hit.face.normal.clone().applyNormalMatrix(new import_three42.Matrix3().getNormalMatrix(matrix));
|
|
17699
|
+
}
|
|
17700
|
+
|
|
17701
|
+
// src/world/_entities/WorldEntities.ts
|
|
17659
17702
|
var WorldEntities = class {
|
|
17660
17703
|
constructor(scene) {
|
|
17661
17704
|
this.scene = scene;
|
|
17662
17705
|
this.columns = /* @__PURE__ */ new Map();
|
|
17663
17706
|
}
|
|
17707
|
+
/** Finds the nearest visible triangle belonging to an entity owned by this world. */
|
|
17708
|
+
raycast(raycaster) {
|
|
17709
|
+
const owners = /* @__PURE__ */ new Map();
|
|
17710
|
+
for (const column of this.columns.values()) {
|
|
17711
|
+
for (const [object4, placement] of column) {
|
|
17712
|
+
for (const mesh of pickableMeshes(object4, this.scene, raycaster)) {
|
|
17713
|
+
owners.set(mesh, { object: object4, ...placement });
|
|
17714
|
+
}
|
|
17715
|
+
}
|
|
17716
|
+
}
|
|
17717
|
+
for (const hit of visibleHits(raycaster, [...owners.keys()])) {
|
|
17718
|
+
const mesh = hit.object;
|
|
17719
|
+
const owner = owners.get(mesh);
|
|
17720
|
+
return {
|
|
17721
|
+
type: owner.type,
|
|
17722
|
+
position: new import_three44.Vector3(...owner.position),
|
|
17723
|
+
object: owner.object,
|
|
17724
|
+
point: hit.point.clone(),
|
|
17725
|
+
normal: hitNormal(hit),
|
|
17726
|
+
distance: hit.distance
|
|
17727
|
+
};
|
|
17728
|
+
}
|
|
17729
|
+
return void 0;
|
|
17730
|
+
}
|
|
17664
17731
|
/** Captures column ownership before asynchronous block or asset loading starts. */
|
|
17665
17732
|
prepare(entities = [], column) {
|
|
17666
17733
|
const placements = entities.flatMap((entity) => {
|
|
@@ -17669,7 +17736,7 @@ var WorldEntities = class {
|
|
|
17669
17736
|
const position = [...entity.position];
|
|
17670
17737
|
const key = column?.join(",") ?? `${Math.floor(position[0] / 16)},${Math.floor(position[2] / 16)}`;
|
|
17671
17738
|
let owner = this.columns.get(key);
|
|
17672
|
-
if (!owner) this.columns.set(key, owner = /* @__PURE__ */ new
|
|
17739
|
+
if (!owner) this.columns.set(key, owner = /* @__PURE__ */ new Map());
|
|
17673
17740
|
return [{ ...resolved, position, column: key, owner }];
|
|
17674
17741
|
});
|
|
17675
17742
|
return async () => {
|
|
@@ -17695,7 +17762,7 @@ var WorldEntities = class {
|
|
|
17695
17762
|
object4.rotation.y = placement.yaw;
|
|
17696
17763
|
await object4.init();
|
|
17697
17764
|
if (!current()) return;
|
|
17698
|
-
placement.owner.
|
|
17765
|
+
placement.owner.set(object4, { type: placement.key.toNamespacedString(), position: placement.position });
|
|
17699
17766
|
this.scene.add(object4);
|
|
17700
17767
|
} catch (error) {
|
|
17701
17768
|
console.warn(`Could not draw saved entity ${placement.key.toNamespacedString()}, skipping it`, error);
|
|
@@ -17710,7 +17777,7 @@ var WorldEntities = class {
|
|
|
17710
17777
|
const objects = this.columns.get(key);
|
|
17711
17778
|
this.columns.delete(key);
|
|
17712
17779
|
if (!objects) return;
|
|
17713
|
-
for (const object4 of objects) {
|
|
17780
|
+
for (const object4 of objects.keys()) {
|
|
17714
17781
|
object4.removeFromScene();
|
|
17715
17782
|
object4.dispose();
|
|
17716
17783
|
}
|
|
@@ -17771,6 +17838,21 @@ var MineRenderWorld = class {
|
|
|
17771
17838
|
if (options.sectionMeshing) this.sectionModels = new SectionModels(options.maxAtlasSize);
|
|
17772
17839
|
if (options.renderEntities) this.entities = new WorldEntities(scene);
|
|
17773
17840
|
}
|
|
17841
|
+
/**
|
|
17842
|
+
* Returns the nearest visible block geometry hit, respecting the raycaster's layers and near/far range.
|
|
17843
|
+
* Includes fluids and block entities; texture alpha does not change triangle intersections.
|
|
17844
|
+
*/
|
|
17845
|
+
raycast(raycaster) {
|
|
17846
|
+
return Chunk.raycast(this._chunks.values(), raycaster);
|
|
17847
|
+
}
|
|
17848
|
+
/**
|
|
17849
|
+
* Returns the nearest visible mob geometry hit when renderEntities is enabled.
|
|
17850
|
+
* Respects layers and near/far; compare its distance with raycast() to account for blocks.
|
|
17851
|
+
* Texture alpha does not change triangle intersections.
|
|
17852
|
+
*/
|
|
17853
|
+
raycastEntities(raycaster) {
|
|
17854
|
+
return this.entities?.raycast(raycaster);
|
|
17855
|
+
}
|
|
17774
17856
|
/** Whether neighboring opaque cubes shade block-face corners. Defaults to false. */
|
|
17775
17857
|
get ambientOcclusion() {
|
|
17776
17858
|
return this._ambientOcclusion;
|
|
@@ -17791,25 +17873,25 @@ var MineRenderWorld = class {
|
|
|
17791
17873
|
}
|
|
17792
17874
|
getBlockAt(posOrX, y, z) {
|
|
17793
17875
|
if (typeof posOrX == "number") {
|
|
17794
|
-
return this.getBlockAt(new
|
|
17876
|
+
return this.getBlockAt(new import_three45.Vector3(posOrX, y, z));
|
|
17795
17877
|
}
|
|
17796
17878
|
if (isTripleArray(posOrX)) {
|
|
17797
|
-
return this.getBlockAt(new
|
|
17879
|
+
return this.getBlockAt(new import_three45.Vector3(posOrX[0], posOrX[1], posOrX[2]));
|
|
17798
17880
|
}
|
|
17799
17881
|
this.validatePosBounds(posOrX);
|
|
17800
17882
|
return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
|
|
17801
17883
|
}
|
|
17802
17884
|
getBiomeAt(posOrX, y, z) {
|
|
17803
|
-
if (typeof posOrX === "number") return this.getBiomeAt(new
|
|
17804
|
-
if (isTripleArray(posOrX)) return this.getBiomeAt(new
|
|
17885
|
+
if (typeof posOrX === "number") return this.getBiomeAt(new import_three45.Vector3(posOrX, y, z));
|
|
17886
|
+
if (isTripleArray(posOrX)) return this.getBiomeAt(new import_three45.Vector3(...posOrX));
|
|
17805
17887
|
this.validatePosBounds(posOrX);
|
|
17806
17888
|
const cx = Math.floor(posOrX.x / 16), cy = Math.floor(posOrX.y / 16), cz = Math.floor(posOrX.z / 16);
|
|
17807
17889
|
const lx = posOrX.x - cx * 16, ly = posOrX.y - cy * 16, lz = posOrX.z - cz * 16;
|
|
17808
17890
|
return this.biomes.get(`${cx}_${cz}`)?.get(cy)?.[Math.floor(lx / 4) + Math.floor(lz / 4) * 4 + Math.floor(ly / 4) * 16];
|
|
17809
17891
|
}
|
|
17810
17892
|
getLightAt(posOrX, y, z) {
|
|
17811
|
-
if (typeof posOrX === "number") return this.getLightAt(new
|
|
17812
|
-
if (isTripleArray(posOrX)) return this.getLightAt(new
|
|
17893
|
+
if (typeof posOrX === "number") return this.getLightAt(new import_three45.Vector3(posOrX, y, z));
|
|
17894
|
+
if (isTripleArray(posOrX)) return this.getLightAt(new import_three45.Vector3(...posOrX));
|
|
17813
17895
|
this.validatePosBounds(posOrX);
|
|
17814
17896
|
const { x, y: py, z: pz } = posOrX;
|
|
17815
17897
|
const cx = Math.floor(x / 16), cy = Math.floor(py / 16), cz = Math.floor(pz / 16);
|
|
@@ -17827,10 +17909,10 @@ var MineRenderWorld = class {
|
|
|
17827
17909
|
}
|
|
17828
17910
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
17829
17911
|
if (typeof posOrX == "number") {
|
|
17830
|
-
return this.setBlockAt(new
|
|
17912
|
+
return this.setBlockAt(new import_three45.Vector3(posOrX, yOrBlock, z), block);
|
|
17831
17913
|
}
|
|
17832
17914
|
if (isTripleArray(posOrX)) {
|
|
17833
|
-
return this.setBlockAt(new
|
|
17915
|
+
return this.setBlockAt(new import_three45.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
17834
17916
|
}
|
|
17835
17917
|
return this.placeBlock(posOrX, yOrBlock);
|
|
17836
17918
|
}
|
|
@@ -17841,10 +17923,10 @@ var MineRenderWorld = class {
|
|
|
17841
17923
|
}
|
|
17842
17924
|
async setBlockVisibleAt(posOrX, yOrVisible, z, visible) {
|
|
17843
17925
|
if (typeof posOrX === "number") {
|
|
17844
|
-
return this.setBlockVisibleAt(new
|
|
17926
|
+
return this.setBlockVisibleAt(new import_three45.Vector3(posOrX, yOrVisible, z), visible);
|
|
17845
17927
|
}
|
|
17846
17928
|
if (isTripleArray(posOrX)) {
|
|
17847
|
-
return this.setBlockVisibleAt(new
|
|
17929
|
+
return this.setBlockVisibleAt(new import_three45.Vector3(...posOrX), yOrVisible);
|
|
17848
17930
|
}
|
|
17849
17931
|
this.validatePosBounds(posOrX);
|
|
17850
17932
|
await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible);
|
|
@@ -17870,7 +17952,7 @@ var MineRenderWorld = class {
|
|
|
17870
17952
|
const collect = async (positions2) => {
|
|
17871
17953
|
for (const pos of positions2) changes.set(pos.toArray().join(","), pos);
|
|
17872
17954
|
};
|
|
17873
|
-
const place = (block) => this.placeBlock(new
|
|
17955
|
+
const place = (block) => this.placeBlock(new import_three45.Vector3(...block.position), block, collect);
|
|
17874
17956
|
const keys = /* @__PURE__ */ new Map();
|
|
17875
17957
|
const types = /* @__PURE__ */ new Set();
|
|
17876
17958
|
for (const block of multiblock.blocks) {
|
|
@@ -17886,7 +17968,7 @@ var MineRenderWorld = class {
|
|
|
17886
17968
|
}
|
|
17887
17969
|
if (!executor) {
|
|
17888
17970
|
const groups2 = /* @__PURE__ */ new Map();
|
|
17889
|
-
const position = new
|
|
17971
|
+
const position = new import_three45.Vector3();
|
|
17890
17972
|
for (const block of multiblock.blocks) {
|
|
17891
17973
|
const [x, y, z] = block.position;
|
|
17892
17974
|
this.validatePosBounds(position.set(x, y, z));
|
|
@@ -17926,7 +18008,7 @@ var MineRenderWorld = class {
|
|
|
17926
18008
|
try {
|
|
17927
18009
|
positions = await chunk.placeBlocks(blocks);
|
|
17928
18010
|
} finally {
|
|
17929
|
-
positions ??= blocks.map(({ index }) => new
|
|
18011
|
+
positions ??= blocks.map(({ index }) => new import_three45.Vector3(
|
|
17930
18012
|
chunk.x * 16 + index % 16,
|
|
17931
18013
|
chunk.y * 16 + Math.floor(index / 256),
|
|
17932
18014
|
chunk.z * 16 + Math.floor(index / 16) % 16
|
|
@@ -17978,7 +18060,7 @@ var MineRenderWorld = class {
|
|
|
17978
18060
|
}
|
|
17979
18061
|
for (const section of chunk.sections) {
|
|
17980
18062
|
if (section.biomes) {
|
|
17981
|
-
const position = new
|
|
18063
|
+
const position = new import_three45.Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);
|
|
17982
18064
|
this.validatePosBounds(position);
|
|
17983
18065
|
const copy = [...section.biomes];
|
|
17984
18066
|
if (copy.length !== 64 || !copy.every((id) => typeof id === "string" && id.length > 0)) {
|
|
@@ -17994,7 +18076,7 @@ var MineRenderWorld = class {
|
|
|
17994
18076
|
for (const section of chunk.sections) {
|
|
17995
18077
|
if (!executor) {
|
|
17996
18078
|
if (!occupiedSections.has(section.y)) continue;
|
|
17997
|
-
const position = new
|
|
18079
|
+
const position = new import_three45.Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);
|
|
17998
18080
|
this.validatePosBounds(position);
|
|
17999
18081
|
const target = this.getOrCreateChunkAt(position);
|
|
18000
18082
|
try {
|
|
@@ -18098,7 +18180,7 @@ var MineRenderWorld = class {
|
|
|
18098
18180
|
this.sectionModels?.clear();
|
|
18099
18181
|
}
|
|
18100
18182
|
updateCulling(positions) {
|
|
18101
|
-
const neighbor = new
|
|
18183
|
+
const neighbor = new import_three45.Vector3();
|
|
18102
18184
|
for (const pos of positions) {
|
|
18103
18185
|
const cx = Math.floor(pos.x / 16), cy = Math.floor(pos.y / 16), cz = Math.floor(pos.z / 16);
|
|
18104
18186
|
const chunk = this._chunks.get(`${cx}_${cy}_${cz}`);
|
|
@@ -18229,7 +18311,7 @@ var MineRenderWorld = class {
|
|
|
18229
18311
|
}
|
|
18230
18312
|
/** Converts block coordinates to scene units by multiplying each component by 16. */
|
|
18231
18313
|
static worldToScenePosition(pos) {
|
|
18232
|
-
return new
|
|
18314
|
+
return new import_three45.Vector3(
|
|
18233
18315
|
pos.x * 16,
|
|
18234
18316
|
pos.y * 16,
|
|
18235
18317
|
pos.z * 16
|
|
@@ -18237,7 +18319,7 @@ var MineRenderWorld = class {
|
|
|
18237
18319
|
}
|
|
18238
18320
|
/** Converts scene units to block coordinates without rounding to an integer block. */
|
|
18239
18321
|
static sceneToWorldPosition(pos) {
|
|
18240
|
-
return new
|
|
18322
|
+
return new import_three45.Vector3(
|
|
18241
18323
|
pos.x / 16,
|
|
18242
18324
|
pos.y / 16,
|
|
18243
18325
|
pos.z / 16
|
|
@@ -18260,7 +18342,7 @@ var MineRenderWorld = class {
|
|
|
18260
18342
|
init_Model();
|
|
18261
18343
|
|
|
18262
18344
|
// src/world/SectionMesh.ts
|
|
18263
|
-
var
|
|
18345
|
+
var import_three46 = require("three");
|
|
18264
18346
|
init_CanvasCompat();
|
|
18265
18347
|
init_Materials();
|
|
18266
18348
|
|
|
@@ -18445,6 +18527,7 @@ function buildSectionGeometry(input) {
|
|
|
18445
18527
|
const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);
|
|
18446
18528
|
const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);
|
|
18447
18529
|
const outputIndices = new Uint32Array(faces * 6);
|
|
18530
|
+
const blockIndices = new Uint16Array(faces);
|
|
18448
18531
|
let vertex = 0, indexOffset = 0;
|
|
18449
18532
|
for (const entry of page.entries) {
|
|
18450
18533
|
const template = templateData[templates[entry]];
|
|
@@ -18459,6 +18542,7 @@ function buildSectionGeometry(input) {
|
|
|
18459
18542
|
const ambientMask = ambientOcclusion && template.ambientOcclusion !== false ? sectionAmbientOcclusionMask(ambientOcclusion, lightIndex) : 0;
|
|
18460
18543
|
for (let quad = 0; quad < template.quads; quad++) {
|
|
18461
18544
|
if (cullMasks[entry] & template.cullFaces[quad]) continue;
|
|
18545
|
+
blockIndices[indexOffset / 6] = indices[entry];
|
|
18462
18546
|
if (ambientMask) quadAmbientOcclusion(template.positions, template.normals, quad, ambientMask, cornerBrightness2);
|
|
18463
18547
|
const brightness = light ? lightBrightness(light[lightIndex + LIGHT_SAMPLE_OFFSETS[quadLightIndex(template.positions, template.normals, quad)]], ambientLight) : 1;
|
|
18464
18548
|
const start = vertex;
|
|
@@ -18491,6 +18575,7 @@ function buildSectionGeometry(input) {
|
|
|
18491
18575
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
18492
18576
|
const lightIndex = (y + 1) * 324 + (z + 1) * 18 + x + 1;
|
|
18493
18577
|
for (let quad = 0; quad < quads.sprites.length; quad++) {
|
|
18578
|
+
blockIndices[indexOffset / 6] = x + z * 16 + y * 256;
|
|
18494
18579
|
const rect = quads.sprites[quad] === 0 ? data.still : data.flow;
|
|
18495
18580
|
const brightness = light ? lightBrightness(fluidLightLevel(
|
|
18496
18581
|
light[lightIndex],
|
|
@@ -18521,11 +18606,11 @@ function buildSectionGeometry(input) {
|
|
|
18521
18606
|
indexOffset += 6;
|
|
18522
18607
|
}
|
|
18523
18608
|
}
|
|
18524
|
-
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices };
|
|
18609
|
+
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices, blockIndices };
|
|
18525
18610
|
});
|
|
18526
18611
|
}
|
|
18527
18612
|
function sectionGeometryTransferables(pages) {
|
|
18528
|
-
return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer]);
|
|
18613
|
+
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]);
|
|
18529
18614
|
}
|
|
18530
18615
|
|
|
18531
18616
|
// src/world/SectionWorker.ts
|
|
@@ -18583,7 +18668,7 @@ var SectionWorker = class _SectionWorker {
|
|
|
18583
18668
|
|
|
18584
18669
|
// src/world/SectionMesh.ts
|
|
18585
18670
|
var templateCache = /* @__PURE__ */ new WeakMap();
|
|
18586
|
-
var WATER_TINT = new
|
|
18671
|
+
var WATER_TINT = new import_three46.Color(4159204).toArray();
|
|
18587
18672
|
function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
18588
18673
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
18589
18674
|
const atlases = [];
|
|
@@ -18680,10 +18765,16 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
18680
18765
|
}
|
|
18681
18766
|
return { input, atlases };
|
|
18682
18767
|
}
|
|
18683
|
-
var SectionMesh = class _SectionMesh extends
|
|
18768
|
+
var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
18684
18769
|
constructor() {
|
|
18685
18770
|
super(...arguments);
|
|
18686
18771
|
this.ownedMeshes = [];
|
|
18772
|
+
this.blockIndices = /* @__PURE__ */ new Map();
|
|
18773
|
+
}
|
|
18774
|
+
/** Returns the owning section cell for a triangle hit on this mesh's merged geometry. */
|
|
18775
|
+
getBlockIndex(hit) {
|
|
18776
|
+
if (hit.faceIndex === void 0 || hit.faceIndex === null) return void 0;
|
|
18777
|
+
return this.blockIndices.get(hit.object)?.[Math.floor(hit.faceIndex / 2)];
|
|
18687
18778
|
}
|
|
18688
18779
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
18689
18780
|
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
@@ -18705,27 +18796,28 @@ var SectionMesh = class _SectionMesh extends import_three43.Group {
|
|
|
18705
18796
|
for (const { atlas, x, y } of page.placements) {
|
|
18706
18797
|
context.drawImage(atlases[atlas].image.canvas, x, y);
|
|
18707
18798
|
}
|
|
18708
|
-
const geometry = new
|
|
18709
|
-
geometry.setAttribute("position", new
|
|
18710
|
-
geometry.setAttribute("normal", new
|
|
18711
|
-
geometry.setAttribute("uv", new
|
|
18712
|
-
geometry.setAttribute("uvBounds", new
|
|
18713
|
-
geometry.setAttribute("color", new
|
|
18714
|
-
geometry.setIndex(new
|
|
18799
|
+
const geometry = new import_three46.BufferGeometry();
|
|
18800
|
+
geometry.setAttribute("position", new import_three46.Float32BufferAttribute(page.positions.buffer, 3));
|
|
18801
|
+
geometry.setAttribute("normal", new import_three46.Float32BufferAttribute(page.normals.buffer, 3));
|
|
18802
|
+
geometry.setAttribute("uv", new import_three46.Float32BufferAttribute(page.uvs.buffer, 2));
|
|
18803
|
+
geometry.setAttribute("uvBounds", new import_three46.Float32BufferAttribute(page.uvBounds.buffer, 4));
|
|
18804
|
+
geometry.setAttribute("color", new import_three46.Float32BufferAttribute(page.colors.buffer, 3));
|
|
18805
|
+
geometry.setIndex(new import_three46.Uint32BufferAttribute(page.indices.buffer, 1));
|
|
18715
18806
|
geometry.computeBoundingBox();
|
|
18716
18807
|
geometry.computeBoundingSphere();
|
|
18717
18808
|
const transparent = page.layer === 2 ? atlases[page.placements[0].atlas].hasTranslucency : page.layer === 1;
|
|
18718
18809
|
const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
|
|
18719
|
-
material.side =
|
|
18810
|
+
material.side = import_three46.FrontSide;
|
|
18720
18811
|
if (page.layer === 2) {
|
|
18721
|
-
material.side =
|
|
18812
|
+
material.side = import_three46.DoubleSide;
|
|
18722
18813
|
material.forceSinglePass = true;
|
|
18723
18814
|
material.depthWrite = !material.transparent;
|
|
18724
18815
|
}
|
|
18725
18816
|
material.vertexColors = true;
|
|
18726
18817
|
const texture = material.uniforms?.map?.value ?? material.map;
|
|
18727
|
-
const mesh = new
|
|
18818
|
+
const mesh = new import_three46.Mesh(geometry, material);
|
|
18728
18819
|
section.add(mesh);
|
|
18820
|
+
section.blockIndices.set(mesh, page.blockIndices);
|
|
18729
18821
|
const unsubscribe = [];
|
|
18730
18822
|
for (const { atlas: id, x, y } of page.placements) {
|
|
18731
18823
|
const atlas = atlases[id];
|
|
@@ -18751,6 +18843,7 @@ var SectionMesh = class _SectionMesh extends import_three43.Group {
|
|
|
18751
18843
|
mesh.material.dispose();
|
|
18752
18844
|
texture?.dispose();
|
|
18753
18845
|
}
|
|
18846
|
+
this.blockIndices.clear();
|
|
18754
18847
|
this.removeFromParent();
|
|
18755
18848
|
super.dispose();
|
|
18756
18849
|
}
|
|
@@ -18760,7 +18853,8 @@ var SectionMesh = class _SectionMesh extends import_three43.Group {
|
|
|
18760
18853
|
init_FluidGeometry();
|
|
18761
18854
|
init_FluidQuads();
|
|
18762
18855
|
init_CubeFace();
|
|
18763
|
-
|
|
18856
|
+
init_InstanceReference();
|
|
18857
|
+
var WATER_TINT2 = new import_three47.Color(4159204).toArray();
|
|
18764
18858
|
var Chunk = class _Chunk {
|
|
18765
18859
|
constructor(scene, x, y, z, onBlocksChanged, sectionModels, neighborCell, biomeAt, onBiomesChanged, lightAt, onLightCleared, ambientLight = 0) {
|
|
18766
18860
|
this.onBlocksChanged = onBlocksChanged;
|
|
@@ -18773,10 +18867,11 @@ var Chunk = class _Chunk {
|
|
|
18773
18867
|
this.ambientLight = ambientLight;
|
|
18774
18868
|
this.data = new ChunkData();
|
|
18775
18869
|
this.renderedBlocks = /* @__PURE__ */ new Map();
|
|
18870
|
+
this.objectBlocks = /* @__PURE__ */ new Set();
|
|
18776
18871
|
this.sectionBlocks = /* @__PURE__ */ new Map();
|
|
18777
18872
|
this.hiddenBlocks = /* @__PURE__ */ new Set();
|
|
18778
18873
|
this.fluidCells = new Uint8Array(4096);
|
|
18779
|
-
this.blockPosition = new
|
|
18874
|
+
this.blockPosition = new import_three47.Vector3();
|
|
18780
18875
|
this.meshDirty = false;
|
|
18781
18876
|
this.meshGeneration = 0;
|
|
18782
18877
|
this.scene = scene;
|
|
@@ -18784,20 +18879,84 @@ var Chunk = class _Chunk {
|
|
|
18784
18879
|
this.y = y;
|
|
18785
18880
|
this.z = z;
|
|
18786
18881
|
}
|
|
18882
|
+
/** Finds the nearest owned block hit across sections, testing each shared mesh once. */
|
|
18883
|
+
static raycast(chunks, raycaster) {
|
|
18884
|
+
const roots = /* @__PURE__ */ new Map();
|
|
18885
|
+
const targets = /* @__PURE__ */ new Map();
|
|
18886
|
+
const meshes = (root, scene) => {
|
|
18887
|
+
const cached2 = roots.get(root);
|
|
18888
|
+
if (cached2) return cached2;
|
|
18889
|
+
const result = pickableMeshes(root, scene, raycaster);
|
|
18890
|
+
roots.set(root, result);
|
|
18891
|
+
return result;
|
|
18892
|
+
};
|
|
18893
|
+
const add = (root, owner, reference) => {
|
|
18894
|
+
for (const mesh of meshes(root, owner.chunk.scene)) {
|
|
18895
|
+
if (reference && reference.instanceable.getInstanceReference(mesh, reference.index) !== reference) continue;
|
|
18896
|
+
let entry = targets.get(mesh);
|
|
18897
|
+
if (!entry) targets.set(mesh, entry = { owners: /* @__PURE__ */ new Map() });
|
|
18898
|
+
entry.owners.set(reference?.index, owner);
|
|
18899
|
+
}
|
|
18900
|
+
};
|
|
18901
|
+
for (const chunk of chunks) {
|
|
18902
|
+
for (const index of chunk.objectBlocks) {
|
|
18903
|
+
const block = chunk.renderedBlocks.get(index).object;
|
|
18904
|
+
if (!block || !block.visible || chunk.hiddenBlocks.has(index)) continue;
|
|
18905
|
+
const owner = { chunk, index };
|
|
18906
|
+
for (const model of block.models) {
|
|
18907
|
+
if (isInstanceReference(model)) {
|
|
18908
|
+
if (model.instanceable.isInstanceActive(model.index, model)) add(model.instanceable, owner, model);
|
|
18909
|
+
} else {
|
|
18910
|
+
add(model, owner);
|
|
18911
|
+
}
|
|
18912
|
+
}
|
|
18913
|
+
for (const entity of block.blockEntities) add(entity, owner);
|
|
18914
|
+
}
|
|
18915
|
+
if (chunk.sectionMesh) {
|
|
18916
|
+
for (const mesh of meshes(chunk.sectionMesh, chunk.scene)) {
|
|
18917
|
+
targets.set(mesh, { owners: /* @__PURE__ */ new Map(), section: { chunk, mesh: chunk.sectionMesh } });
|
|
18918
|
+
}
|
|
18919
|
+
}
|
|
18920
|
+
}
|
|
18921
|
+
for (const hit of visibleHits(raycaster, [...targets.keys()])) {
|
|
18922
|
+
const mesh = hit.object;
|
|
18923
|
+
const entry = targets.get(mesh);
|
|
18924
|
+
let owner = entry.owners.get(hit.instanceId) ?? entry.owners.get(void 0);
|
|
18925
|
+
if (entry.section) {
|
|
18926
|
+
const index = entry.section.mesh.getBlockIndex(hit);
|
|
18927
|
+
if (index !== void 0) owner = { chunk: entry.section.chunk, index };
|
|
18928
|
+
}
|
|
18929
|
+
if (!owner || owner.chunk.hiddenBlocks.has(owner.index)) continue;
|
|
18930
|
+
const info = owner.chunk.renderedBlocks.get(owner.index);
|
|
18931
|
+
if (!info) continue;
|
|
18932
|
+
return {
|
|
18933
|
+
position: new import_three47.Vector3(
|
|
18934
|
+
owner.chunk.x * 16 + owner.index % 16,
|
|
18935
|
+
owner.chunk.y * 16 + Math.floor(owner.index / 256),
|
|
18936
|
+
owner.chunk.z * 16 + Math.floor(owner.index / 16) % 16
|
|
18937
|
+
),
|
|
18938
|
+
block: info.block,
|
|
18939
|
+
point: hit.point.clone(),
|
|
18940
|
+
normal: hitNormal(hit),
|
|
18941
|
+
distance: hit.distance
|
|
18942
|
+
};
|
|
18943
|
+
}
|
|
18944
|
+
return void 0;
|
|
18945
|
+
}
|
|
18787
18946
|
getBlockAt(posOrX, y, z) {
|
|
18788
18947
|
if (typeof posOrX == "number") {
|
|
18789
|
-
return this.getBlockAt(new
|
|
18948
|
+
return this.getBlockAt(new import_three47.Vector3(posOrX, y, z));
|
|
18790
18949
|
}
|
|
18791
18950
|
if (isTripleArray(posOrX)) {
|
|
18792
|
-
return this.getBlockAt(new
|
|
18951
|
+
return this.getBlockAt(new import_three47.Vector3(posOrX[0], posOrX[1], posOrX[2]));
|
|
18793
18952
|
}
|
|
18794
18953
|
const pos = this.blockPosition.set(posOrX.x - this.x * 16, posOrX.y - this.y * 16, posOrX.z - this.z * 16);
|
|
18795
18954
|
const index = _Chunk.chunkPosToBlockIndex(pos);
|
|
18796
18955
|
return this.renderedBlocks.get(index);
|
|
18797
18956
|
}
|
|
18798
18957
|
getBiomeAt(posOrX, y, z) {
|
|
18799
|
-
if (typeof posOrX === "number") return this.getBiomeAt(new
|
|
18800
|
-
if (isTripleArray(posOrX)) return this.getBiomeAt(new
|
|
18958
|
+
if (typeof posOrX === "number") return this.getBiomeAt(new import_three47.Vector3(posOrX, y, z));
|
|
18959
|
+
if (isTripleArray(posOrX)) return this.getBiomeAt(new import_three47.Vector3(...posOrX));
|
|
18801
18960
|
const pos = this.worldPosToChunkPos(posOrX);
|
|
18802
18961
|
_Chunk.chunkPosToBlockIndex(pos);
|
|
18803
18962
|
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];
|
|
@@ -18840,17 +18999,17 @@ var Chunk = class _Chunk {
|
|
|
18840
18999
|
this.hiddenBlocks.add(index);
|
|
18841
19000
|
this.renderedBlocks.get(index)?.object?.setVisible(false);
|
|
18842
19001
|
}
|
|
18843
|
-
const positions = blocks.map(({ index }) => new
|
|
19002
|
+
const positions = blocks.map(({ index }) => new import_three47.Vector3(...this.positionAt(index)));
|
|
18844
19003
|
if (this.onBlocksChanged) await this.onBlocksChanged(positions);
|
|
18845
19004
|
else await this.rebuildSectionMesh();
|
|
18846
19005
|
}
|
|
18847
19006
|
}
|
|
18848
19007
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
18849
19008
|
if (typeof posOrX == "number") {
|
|
18850
|
-
return this.setBlockAt(new
|
|
19009
|
+
return this.setBlockAt(new import_three47.Vector3(posOrX, yOrBlock, z), block);
|
|
18851
19010
|
}
|
|
18852
19011
|
if (isTripleArray(posOrX)) {
|
|
18853
|
-
return this.setBlockAt(new
|
|
19012
|
+
return this.setBlockAt(new import_three47.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
18854
19013
|
}
|
|
18855
19014
|
const worldPos = posOrX;
|
|
18856
19015
|
const pos = this.worldPosToChunkPos(worldPos);
|
|
@@ -18904,7 +19063,8 @@ var Chunk = class _Chunk {
|
|
|
18904
19063
|
if (this.fluidCells[index]) this.meshDirty = true;
|
|
18905
19064
|
this.fluidCells[index] = 0;
|
|
18906
19065
|
this.renderedBlocks.delete(index);
|
|
18907
|
-
|
|
19066
|
+
this.objectBlocks.delete(index);
|
|
19067
|
+
const worldPos = new import_three47.Vector3(
|
|
18908
19068
|
this.x * 16 + index % 16,
|
|
18909
19069
|
this.y * 16 + Math.floor(index / 256),
|
|
18910
19070
|
this.z * 16 + Math.floor(index / 16) % 16
|
|
@@ -18946,6 +19106,7 @@ var Chunk = class _Chunk {
|
|
|
18946
19106
|
this.renderedBlocks.set(index, { get block() {
|
|
18947
19107
|
return readBlock();
|
|
18948
19108
|
}, object: object4 });
|
|
19109
|
+
if (object4) this.objectBlocks.add(index);
|
|
18949
19110
|
} catch (error) {
|
|
18950
19111
|
this.data.assign(index, 0);
|
|
18951
19112
|
this.fluidCells[index] = 0;
|
|
@@ -18964,6 +19125,7 @@ var Chunk = class _Chunk {
|
|
|
18964
19125
|
this.fluidCells.fill(0);
|
|
18965
19126
|
this.waterTints = void 0;
|
|
18966
19127
|
this.renderedBlocks.clear();
|
|
19128
|
+
this.objectBlocks.clear();
|
|
18967
19129
|
this.hiddenBlocks.clear();
|
|
18968
19130
|
this.meshDirty = true;
|
|
18969
19131
|
this.data.copyFrom(data);
|
|
@@ -19013,6 +19175,7 @@ var Chunk = class _Chunk {
|
|
|
19013
19175
|
this.renderedBlocks.set(index, { get block() {
|
|
19014
19176
|
return readBlock();
|
|
19015
19177
|
}, object: void 0 });
|
|
19178
|
+
this.objectBlocks.delete(index);
|
|
19016
19179
|
} catch (error) {
|
|
19017
19180
|
this.data.assign(index, 0);
|
|
19018
19181
|
this.fluidCells[index] = 0;
|
|
@@ -19032,16 +19195,18 @@ var Chunk = class _Chunk {
|
|
|
19032
19195
|
biome,
|
|
19033
19196
|
biomePosition: this.biomePosition(index, blockState3, this.data.stateAt(this.data.idAt(index)))
|
|
19034
19197
|
});
|
|
19035
|
-
object4.setPosition(new
|
|
19198
|
+
object4.setPosition(new import_three47.Vector3(
|
|
19036
19199
|
this.x * 256 + index % 16 * 16,
|
|
19037
19200
|
this.y * 256 + Math.floor(index / 256) * 16,
|
|
19038
19201
|
this.z * 256 + Math.floor(index / 16) % 16 * 16
|
|
19039
19202
|
));
|
|
19040
19203
|
this.renderedBlocks.get(index).object = object4;
|
|
19204
|
+
this.objectBlocks.add(index);
|
|
19041
19205
|
} catch (error) {
|
|
19042
19206
|
this.data.assign(index, 0);
|
|
19043
19207
|
this.fluidCells[index] = 0;
|
|
19044
19208
|
this.renderedBlocks.delete(index);
|
|
19209
|
+
this.objectBlocks.delete(index);
|
|
19045
19210
|
object4?.removeFromScene();
|
|
19046
19211
|
if (!failed) failure = error;
|
|
19047
19212
|
failed = true;
|
|
@@ -19122,7 +19287,7 @@ var Chunk = class _Chunk {
|
|
|
19122
19287
|
context.prepared = await prepare(async () => await available() ? BlockTints.getBiomeColor(blockState3?.key, biome, position) : void 0);
|
|
19123
19288
|
if (fluid?.kind === "water" && await available()) {
|
|
19124
19289
|
const color2 = await Biomes.getColor(biome, "water", blockState3?.key);
|
|
19125
|
-
if (color2 !== void 0 && color2 !== 4159204) context.waterTint = new
|
|
19290
|
+
if (color2 !== void 0 && color2 !== 4159204) context.waterTint = new import_three47.Color(color2).toArray();
|
|
19126
19291
|
}
|
|
19127
19292
|
}
|
|
19128
19293
|
for (const index of indices2) contexts.set(index, context);
|
|
@@ -19293,7 +19458,7 @@ var Chunk = class _Chunk {
|
|
|
19293
19458
|
/** Removes stored blocks and render objects. Set `notify` to false to skip the owning world's update. */
|
|
19294
19459
|
async clear(notify = true) {
|
|
19295
19460
|
const positions = notify && this.onBlocksChanged ? [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
|
|
19296
|
-
new
|
|
19461
|
+
new import_three47.Vector3(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
|
|
19297
19462
|
)) : [];
|
|
19298
19463
|
for (const info of this.renderedBlocks.values()) info.object?.removeFromScene();
|
|
19299
19464
|
this.sectionBlocks.clear();
|
|
@@ -19302,6 +19467,7 @@ var Chunk = class _Chunk {
|
|
|
19302
19467
|
this.sectionMesh = void 0;
|
|
19303
19468
|
this.meshDirty = false;
|
|
19304
19469
|
this.renderedBlocks.clear();
|
|
19470
|
+
this.objectBlocks.clear();
|
|
19305
19471
|
this.hiddenBlocks.clear();
|
|
19306
19472
|
this.fluidCells.fill(0);
|
|
19307
19473
|
this.waterTints = void 0;
|
|
@@ -19328,14 +19494,14 @@ var Chunk = class _Chunk {
|
|
|
19328
19494
|
return pos.y * 16 * 16 + pos.z * 16 + pos.x;
|
|
19329
19495
|
}
|
|
19330
19496
|
worldPosToChunkPos(pos) {
|
|
19331
|
-
return new
|
|
19497
|
+
return new import_three47.Vector3(
|
|
19332
19498
|
pos.x - this.x * 16,
|
|
19333
19499
|
pos.y - this.y * 16,
|
|
19334
19500
|
pos.z - this.z * 16
|
|
19335
19501
|
);
|
|
19336
19502
|
}
|
|
19337
19503
|
chunkPosToWorldPos(pos) {
|
|
19338
|
-
return new
|
|
19504
|
+
return new import_three47.Vector3(
|
|
19339
19505
|
this.x * 16 + pos.x,
|
|
19340
19506
|
this.y * 16 + pos.y,
|
|
19341
19507
|
this.z * 16 + pos.z
|