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.js
CHANGED
|
@@ -12596,6 +12596,10 @@ var _BlockObject = class _BlockObject extends SceneObject {
|
|
|
12596
12596
|
get blockEntities() {
|
|
12597
12597
|
return this._entities;
|
|
12598
12598
|
}
|
|
12599
|
+
/** Model placements drawn for this block, including its fluid surface. */
|
|
12600
|
+
get models() {
|
|
12601
|
+
return this._models;
|
|
12602
|
+
}
|
|
12599
12603
|
/** Sets visibility for this block's model instances and block entities. */
|
|
12600
12604
|
setVisible(visible) {
|
|
12601
12605
|
this.visible = visible;
|
|
@@ -17351,12 +17355,12 @@ var AnvilWorldSource = class {
|
|
|
17351
17355
|
};
|
|
17352
17356
|
|
|
17353
17357
|
// src/world/Chunk.ts
|
|
17354
|
-
var
|
|
17358
|
+
var import_three47 = require("three");
|
|
17355
17359
|
init_BlockStates();
|
|
17356
17360
|
init_AssetKey();
|
|
17357
17361
|
|
|
17358
17362
|
// src/world/MineRenderWorld.ts
|
|
17359
|
-
var
|
|
17363
|
+
var import_three45 = require("three");
|
|
17360
17364
|
init_Model();
|
|
17361
17365
|
init_util();
|
|
17362
17366
|
init_AssetKey();
|
|
@@ -17621,11 +17625,74 @@ function resolveSavedEntity(entity) {
|
|
|
17621
17625
|
|
|
17622
17626
|
// src/world/_entities/WorldEntities.ts
|
|
17623
17627
|
init_BannerPatterns();
|
|
17628
|
+
var import_three44 = require("three");
|
|
17629
|
+
|
|
17630
|
+
// src/world/_picking/Picking.ts
|
|
17631
|
+
var import_three42 = require("three");
|
|
17632
|
+
init_three();
|
|
17633
|
+
function pickableMeshes(root, scene, raycaster) {
|
|
17634
|
+
const result = [];
|
|
17635
|
+
let attached = false;
|
|
17636
|
+
for (let parent = root; parent; parent = parent.parent) {
|
|
17637
|
+
if (!parent.visible) return result;
|
|
17638
|
+
if (parent === scene) attached = true;
|
|
17639
|
+
}
|
|
17640
|
+
if (!attached) return result;
|
|
17641
|
+
root.updateWorldMatrix(true, true);
|
|
17642
|
+
root.traverseVisible((object4) => {
|
|
17643
|
+
if (isMesh(object4) && raycaster.layers.test(object4.layers)) result.push(object4);
|
|
17644
|
+
});
|
|
17645
|
+
return result;
|
|
17646
|
+
}
|
|
17647
|
+
function visibleHits(raycaster, meshes) {
|
|
17648
|
+
return raycaster.intersectObjects(meshes, false).filter((hit) => {
|
|
17649
|
+
if (!hit.face) return false;
|
|
17650
|
+
const mesh = hit.object;
|
|
17651
|
+
const material = Array.isArray(mesh.material) ? mesh.material[hit.face.materialIndex] : mesh.material;
|
|
17652
|
+
return material?.visible;
|
|
17653
|
+
});
|
|
17654
|
+
}
|
|
17655
|
+
function hitNormal(hit) {
|
|
17656
|
+
const mesh = hit.object;
|
|
17657
|
+
const matrix = mesh.matrixWorld.clone();
|
|
17658
|
+
if (isInstancedMesh(mesh) && hit.instanceId !== void 0) {
|
|
17659
|
+
const instance = new import_three42.Matrix4();
|
|
17660
|
+
mesh.getMatrixAt(hit.instanceId, instance);
|
|
17661
|
+
matrix.multiply(instance);
|
|
17662
|
+
}
|
|
17663
|
+
return hit.face.normal.clone().applyNormalMatrix(new import_three42.Matrix3().getNormalMatrix(matrix));
|
|
17664
|
+
}
|
|
17665
|
+
|
|
17666
|
+
// src/world/_entities/WorldEntities.ts
|
|
17624
17667
|
var WorldEntities = class {
|
|
17625
17668
|
constructor(scene) {
|
|
17626
17669
|
this.scene = scene;
|
|
17627
17670
|
this.columns = /* @__PURE__ */ new Map();
|
|
17628
17671
|
}
|
|
17672
|
+
/** Finds the nearest visible triangle belonging to an entity owned by this world. */
|
|
17673
|
+
raycast(raycaster) {
|
|
17674
|
+
const owners = /* @__PURE__ */ new Map();
|
|
17675
|
+
for (const column of this.columns.values()) {
|
|
17676
|
+
for (const [object4, placement] of column) {
|
|
17677
|
+
for (const mesh of pickableMeshes(object4, this.scene, raycaster)) {
|
|
17678
|
+
owners.set(mesh, { object: object4, ...placement });
|
|
17679
|
+
}
|
|
17680
|
+
}
|
|
17681
|
+
}
|
|
17682
|
+
for (const hit of visibleHits(raycaster, [...owners.keys()])) {
|
|
17683
|
+
const mesh = hit.object;
|
|
17684
|
+
const owner = owners.get(mesh);
|
|
17685
|
+
return {
|
|
17686
|
+
type: owner.type,
|
|
17687
|
+
position: new import_three44.Vector3(...owner.position),
|
|
17688
|
+
object: owner.object,
|
|
17689
|
+
point: hit.point.clone(),
|
|
17690
|
+
normal: hitNormal(hit),
|
|
17691
|
+
distance: hit.distance
|
|
17692
|
+
};
|
|
17693
|
+
}
|
|
17694
|
+
return void 0;
|
|
17695
|
+
}
|
|
17629
17696
|
/** Captures column ownership before asynchronous block or asset loading starts. */
|
|
17630
17697
|
prepare(entities = [], column) {
|
|
17631
17698
|
const placements = entities.flatMap((entity) => {
|
|
@@ -17634,7 +17701,7 @@ var WorldEntities = class {
|
|
|
17634
17701
|
const position = [...entity.position];
|
|
17635
17702
|
const key = column?.join(",") ?? `${Math.floor(position[0] / 16)},${Math.floor(position[2] / 16)}`;
|
|
17636
17703
|
let owner = this.columns.get(key);
|
|
17637
|
-
if (!owner) this.columns.set(key, owner = /* @__PURE__ */ new
|
|
17704
|
+
if (!owner) this.columns.set(key, owner = /* @__PURE__ */ new Map());
|
|
17638
17705
|
return [{ ...resolved, position, column: key, owner }];
|
|
17639
17706
|
});
|
|
17640
17707
|
return async () => {
|
|
@@ -17660,7 +17727,7 @@ var WorldEntities = class {
|
|
|
17660
17727
|
object4.rotation.y = placement.yaw;
|
|
17661
17728
|
await object4.init();
|
|
17662
17729
|
if (!current()) return;
|
|
17663
|
-
placement.owner.
|
|
17730
|
+
placement.owner.set(object4, { type: placement.key.toNamespacedString(), position: placement.position });
|
|
17664
17731
|
this.scene.add(object4);
|
|
17665
17732
|
} catch (error) {
|
|
17666
17733
|
console.warn(`Could not draw saved entity ${placement.key.toNamespacedString()}, skipping it`, error);
|
|
@@ -17675,7 +17742,7 @@ var WorldEntities = class {
|
|
|
17675
17742
|
const objects = this.columns.get(key);
|
|
17676
17743
|
this.columns.delete(key);
|
|
17677
17744
|
if (!objects) return;
|
|
17678
|
-
for (const object4 of objects) {
|
|
17745
|
+
for (const object4 of objects.keys()) {
|
|
17679
17746
|
object4.removeFromScene();
|
|
17680
17747
|
object4.dispose();
|
|
17681
17748
|
}
|
|
@@ -17736,6 +17803,21 @@ var MineRenderWorld = class {
|
|
|
17736
17803
|
if (options.sectionMeshing) this.sectionModels = new SectionModels(options.maxAtlasSize);
|
|
17737
17804
|
if (options.renderEntities) this.entities = new WorldEntities(scene);
|
|
17738
17805
|
}
|
|
17806
|
+
/**
|
|
17807
|
+
* Returns the nearest visible block geometry hit, respecting the raycaster's layers and near/far range.
|
|
17808
|
+
* Includes fluids and block entities; texture alpha does not change triangle intersections.
|
|
17809
|
+
*/
|
|
17810
|
+
raycast(raycaster) {
|
|
17811
|
+
return Chunk.raycast(this._chunks.values(), raycaster);
|
|
17812
|
+
}
|
|
17813
|
+
/**
|
|
17814
|
+
* Returns the nearest visible mob geometry hit when renderEntities is enabled.
|
|
17815
|
+
* Respects layers and near/far; compare its distance with raycast() to account for blocks.
|
|
17816
|
+
* Texture alpha does not change triangle intersections.
|
|
17817
|
+
*/
|
|
17818
|
+
raycastEntities(raycaster) {
|
|
17819
|
+
return this.entities?.raycast(raycaster);
|
|
17820
|
+
}
|
|
17739
17821
|
/** Whether neighboring opaque cubes shade block-face corners. Defaults to false. */
|
|
17740
17822
|
get ambientOcclusion() {
|
|
17741
17823
|
return this._ambientOcclusion;
|
|
@@ -17756,25 +17838,25 @@ var MineRenderWorld = class {
|
|
|
17756
17838
|
}
|
|
17757
17839
|
getBlockAt(posOrX, y, z) {
|
|
17758
17840
|
if (typeof posOrX == "number") {
|
|
17759
|
-
return this.getBlockAt(new
|
|
17841
|
+
return this.getBlockAt(new import_three45.Vector3(posOrX, y, z));
|
|
17760
17842
|
}
|
|
17761
17843
|
if (isTripleArray(posOrX)) {
|
|
17762
|
-
return this.getBlockAt(new
|
|
17844
|
+
return this.getBlockAt(new import_three45.Vector3(posOrX[0], posOrX[1], posOrX[2]));
|
|
17763
17845
|
}
|
|
17764
17846
|
this.validatePosBounds(posOrX);
|
|
17765
17847
|
return this.getChunkAt(posOrX)?.getBlockAt(posOrX);
|
|
17766
17848
|
}
|
|
17767
17849
|
getBiomeAt(posOrX, y, z) {
|
|
17768
|
-
if (typeof posOrX === "number") return this.getBiomeAt(new
|
|
17769
|
-
if (isTripleArray(posOrX)) return this.getBiomeAt(new
|
|
17850
|
+
if (typeof posOrX === "number") return this.getBiomeAt(new import_three45.Vector3(posOrX, y, z));
|
|
17851
|
+
if (isTripleArray(posOrX)) return this.getBiomeAt(new import_three45.Vector3(...posOrX));
|
|
17770
17852
|
this.validatePosBounds(posOrX);
|
|
17771
17853
|
const cx = Math.floor(posOrX.x / 16), cy = Math.floor(posOrX.y / 16), cz = Math.floor(posOrX.z / 16);
|
|
17772
17854
|
const lx = posOrX.x - cx * 16, ly = posOrX.y - cy * 16, lz = posOrX.z - cz * 16;
|
|
17773
17855
|
return this.biomes.get(`${cx}_${cz}`)?.get(cy)?.[Math.floor(lx / 4) + Math.floor(lz / 4) * 4 + Math.floor(ly / 4) * 16];
|
|
17774
17856
|
}
|
|
17775
17857
|
getLightAt(posOrX, y, z) {
|
|
17776
|
-
if (typeof posOrX === "number") return this.getLightAt(new
|
|
17777
|
-
if (isTripleArray(posOrX)) return this.getLightAt(new
|
|
17858
|
+
if (typeof posOrX === "number") return this.getLightAt(new import_three45.Vector3(posOrX, y, z));
|
|
17859
|
+
if (isTripleArray(posOrX)) return this.getLightAt(new import_three45.Vector3(...posOrX));
|
|
17778
17860
|
this.validatePosBounds(posOrX);
|
|
17779
17861
|
const { x, y: py, z: pz } = posOrX;
|
|
17780
17862
|
const cx = Math.floor(x / 16), cy = Math.floor(py / 16), cz = Math.floor(pz / 16);
|
|
@@ -17792,10 +17874,10 @@ var MineRenderWorld = class {
|
|
|
17792
17874
|
}
|
|
17793
17875
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
17794
17876
|
if (typeof posOrX == "number") {
|
|
17795
|
-
return this.setBlockAt(new
|
|
17877
|
+
return this.setBlockAt(new import_three45.Vector3(posOrX, yOrBlock, z), block);
|
|
17796
17878
|
}
|
|
17797
17879
|
if (isTripleArray(posOrX)) {
|
|
17798
|
-
return this.setBlockAt(new
|
|
17880
|
+
return this.setBlockAt(new import_three45.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
17799
17881
|
}
|
|
17800
17882
|
return this.placeBlock(posOrX, yOrBlock);
|
|
17801
17883
|
}
|
|
@@ -17806,10 +17888,10 @@ var MineRenderWorld = class {
|
|
|
17806
17888
|
}
|
|
17807
17889
|
async setBlockVisibleAt(posOrX, yOrVisible, z, visible) {
|
|
17808
17890
|
if (typeof posOrX === "number") {
|
|
17809
|
-
return this.setBlockVisibleAt(new
|
|
17891
|
+
return this.setBlockVisibleAt(new import_three45.Vector3(posOrX, yOrVisible, z), visible);
|
|
17810
17892
|
}
|
|
17811
17893
|
if (isTripleArray(posOrX)) {
|
|
17812
|
-
return this.setBlockVisibleAt(new
|
|
17894
|
+
return this.setBlockVisibleAt(new import_three45.Vector3(...posOrX), yOrVisible);
|
|
17813
17895
|
}
|
|
17814
17896
|
this.validatePosBounds(posOrX);
|
|
17815
17897
|
await this.getChunkAt(posOrX)?.setBlockVisibleAt(posOrX, yOrVisible);
|
|
@@ -17835,7 +17917,7 @@ var MineRenderWorld = class {
|
|
|
17835
17917
|
const collect = async (positions2) => {
|
|
17836
17918
|
for (const pos of positions2) changes.set(pos.toArray().join(","), pos);
|
|
17837
17919
|
};
|
|
17838
|
-
const place = (block) => this.placeBlock(new
|
|
17920
|
+
const place = (block) => this.placeBlock(new import_three45.Vector3(...block.position), block, collect);
|
|
17839
17921
|
const keys = /* @__PURE__ */ new Map();
|
|
17840
17922
|
const types = /* @__PURE__ */ new Set();
|
|
17841
17923
|
for (const block of multiblock.blocks) {
|
|
@@ -17851,7 +17933,7 @@ var MineRenderWorld = class {
|
|
|
17851
17933
|
}
|
|
17852
17934
|
if (!executor) {
|
|
17853
17935
|
const groups2 = /* @__PURE__ */ new Map();
|
|
17854
|
-
const position = new
|
|
17936
|
+
const position = new import_three45.Vector3();
|
|
17855
17937
|
for (const block of multiblock.blocks) {
|
|
17856
17938
|
const [x, y, z] = block.position;
|
|
17857
17939
|
this.validatePosBounds(position.set(x, y, z));
|
|
@@ -17891,7 +17973,7 @@ var MineRenderWorld = class {
|
|
|
17891
17973
|
try {
|
|
17892
17974
|
positions = await chunk.placeBlocks(blocks);
|
|
17893
17975
|
} finally {
|
|
17894
|
-
positions ?? (positions = blocks.map(({ index }) => new
|
|
17976
|
+
positions ?? (positions = blocks.map(({ index }) => new import_three45.Vector3(
|
|
17895
17977
|
chunk.x * 16 + index % 16,
|
|
17896
17978
|
chunk.y * 16 + Math.floor(index / 256),
|
|
17897
17979
|
chunk.z * 16 + Math.floor(index / 16) % 16
|
|
@@ -17943,7 +18025,7 @@ var MineRenderWorld = class {
|
|
|
17943
18025
|
}
|
|
17944
18026
|
for (const section of chunk.sections) {
|
|
17945
18027
|
if (section.biomes) {
|
|
17946
|
-
const position = new
|
|
18028
|
+
const position = new import_three45.Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);
|
|
17947
18029
|
this.validatePosBounds(position);
|
|
17948
18030
|
const copy = [...section.biomes];
|
|
17949
18031
|
if (copy.length !== 64 || !copy.every((id) => typeof id === "string" && id.length > 0)) {
|
|
@@ -17959,7 +18041,7 @@ var MineRenderWorld = class {
|
|
|
17959
18041
|
for (const section of chunk.sections) {
|
|
17960
18042
|
if (!executor) {
|
|
17961
18043
|
if (!occupiedSections.has(section.y)) continue;
|
|
17962
|
-
const position = new
|
|
18044
|
+
const position = new import_three45.Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);
|
|
17963
18045
|
this.validatePosBounds(position);
|
|
17964
18046
|
const target = this.getOrCreateChunkAt(position);
|
|
17965
18047
|
try {
|
|
@@ -18063,7 +18145,7 @@ var MineRenderWorld = class {
|
|
|
18063
18145
|
this.sectionModels?.clear();
|
|
18064
18146
|
}
|
|
18065
18147
|
updateCulling(positions) {
|
|
18066
|
-
const neighbor = new
|
|
18148
|
+
const neighbor = new import_three45.Vector3();
|
|
18067
18149
|
for (const pos of positions) {
|
|
18068
18150
|
const cx = Math.floor(pos.x / 16), cy = Math.floor(pos.y / 16), cz = Math.floor(pos.z / 16);
|
|
18069
18151
|
const chunk = this._chunks.get(`${cx}_${cy}_${cz}`);
|
|
@@ -18194,7 +18276,7 @@ var MineRenderWorld = class {
|
|
|
18194
18276
|
}
|
|
18195
18277
|
/** Converts block coordinates to scene units by multiplying each component by 16. */
|
|
18196
18278
|
static worldToScenePosition(pos) {
|
|
18197
|
-
return new
|
|
18279
|
+
return new import_three45.Vector3(
|
|
18198
18280
|
pos.x * 16,
|
|
18199
18281
|
pos.y * 16,
|
|
18200
18282
|
pos.z * 16
|
|
@@ -18202,7 +18284,7 @@ var MineRenderWorld = class {
|
|
|
18202
18284
|
}
|
|
18203
18285
|
/** Converts scene units to block coordinates without rounding to an integer block. */
|
|
18204
18286
|
static sceneToWorldPosition(pos) {
|
|
18205
|
-
return new
|
|
18287
|
+
return new import_three45.Vector3(
|
|
18206
18288
|
pos.x / 16,
|
|
18207
18289
|
pos.y / 16,
|
|
18208
18290
|
pos.z / 16
|
|
@@ -18225,7 +18307,7 @@ var MineRenderWorld = class {
|
|
|
18225
18307
|
init_Model();
|
|
18226
18308
|
|
|
18227
18309
|
// src/world/SectionMesh.ts
|
|
18228
|
-
var
|
|
18310
|
+
var import_three46 = require("three");
|
|
18229
18311
|
init_CanvasCompat();
|
|
18230
18312
|
init_Materials();
|
|
18231
18313
|
|
|
@@ -18410,6 +18492,7 @@ function buildSectionGeometry(input) {
|
|
|
18410
18492
|
const positions = new Float32Array(faces * 12), normals = new Float32Array(faces * 12);
|
|
18411
18493
|
const uvs = new Float32Array(faces * 8), uvBounds = new Float32Array(faces * 16), colors = new Float32Array(faces * 12);
|
|
18412
18494
|
const outputIndices = new Uint32Array(faces * 6);
|
|
18495
|
+
const blockIndices = new Uint16Array(faces);
|
|
18413
18496
|
let vertex = 0, indexOffset = 0;
|
|
18414
18497
|
for (const entry of page.entries) {
|
|
18415
18498
|
const template = templateData[templates[entry]];
|
|
@@ -18424,6 +18507,7 @@ function buildSectionGeometry(input) {
|
|
|
18424
18507
|
const ambientMask = ambientOcclusion && template.ambientOcclusion !== false ? sectionAmbientOcclusionMask(ambientOcclusion, lightIndex) : 0;
|
|
18425
18508
|
for (let quad = 0; quad < template.quads; quad++) {
|
|
18426
18509
|
if (cullMasks[entry] & template.cullFaces[quad]) continue;
|
|
18510
|
+
blockIndices[indexOffset / 6] = indices[entry];
|
|
18427
18511
|
if (ambientMask) quadAmbientOcclusion(template.positions, template.normals, quad, ambientMask, cornerBrightness2);
|
|
18428
18512
|
const brightness = light ? lightBrightness(light[lightIndex + LIGHT_SAMPLE_OFFSETS[quadLightIndex(template.positions, template.normals, quad)]], ambientLight) : 1;
|
|
18429
18513
|
const start = vertex;
|
|
@@ -18456,6 +18540,7 @@ function buildSectionGeometry(input) {
|
|
|
18456
18540
|
const mapV = (v) => 1 - (placement.y + (1 - v) * atlas.height) / page.height;
|
|
18457
18541
|
const lightIndex = (y + 1) * 324 + (z + 1) * 18 + x + 1;
|
|
18458
18542
|
for (let quad = 0; quad < quads.sprites.length; quad++) {
|
|
18543
|
+
blockIndices[indexOffset / 6] = x + z * 16 + y * 256;
|
|
18459
18544
|
const rect = quads.sprites[quad] === 0 ? data.still : data.flow;
|
|
18460
18545
|
const brightness = light ? lightBrightness(fluidLightLevel(
|
|
18461
18546
|
light[lightIndex],
|
|
@@ -18486,11 +18571,11 @@ function buildSectionGeometry(input) {
|
|
|
18486
18571
|
indexOffset += 6;
|
|
18487
18572
|
}
|
|
18488
18573
|
}
|
|
18489
|
-
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices };
|
|
18574
|
+
return { layer: page.layer, width: page.width, height: page.height, placements: page.placements, positions, normals, uvs, uvBounds, colors, indices: outputIndices, blockIndices };
|
|
18490
18575
|
});
|
|
18491
18576
|
}
|
|
18492
18577
|
function sectionGeometryTransferables(pages) {
|
|
18493
|
-
return pages.flatMap((page) => [page.positions.buffer, page.normals.buffer, page.uvs.buffer, page.uvBounds.buffer, page.colors.buffer, page.indices.buffer]);
|
|
18578
|
+
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]);
|
|
18494
18579
|
}
|
|
18495
18580
|
|
|
18496
18581
|
// src/world/SectionWorker.ts
|
|
@@ -18547,7 +18632,7 @@ var SectionWorker = _SectionWorker;
|
|
|
18547
18632
|
|
|
18548
18633
|
// src/world/SectionMesh.ts
|
|
18549
18634
|
var templateCache = /* @__PURE__ */ new WeakMap();
|
|
18550
|
-
var WATER_TINT = new
|
|
18635
|
+
var WATER_TINT = new import_three46.Color(4159204).toArray();
|
|
18551
18636
|
function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
18552
18637
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
18553
18638
|
const atlases = [];
|
|
@@ -18644,10 +18729,16 @@ function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
|
18644
18729
|
}
|
|
18645
18730
|
return { input, atlases };
|
|
18646
18731
|
}
|
|
18647
|
-
var SectionMesh = class _SectionMesh extends
|
|
18732
|
+
var SectionMesh = class _SectionMesh extends import_three46.Group {
|
|
18648
18733
|
constructor() {
|
|
18649
18734
|
super(...arguments);
|
|
18650
18735
|
this.ownedMeshes = [];
|
|
18736
|
+
this.blockIndices = /* @__PURE__ */ new Map();
|
|
18737
|
+
}
|
|
18738
|
+
/** Returns the owning section cell for a triangle hit on this mesh's merged geometry. */
|
|
18739
|
+
getBlockIndex(hit) {
|
|
18740
|
+
if (hit.faceIndex === void 0 || hit.faceIndex === null) return void 0;
|
|
18741
|
+
return this.blockIndices.get(hit.object)?.[Math.floor(hit.faceIndex / 2)];
|
|
18651
18742
|
}
|
|
18652
18743
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
18653
18744
|
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
@@ -18669,27 +18760,28 @@ var SectionMesh = class _SectionMesh extends import_three43.Group {
|
|
|
18669
18760
|
for (const { atlas, x, y } of page.placements) {
|
|
18670
18761
|
context.drawImage(atlases[atlas].image.canvas, x, y);
|
|
18671
18762
|
}
|
|
18672
|
-
const geometry = new
|
|
18673
|
-
geometry.setAttribute("position", new
|
|
18674
|
-
geometry.setAttribute("normal", new
|
|
18675
|
-
geometry.setAttribute("uv", new
|
|
18676
|
-
geometry.setAttribute("uvBounds", new
|
|
18677
|
-
geometry.setAttribute("color", new
|
|
18678
|
-
geometry.setIndex(new
|
|
18763
|
+
const geometry = new import_three46.BufferGeometry();
|
|
18764
|
+
geometry.setAttribute("position", new import_three46.Float32BufferAttribute(page.positions.buffer, 3));
|
|
18765
|
+
geometry.setAttribute("normal", new import_three46.Float32BufferAttribute(page.normals.buffer, 3));
|
|
18766
|
+
geometry.setAttribute("uv", new import_three46.Float32BufferAttribute(page.uvs.buffer, 2));
|
|
18767
|
+
geometry.setAttribute("uvBounds", new import_three46.Float32BufferAttribute(page.uvBounds.buffer, 4));
|
|
18768
|
+
geometry.setAttribute("color", new import_three46.Float32BufferAttribute(page.colors.buffer, 3));
|
|
18769
|
+
geometry.setIndex(new import_three46.Uint32BufferAttribute(page.indices.buffer, 1));
|
|
18679
18770
|
geometry.computeBoundingBox();
|
|
18680
18771
|
geometry.computeBoundingSphere();
|
|
18681
18772
|
const transparent = page.layer === 2 ? atlases[page.placements[0].atlas].hasTranslucency : page.layer === 1;
|
|
18682
18773
|
const material = Materials.createShadedCanvasMaterial(canvas, transparent, false, true);
|
|
18683
|
-
material.side =
|
|
18774
|
+
material.side = import_three46.FrontSide;
|
|
18684
18775
|
if (page.layer === 2) {
|
|
18685
|
-
material.side =
|
|
18776
|
+
material.side = import_three46.DoubleSide;
|
|
18686
18777
|
material.forceSinglePass = true;
|
|
18687
18778
|
material.depthWrite = !material.transparent;
|
|
18688
18779
|
}
|
|
18689
18780
|
material.vertexColors = true;
|
|
18690
18781
|
const texture = material.uniforms?.map?.value ?? material.map;
|
|
18691
|
-
const mesh = new
|
|
18782
|
+
const mesh = new import_three46.Mesh(geometry, material);
|
|
18692
18783
|
section.add(mesh);
|
|
18784
|
+
section.blockIndices.set(mesh, page.blockIndices);
|
|
18693
18785
|
const unsubscribe = [];
|
|
18694
18786
|
for (const { atlas: id, x, y } of page.placements) {
|
|
18695
18787
|
const atlas = atlases[id];
|
|
@@ -18715,6 +18807,7 @@ var SectionMesh = class _SectionMesh extends import_three43.Group {
|
|
|
18715
18807
|
mesh.material.dispose();
|
|
18716
18808
|
texture?.dispose();
|
|
18717
18809
|
}
|
|
18810
|
+
this.blockIndices.clear();
|
|
18718
18811
|
this.removeFromParent();
|
|
18719
18812
|
super.dispose();
|
|
18720
18813
|
}
|
|
@@ -18724,7 +18817,8 @@ var SectionMesh = class _SectionMesh extends import_three43.Group {
|
|
|
18724
18817
|
init_FluidGeometry();
|
|
18725
18818
|
init_FluidQuads();
|
|
18726
18819
|
init_CubeFace();
|
|
18727
|
-
|
|
18820
|
+
init_InstanceReference();
|
|
18821
|
+
var WATER_TINT2 = new import_three47.Color(4159204).toArray();
|
|
18728
18822
|
var Chunk = class _Chunk {
|
|
18729
18823
|
constructor(scene, x, y, z, onBlocksChanged, sectionModels, neighborCell, biomeAt, onBiomesChanged, lightAt, onLightCleared, ambientLight = 0) {
|
|
18730
18824
|
this.onBlocksChanged = onBlocksChanged;
|
|
@@ -18737,10 +18831,11 @@ var Chunk = class _Chunk {
|
|
|
18737
18831
|
this.ambientLight = ambientLight;
|
|
18738
18832
|
this.data = new ChunkData();
|
|
18739
18833
|
this.renderedBlocks = /* @__PURE__ */ new Map();
|
|
18834
|
+
this.objectBlocks = /* @__PURE__ */ new Set();
|
|
18740
18835
|
this.sectionBlocks = /* @__PURE__ */ new Map();
|
|
18741
18836
|
this.hiddenBlocks = /* @__PURE__ */ new Set();
|
|
18742
18837
|
this.fluidCells = new Uint8Array(4096);
|
|
18743
|
-
this.blockPosition = new
|
|
18838
|
+
this.blockPosition = new import_three47.Vector3();
|
|
18744
18839
|
this.meshDirty = false;
|
|
18745
18840
|
this.meshGeneration = 0;
|
|
18746
18841
|
this.scene = scene;
|
|
@@ -18748,20 +18843,84 @@ var Chunk = class _Chunk {
|
|
|
18748
18843
|
this.y = y;
|
|
18749
18844
|
this.z = z;
|
|
18750
18845
|
}
|
|
18846
|
+
/** Finds the nearest owned block hit across sections, testing each shared mesh once. */
|
|
18847
|
+
static raycast(chunks, raycaster) {
|
|
18848
|
+
const roots = /* @__PURE__ */ new Map();
|
|
18849
|
+
const targets = /* @__PURE__ */ new Map();
|
|
18850
|
+
const meshes = (root, scene) => {
|
|
18851
|
+
const cached2 = roots.get(root);
|
|
18852
|
+
if (cached2) return cached2;
|
|
18853
|
+
const result = pickableMeshes(root, scene, raycaster);
|
|
18854
|
+
roots.set(root, result);
|
|
18855
|
+
return result;
|
|
18856
|
+
};
|
|
18857
|
+
const add = (root, owner, reference) => {
|
|
18858
|
+
for (const mesh of meshes(root, owner.chunk.scene)) {
|
|
18859
|
+
if (reference && reference.instanceable.getInstanceReference(mesh, reference.index) !== reference) continue;
|
|
18860
|
+
let entry = targets.get(mesh);
|
|
18861
|
+
if (!entry) targets.set(mesh, entry = { owners: /* @__PURE__ */ new Map() });
|
|
18862
|
+
entry.owners.set(reference?.index, owner);
|
|
18863
|
+
}
|
|
18864
|
+
};
|
|
18865
|
+
for (const chunk of chunks) {
|
|
18866
|
+
for (const index of chunk.objectBlocks) {
|
|
18867
|
+
const block = chunk.renderedBlocks.get(index).object;
|
|
18868
|
+
if (!block || !block.visible || chunk.hiddenBlocks.has(index)) continue;
|
|
18869
|
+
const owner = { chunk, index };
|
|
18870
|
+
for (const model of block.models) {
|
|
18871
|
+
if (isInstanceReference(model)) {
|
|
18872
|
+
if (model.instanceable.isInstanceActive(model.index, model)) add(model.instanceable, owner, model);
|
|
18873
|
+
} else {
|
|
18874
|
+
add(model, owner);
|
|
18875
|
+
}
|
|
18876
|
+
}
|
|
18877
|
+
for (const entity of block.blockEntities) add(entity, owner);
|
|
18878
|
+
}
|
|
18879
|
+
if (chunk.sectionMesh) {
|
|
18880
|
+
for (const mesh of meshes(chunk.sectionMesh, chunk.scene)) {
|
|
18881
|
+
targets.set(mesh, { owners: /* @__PURE__ */ new Map(), section: { chunk, mesh: chunk.sectionMesh } });
|
|
18882
|
+
}
|
|
18883
|
+
}
|
|
18884
|
+
}
|
|
18885
|
+
for (const hit of visibleHits(raycaster, [...targets.keys()])) {
|
|
18886
|
+
const mesh = hit.object;
|
|
18887
|
+
const entry = targets.get(mesh);
|
|
18888
|
+
let owner = entry.owners.get(hit.instanceId) ?? entry.owners.get(void 0);
|
|
18889
|
+
if (entry.section) {
|
|
18890
|
+
const index = entry.section.mesh.getBlockIndex(hit);
|
|
18891
|
+
if (index !== void 0) owner = { chunk: entry.section.chunk, index };
|
|
18892
|
+
}
|
|
18893
|
+
if (!owner || owner.chunk.hiddenBlocks.has(owner.index)) continue;
|
|
18894
|
+
const info = owner.chunk.renderedBlocks.get(owner.index);
|
|
18895
|
+
if (!info) continue;
|
|
18896
|
+
return {
|
|
18897
|
+
position: new import_three47.Vector3(
|
|
18898
|
+
owner.chunk.x * 16 + owner.index % 16,
|
|
18899
|
+
owner.chunk.y * 16 + Math.floor(owner.index / 256),
|
|
18900
|
+
owner.chunk.z * 16 + Math.floor(owner.index / 16) % 16
|
|
18901
|
+
),
|
|
18902
|
+
block: info.block,
|
|
18903
|
+
point: hit.point.clone(),
|
|
18904
|
+
normal: hitNormal(hit),
|
|
18905
|
+
distance: hit.distance
|
|
18906
|
+
};
|
|
18907
|
+
}
|
|
18908
|
+
return void 0;
|
|
18909
|
+
}
|
|
18751
18910
|
getBlockAt(posOrX, y, z) {
|
|
18752
18911
|
if (typeof posOrX == "number") {
|
|
18753
|
-
return this.getBlockAt(new
|
|
18912
|
+
return this.getBlockAt(new import_three47.Vector3(posOrX, y, z));
|
|
18754
18913
|
}
|
|
18755
18914
|
if (isTripleArray(posOrX)) {
|
|
18756
|
-
return this.getBlockAt(new
|
|
18915
|
+
return this.getBlockAt(new import_three47.Vector3(posOrX[0], posOrX[1], posOrX[2]));
|
|
18757
18916
|
}
|
|
18758
18917
|
const pos = this.blockPosition.set(posOrX.x - this.x * 16, posOrX.y - this.y * 16, posOrX.z - this.z * 16);
|
|
18759
18918
|
const index = _Chunk.chunkPosToBlockIndex(pos);
|
|
18760
18919
|
return this.renderedBlocks.get(index);
|
|
18761
18920
|
}
|
|
18762
18921
|
getBiomeAt(posOrX, y, z) {
|
|
18763
|
-
if (typeof posOrX === "number") return this.getBiomeAt(new
|
|
18764
|
-
if (isTripleArray(posOrX)) return this.getBiomeAt(new
|
|
18922
|
+
if (typeof posOrX === "number") return this.getBiomeAt(new import_three47.Vector3(posOrX, y, z));
|
|
18923
|
+
if (isTripleArray(posOrX)) return this.getBiomeAt(new import_three47.Vector3(...posOrX));
|
|
18765
18924
|
const pos = this.worldPosToChunkPos(posOrX);
|
|
18766
18925
|
_Chunk.chunkPosToBlockIndex(pos);
|
|
18767
18926
|
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];
|
|
@@ -18804,17 +18963,17 @@ var Chunk = class _Chunk {
|
|
|
18804
18963
|
this.hiddenBlocks.add(index);
|
|
18805
18964
|
this.renderedBlocks.get(index)?.object?.setVisible(false);
|
|
18806
18965
|
}
|
|
18807
|
-
const positions = blocks.map(({ index }) => new
|
|
18966
|
+
const positions = blocks.map(({ index }) => new import_three47.Vector3(...this.positionAt(index)));
|
|
18808
18967
|
if (this.onBlocksChanged) await this.onBlocksChanged(positions);
|
|
18809
18968
|
else await this.rebuildSectionMesh();
|
|
18810
18969
|
}
|
|
18811
18970
|
}
|
|
18812
18971
|
async setBlockAt(posOrX, yOrBlock, z, block) {
|
|
18813
18972
|
if (typeof posOrX == "number") {
|
|
18814
|
-
return this.setBlockAt(new
|
|
18973
|
+
return this.setBlockAt(new import_three47.Vector3(posOrX, yOrBlock, z), block);
|
|
18815
18974
|
}
|
|
18816
18975
|
if (isTripleArray(posOrX)) {
|
|
18817
|
-
return this.setBlockAt(new
|
|
18976
|
+
return this.setBlockAt(new import_three47.Vector3(posOrX[0], posOrX[1], posOrX[2]), yOrBlock);
|
|
18818
18977
|
}
|
|
18819
18978
|
const worldPos = posOrX;
|
|
18820
18979
|
const pos = this.worldPosToChunkPos(worldPos);
|
|
@@ -18868,7 +19027,8 @@ var Chunk = class _Chunk {
|
|
|
18868
19027
|
if (this.fluidCells[index]) this.meshDirty = true;
|
|
18869
19028
|
this.fluidCells[index] = 0;
|
|
18870
19029
|
this.renderedBlocks.delete(index);
|
|
18871
|
-
|
|
19030
|
+
this.objectBlocks.delete(index);
|
|
19031
|
+
const worldPos = new import_three47.Vector3(
|
|
18872
19032
|
this.x * 16 + index % 16,
|
|
18873
19033
|
this.y * 16 + Math.floor(index / 256),
|
|
18874
19034
|
this.z * 16 + Math.floor(index / 16) % 16
|
|
@@ -18910,6 +19070,7 @@ var Chunk = class _Chunk {
|
|
|
18910
19070
|
this.renderedBlocks.set(index, { get block() {
|
|
18911
19071
|
return readBlock();
|
|
18912
19072
|
}, object: object4 });
|
|
19073
|
+
if (object4) this.objectBlocks.add(index);
|
|
18913
19074
|
} catch (error) {
|
|
18914
19075
|
this.data.assign(index, 0);
|
|
18915
19076
|
this.fluidCells[index] = 0;
|
|
@@ -18928,6 +19089,7 @@ var Chunk = class _Chunk {
|
|
|
18928
19089
|
this.fluidCells.fill(0);
|
|
18929
19090
|
this.waterTints = void 0;
|
|
18930
19091
|
this.renderedBlocks.clear();
|
|
19092
|
+
this.objectBlocks.clear();
|
|
18931
19093
|
this.hiddenBlocks.clear();
|
|
18932
19094
|
this.meshDirty = true;
|
|
18933
19095
|
this.data.copyFrom(data);
|
|
@@ -18977,6 +19139,7 @@ var Chunk = class _Chunk {
|
|
|
18977
19139
|
this.renderedBlocks.set(index, { get block() {
|
|
18978
19140
|
return readBlock();
|
|
18979
19141
|
}, object: void 0 });
|
|
19142
|
+
this.objectBlocks.delete(index);
|
|
18980
19143
|
} catch (error) {
|
|
18981
19144
|
this.data.assign(index, 0);
|
|
18982
19145
|
this.fluidCells[index] = 0;
|
|
@@ -18996,16 +19159,18 @@ var Chunk = class _Chunk {
|
|
|
18996
19159
|
biome,
|
|
18997
19160
|
biomePosition: this.biomePosition(index, blockState3, this.data.stateAt(this.data.idAt(index)))
|
|
18998
19161
|
});
|
|
18999
|
-
object4.setPosition(new
|
|
19162
|
+
object4.setPosition(new import_three47.Vector3(
|
|
19000
19163
|
this.x * 256 + index % 16 * 16,
|
|
19001
19164
|
this.y * 256 + Math.floor(index / 256) * 16,
|
|
19002
19165
|
this.z * 256 + Math.floor(index / 16) % 16 * 16
|
|
19003
19166
|
));
|
|
19004
19167
|
this.renderedBlocks.get(index).object = object4;
|
|
19168
|
+
this.objectBlocks.add(index);
|
|
19005
19169
|
} catch (error) {
|
|
19006
19170
|
this.data.assign(index, 0);
|
|
19007
19171
|
this.fluidCells[index] = 0;
|
|
19008
19172
|
this.renderedBlocks.delete(index);
|
|
19173
|
+
this.objectBlocks.delete(index);
|
|
19009
19174
|
object4?.removeFromScene();
|
|
19010
19175
|
if (!failed) failure = error;
|
|
19011
19176
|
failed = true;
|
|
@@ -19086,7 +19251,7 @@ var Chunk = class _Chunk {
|
|
|
19086
19251
|
context.prepared = await prepare(async () => await available() ? BlockTints.getBiomeColor(blockState3?.key, biome, position) : void 0);
|
|
19087
19252
|
if (fluid?.kind === "water" && await available()) {
|
|
19088
19253
|
const color2 = await Biomes.getColor(biome, "water", blockState3?.key);
|
|
19089
|
-
if (color2 !== void 0 && color2 !== 4159204) context.waterTint = new
|
|
19254
|
+
if (color2 !== void 0 && color2 !== 4159204) context.waterTint = new import_three47.Color(color2).toArray();
|
|
19090
19255
|
}
|
|
19091
19256
|
}
|
|
19092
19257
|
for (const index of indices2) contexts.set(index, context);
|
|
@@ -19257,7 +19422,7 @@ var Chunk = class _Chunk {
|
|
|
19257
19422
|
/** Removes stored blocks and render objects. Set `notify` to false to skip the owning world's update. */
|
|
19258
19423
|
async clear(notify = true) {
|
|
19259
19424
|
const positions = notify && this.onBlocksChanged ? [...this.renderedBlocks.keys()].map((index) => this.chunkPosToWorldPos(
|
|
19260
|
-
new
|
|
19425
|
+
new import_three47.Vector3(index % 16, Math.floor(index / 256), Math.floor(index / 16) % 16)
|
|
19261
19426
|
)) : [];
|
|
19262
19427
|
for (const info of this.renderedBlocks.values()) info.object?.removeFromScene();
|
|
19263
19428
|
this.sectionBlocks.clear();
|
|
@@ -19266,6 +19431,7 @@ var Chunk = class _Chunk {
|
|
|
19266
19431
|
this.sectionMesh = void 0;
|
|
19267
19432
|
this.meshDirty = false;
|
|
19268
19433
|
this.renderedBlocks.clear();
|
|
19434
|
+
this.objectBlocks.clear();
|
|
19269
19435
|
this.hiddenBlocks.clear();
|
|
19270
19436
|
this.fluidCells.fill(0);
|
|
19271
19437
|
this.waterTints = void 0;
|
|
@@ -19292,14 +19458,14 @@ var Chunk = class _Chunk {
|
|
|
19292
19458
|
return pos.y * 16 * 16 + pos.z * 16 + pos.x;
|
|
19293
19459
|
}
|
|
19294
19460
|
worldPosToChunkPos(pos) {
|
|
19295
|
-
return new
|
|
19461
|
+
return new import_three47.Vector3(
|
|
19296
19462
|
pos.x - this.x * 16,
|
|
19297
19463
|
pos.y - this.y * 16,
|
|
19298
19464
|
pos.z - this.z * 16
|
|
19299
19465
|
);
|
|
19300
19466
|
}
|
|
19301
19467
|
chunkPosToWorldPos(pos) {
|
|
19302
|
-
return new
|
|
19468
|
+
return new import_three47.Vector3(
|
|
19303
19469
|
this.x * 16 + pos.x,
|
|
19304
19470
|
this.y * 16 + pos.y,
|
|
19305
19471
|
this.z * 16 + pos.z
|