minerender 2.1.0-alpha.119 → 2.1.0-alpha.120
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 +121 -73
- package/dist/browser/index.d.ts +121 -73
- package/dist/browser/index.js +203 -19
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +203 -19
- package/dist/browser/index.mjs.map +1 -1
- package/dist/browser/section.worker.js +43 -5
- package/dist/browser/section.worker.js.map +1 -1
- package/dist/browser/section.worker.mjs +43 -5
- package/dist/browser/section.worker.mjs.map +1 -1
- package/dist/bundle.js +209 -19
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +121 -73
- package/dist/node/index.d.ts +121 -73
- package/dist/node/index.js +205 -19
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +203 -19
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/bundle.js
CHANGED
|
@@ -95481,6 +95481,7 @@ ${shader.fragmentShader}`.replace(
|
|
|
95481
95481
|
classicSkinTextureCoordinates: () => classicSkinTextureCoordinates,
|
|
95482
95482
|
computeMorphedAttributes: () => computeMorphedAttributes,
|
|
95483
95483
|
computeTangents: () => computeTangents,
|
|
95484
|
+
copySectionLight: () => copySectionLight,
|
|
95484
95485
|
createCanvas: () => createCanvas,
|
|
95485
95486
|
createFluidGeometry: () => createFluidGeometry,
|
|
95486
95487
|
createGuiTextGeometry: () => createGuiTextGeometry,
|
|
@@ -95533,6 +95534,7 @@ ${shader.fragmentShader}`.replace(
|
|
|
95533
95534
|
sampleEntityAnimation: () => sampleEntityAnimation,
|
|
95534
95535
|
sampleEntityKeyframes: () => sampleEntityKeyframes,
|
|
95535
95536
|
sampleFluid: () => sampleFluid,
|
|
95537
|
+
sampleSectionLight: () => sampleSectionLight,
|
|
95536
95538
|
sectionGeometryTransferables: () => sectionGeometryTransferables,
|
|
95537
95539
|
serializeBoxGeometryKey: () => serializeBoxGeometryKey,
|
|
95538
95540
|
serializeImageKey: () => serializeImageKey,
|
|
@@ -107197,11 +107199,20 @@ gl_FragDepth=readDepth(vUv);
|
|
|
107197
107199
|
const { root, expected } = await this.readNBT(data, location, options);
|
|
107198
107200
|
const level = root.Level?.type === "compound" ? root.Level.value : root;
|
|
107199
107201
|
const dataVersion = root.DataVersion?.type === "int" ? root.DataVersion.value : void 0;
|
|
107202
|
+
const sections = this.compounds(level.sections ?? level.Sections, "sections");
|
|
107203
|
+
const lightFlagName = level.isLightOn ? "isLightOn" : "LightPopulated";
|
|
107204
|
+
const lightFlag = level[lightFlagName];
|
|
107205
|
+
if (lightFlag && (lightFlag.type !== "byte" || lightFlag.value !== 0 && lightFlag.value !== 1)) {
|
|
107206
|
+
throw new MineRenderError(`Anvil ${lightFlagName} must be a byte containing 0 or 1`);
|
|
107207
|
+
}
|
|
107208
|
+
const modernLighting = root.Level?.type !== "compound" || sections.some((section) => section.Palette || section.BlockStates || section.block_states);
|
|
107209
|
+
const lightValid = lightFlag ? lightFlag.value === 1 : modernLighting ? false : void 0;
|
|
107200
107210
|
const chunk = {
|
|
107201
107211
|
x: this.integer(level.xPos, "xPos"),
|
|
107202
107212
|
z: this.integer(level.zPos, "zPos"),
|
|
107203
107213
|
dataVersion,
|
|
107204
|
-
sections: []
|
|
107214
|
+
sections: [],
|
|
107215
|
+
...lightValid !== void 0 ? { lightValid } : {}
|
|
107205
107216
|
};
|
|
107206
107217
|
if ((chunk.x % 32 + 32) % 32 !== location.x || (chunk.z % 32 + 32) % 32 !== location.z) {
|
|
107207
107218
|
throw new MineRenderError("Anvil chunk coordinates do not match its region location");
|
|
@@ -107211,7 +107222,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
107211
107222
|
}
|
|
107212
107223
|
const numericStates = /* @__PURE__ */ new Map();
|
|
107213
107224
|
let legacyMappings;
|
|
107214
|
-
for (const section of
|
|
107225
|
+
for (const section of sections) {
|
|
107215
107226
|
const y5 = this.integer(section.Y, "section Y");
|
|
107216
107227
|
let data2;
|
|
107217
107228
|
if (section.Blocks || section.Data || section.Add) {
|
|
@@ -107241,7 +107252,8 @@ gl_FragDepth=readDepth(vUv);
|
|
|
107241
107252
|
}
|
|
107242
107253
|
if (chunk.sections.some((section2) => section2.y === y5)) throw new MineRenderError(`Duplicate Anvil section Y ${y5}`);
|
|
107243
107254
|
const biomes = this.biomes(section.biomes);
|
|
107244
|
-
|
|
107255
|
+
const light = this.light(section, y5, chunk.lightValid);
|
|
107256
|
+
chunk.sections.push({ y: y5, data: data2, ...biomes ? { biomes } : {}, ...light ? { light } : {} });
|
|
107245
107257
|
}
|
|
107246
107258
|
for (const entry of this.compounds(level.block_entities ?? level.TileEntities, "block entities")) {
|
|
107247
107259
|
const x4 = this.integer(entry.x, "block entity x") - chunk.x * 16;
|
|
@@ -107294,6 +107306,18 @@ gl_FragDepth=readDepth(vUv);
|
|
|
107294
107306
|
return { position: [...position.value.value], nbt: { type: "compound", value } };
|
|
107295
107307
|
});
|
|
107296
107308
|
}
|
|
107309
|
+
static light(section, y5, valid) {
|
|
107310
|
+
const light = {};
|
|
107311
|
+
for (const [name2, channel] of [["BlockLight", "block"], ["SkyLight", "sky"]]) {
|
|
107312
|
+
const tag = section[name2];
|
|
107313
|
+
if (!tag) continue;
|
|
107314
|
+
if (tag.type !== "byteArray" || !Array.isArray(tag.value) || tag.value.length !== 2048) {
|
|
107315
|
+
throw new MineRenderError(`Anvil section ${y5} ${name2} must contain 2048 bytes`);
|
|
107316
|
+
}
|
|
107317
|
+
light[channel] = Uint8Array.from(tag.value);
|
|
107318
|
+
}
|
|
107319
|
+
return light.block || light.sky || valid ? light : void 0;
|
|
107320
|
+
}
|
|
107297
107321
|
static biomes(tag) {
|
|
107298
107322
|
if (!tag) return void 0;
|
|
107299
107323
|
if (tag.type !== "compound") throw new MineRenderError("Anvil biomes must be a compound");
|
|
@@ -107894,12 +107918,48 @@ gl_FragDepth=readDepth(vUv);
|
|
|
107894
107918
|
|
|
107895
107919
|
// src/world/MineRenderWorld.ts
|
|
107896
107920
|
init_FluidQuads();
|
|
107921
|
+
|
|
107922
|
+
// src/world/WorldLight.ts
|
|
107923
|
+
init_dirname();
|
|
107924
|
+
init_buffer2();
|
|
107925
|
+
init_process2();
|
|
107926
|
+
function copySectionLight(light) {
|
|
107927
|
+
const copy = {};
|
|
107928
|
+
for (const channel of ["block", "sky"]) {
|
|
107929
|
+
const bytes = light[channel];
|
|
107930
|
+
if (bytes === void 0) continue;
|
|
107931
|
+
if (!(bytes instanceof Uint8Array) || bytes.length !== 2048) {
|
|
107932
|
+
throw new RangeError(`Section ${channel} light must contain 2048 packed bytes`);
|
|
107933
|
+
}
|
|
107934
|
+
copy[channel] = new Uint8Array(bytes);
|
|
107935
|
+
}
|
|
107936
|
+
return copy;
|
|
107937
|
+
}
|
|
107938
|
+
function sampleSectionLight(light, index) {
|
|
107939
|
+
if (!light) return void 0;
|
|
107940
|
+
const shift = (index & 1) * 4;
|
|
107941
|
+
return {
|
|
107942
|
+
block: (light.block?.[index >> 1] ?? 0) >> shift & 15,
|
|
107943
|
+
sky: (light.sky?.[index >> 1] ?? 0) >> shift & 15
|
|
107944
|
+
};
|
|
107945
|
+
}
|
|
107946
|
+
|
|
107947
|
+
// src/world/MineRenderWorld.ts
|
|
107897
107948
|
var MineRenderWorld = class {
|
|
107898
107949
|
constructor(scene, options = {}) {
|
|
107899
107950
|
this._chunks = /* @__PURE__ */ new Map();
|
|
107900
107951
|
this.biomes = /* @__PURE__ */ new Map();
|
|
107952
|
+
this.light = /* @__PURE__ */ new Map();
|
|
107953
|
+
this.lightValidity = /* @__PURE__ */ new Map();
|
|
107954
|
+
this.highestSkySection = /* @__PURE__ */ new Map();
|
|
107901
107955
|
this.pendingCulling = /* @__PURE__ */ new Map();
|
|
107956
|
+
if (options.savedLighting && !options.sectionMeshing) throw new TypeError("savedLighting requires sectionMeshing");
|
|
107957
|
+
if (options.ambientLight !== void 0 && (!Number.isFinite(options.ambientLight) || options.ambientLight < 0 || options.ambientLight > 1)) {
|
|
107958
|
+
throw new RangeError("ambientLight must be a number from 0 to 1");
|
|
107959
|
+
}
|
|
107902
107960
|
this.scene = scene;
|
|
107961
|
+
this.savedLighting = options.savedLighting ?? false;
|
|
107962
|
+
this.ambientLight = options.ambientLight ?? 0;
|
|
107903
107963
|
if (options.sectionMeshing) this.sectionModels = new SectionModels(options.maxAtlasSize);
|
|
107904
107964
|
if (options.renderEntities) this.entities = new WorldEntities(scene);
|
|
107905
107965
|
}
|
|
@@ -107921,6 +107981,24 @@ gl_FragDepth=readDepth(vUv);
|
|
|
107921
107981
|
const lx = posOrX.x - cx * 16, ly = posOrX.y - cy * 16, lz = posOrX.z - cz * 16;
|
|
107922
107982
|
return this.biomes.get(`${cx}_${cz}`)?.get(cy)?.[Math.floor(lx / 4) + Math.floor(lz / 4) * 4 + Math.floor(ly / 4) * 16];
|
|
107923
107983
|
}
|
|
107984
|
+
getLightAt(posOrX, y5, z4) {
|
|
107985
|
+
if (typeof posOrX === "number") return this.getLightAt(new Vector3(posOrX, y5, z4));
|
|
107986
|
+
if (isTripleArray(posOrX)) return this.getLightAt(new Vector3(...posOrX));
|
|
107987
|
+
this.validatePosBounds(posOrX);
|
|
107988
|
+
const { x: x4, y: py, z: pz } = posOrX;
|
|
107989
|
+
const cx = Math.floor(x4 / 16), cy = Math.floor(py / 16), cz = Math.floor(pz / 16);
|
|
107990
|
+
const key = `${cx}_${cz}`, top = this.highestSkySection.get(key);
|
|
107991
|
+
const sample = sampleSectionLight(this.light.get(key)?.get(cy), (x4 & 15) + (pz & 15) * 16 + (py & 15) * 256);
|
|
107992
|
+
return top !== void 0 && cy > top ? { block: sample?.block ?? 0, sky: 15 } : sample;
|
|
107993
|
+
}
|
|
107994
|
+
lightLevelAt(x4, y5, z4) {
|
|
107995
|
+
const cx = Math.floor(x4 / 16), cy = Math.floor(y5 / 16), cz = Math.floor(z4 / 16), key = `${cx}_${cz}`;
|
|
107996
|
+
if (this.lightValidity.get(key) === false) return 255;
|
|
107997
|
+
const top = this.highestSkySection.get(key);
|
|
107998
|
+
if (top !== void 0 && cy > top) return 15;
|
|
107999
|
+
const sample = sampleSectionLight(this.light.get(key)?.get(cy), (x4 & 15) + (z4 & 15) * 16 + (y5 & 15) * 256);
|
|
108000
|
+
return sample ? Math.max(sample.block, sample.sky) : 255;
|
|
108001
|
+
}
|
|
107924
108002
|
async setBlockAt(posOrX, yOrBlock, z4, block) {
|
|
107925
108003
|
if (typeof posOrX == "number") {
|
|
107926
108004
|
return this.setBlockAt(new Vector3(posOrX, yOrBlock, z4), block);
|
|
@@ -108035,7 +108113,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108035
108113
|
}
|
|
108036
108114
|
}
|
|
108037
108115
|
}
|
|
108038
|
-
/** Replaces a chunk column's blocks and
|
|
108116
|
+
/** Replaces a chunk column's blocks, biomes, and saved light and, with `renderEntities`, its supported saved mobs. */
|
|
108039
108117
|
async placeChunk(chunk, executor) {
|
|
108040
108118
|
if (![chunk.x, chunk.z].every(Number.isSafeInteger)) {
|
|
108041
108119
|
throw new RangeError("Chunk column coordinates must be safe integers");
|
|
@@ -108043,6 +108121,11 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108043
108121
|
if (!chunk.sections.every((section) => Number.isSafeInteger(section.y))) {
|
|
108044
108122
|
throw new RangeError("Chunk section coordinates must be safe integers");
|
|
108045
108123
|
}
|
|
108124
|
+
const lights = /* @__PURE__ */ new Map();
|
|
108125
|
+
for (const section of chunk.sections) {
|
|
108126
|
+
const light = section.light ?? (chunk.lightValid === true ? {} : void 0);
|
|
108127
|
+
if (light) lights.set(section.y, copySectionLight(light));
|
|
108128
|
+
}
|
|
108046
108129
|
this.entities?.clearColumn(chunk.x, chunk.z);
|
|
108047
108130
|
const placeEntities = this.entities?.prepare(chunk.entities, [chunk.x, chunk.z]);
|
|
108048
108131
|
const changes = /* @__PURE__ */ new Map();
|
|
@@ -108058,6 +108141,15 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108058
108141
|
}
|
|
108059
108142
|
try {
|
|
108060
108143
|
await this.clearChunkColumn(chunk.x, chunk.z);
|
|
108144
|
+
const columnKey = `${chunk.x}_${chunk.z}`;
|
|
108145
|
+
if (lights.size) this.light.set(columnKey, lights);
|
|
108146
|
+
for (const [y5, light] of lights) {
|
|
108147
|
+
if (light.sky) this.highestSkySection.set(columnKey, Math.max(y5, this.highestSkySection.get(columnKey) ?? -Infinity));
|
|
108148
|
+
}
|
|
108149
|
+
if (chunk.lightValid !== void 0) this.lightValidity.set(columnKey, chunk.lightValid);
|
|
108150
|
+
if (this.savedLighting) {
|
|
108151
|
+
for (const y5 of lights.keys()) this.markSectionChanged({ x: chunk.x, y: y5, z: chunk.z });
|
|
108152
|
+
}
|
|
108061
108153
|
for (const section of chunk.sections) {
|
|
108062
108154
|
if (section.biomes) {
|
|
108063
108155
|
const position = new Vector3(chunk.x * 16, section.y * 16, chunk.z * 16);
|
|
@@ -108127,6 +108219,12 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108127
108219
|
}
|
|
108128
108220
|
async clearChunkColumn(x4, z4) {
|
|
108129
108221
|
this.biomes.delete(`${x4}_${z4}`);
|
|
108222
|
+
if (this.savedLighting) {
|
|
108223
|
+
for (const y5 of this.light.get(`${x4}_${z4}`)?.keys() ?? []) this.markSectionChanged({ x: x4, y: y5, z: z4 });
|
|
108224
|
+
}
|
|
108225
|
+
this.light.delete(`${x4}_${z4}`);
|
|
108226
|
+
this.lightValidity.delete(`${x4}_${z4}`);
|
|
108227
|
+
this.highestSkySection.delete(`${x4}_${z4}`);
|
|
108130
108228
|
const previous = [...this._chunks.entries()].filter(([, section]) => section.x === x4 && section.z === z4);
|
|
108131
108229
|
for (const [key, section] of previous) {
|
|
108132
108230
|
this._chunks.delete(key);
|
|
@@ -108136,7 +108234,8 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108136
108234
|
}
|
|
108137
108235
|
}
|
|
108138
108236
|
markSectionChanged(chunk) {
|
|
108139
|
-
|
|
108237
|
+
const current = this._chunks.get(`${chunk.x}_${chunk.y}_${chunk.z}`);
|
|
108238
|
+
if (current && current === chunk) this.pendingCulling.set(current, "all");
|
|
108140
108239
|
for (let dy = -1; dy <= 1; dy++) {
|
|
108141
108240
|
for (let dz = -1; dz <= 1; dz++) {
|
|
108142
108241
|
for (let dx = -1; dx <= 1; dx++) {
|
|
@@ -108164,6 +108263,9 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108164
108263
|
const chunks = [...this._chunks.values()];
|
|
108165
108264
|
this._chunks.clear();
|
|
108166
108265
|
this.biomes.clear();
|
|
108266
|
+
this.light.clear();
|
|
108267
|
+
this.lightValidity.clear();
|
|
108268
|
+
this.highestSkySection.clear();
|
|
108167
108269
|
for (const chunk of chunks) {
|
|
108168
108270
|
await chunk.dispose();
|
|
108169
108271
|
}
|
|
@@ -108226,6 +108328,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108226
108328
|
}
|
|
108227
108329
|
}
|
|
108228
108330
|
for (const [index, mask] of masks) await chunk.setCullMaskIndex(index, mask);
|
|
108331
|
+
await chunk.refreshLight(indices === "all" ? void 0 : indices);
|
|
108229
108332
|
}
|
|
108230
108333
|
await Promise.all(batch.map(([chunk]) => chunk.rebuildSectionMesh()));
|
|
108231
108334
|
}
|
|
@@ -108266,7 +108369,23 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108266
108369
|
}
|
|
108267
108370
|
await chunk.refreshBiomes();
|
|
108268
108371
|
await this._chunks.get(`${x4}_${y5 + 1}_${z4}`)?.refreshBiomes();
|
|
108269
|
-
}
|
|
108372
|
+
},
|
|
108373
|
+
this.savedLighting ? (x5, y6, z5) => this.lightLevelAt(x5, y6, z5) : void 0,
|
|
108374
|
+
async () => {
|
|
108375
|
+
if (this._chunks.get(key) !== chunk) return;
|
|
108376
|
+
const columnKey = `${x4}_${z4}`, column = this.light.get(columnKey);
|
|
108377
|
+
if (!column?.delete(y5)) return;
|
|
108378
|
+
if (!column.size) this.light.delete(columnKey);
|
|
108379
|
+
this.highestSkySection.delete(columnKey);
|
|
108380
|
+
for (const [y6, light] of column) {
|
|
108381
|
+
if (light.sky) this.highestSkySection.set(columnKey, Math.max(y6, this.highestSkySection.get(columnKey) ?? -Infinity));
|
|
108382
|
+
}
|
|
108383
|
+
if (this.savedLighting) {
|
|
108384
|
+
this.markSectionChanged(chunk);
|
|
108385
|
+
await this.updateCulling([]);
|
|
108386
|
+
}
|
|
108387
|
+
},
|
|
108388
|
+
this.ambientLight
|
|
108270
108389
|
);
|
|
108271
108390
|
this._chunks.set(key, chunk);
|
|
108272
108391
|
}
|
|
@@ -108321,12 +108440,46 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108321
108440
|
init_buffer2();
|
|
108322
108441
|
init_process2();
|
|
108323
108442
|
init_FluidQuads();
|
|
108443
|
+
|
|
108444
|
+
// src/world/_light/FaceLight.ts
|
|
108445
|
+
init_dirname();
|
|
108446
|
+
init_buffer2();
|
|
108447
|
+
init_process2();
|
|
108448
|
+
function lightBrightness(level, ambient = 0) {
|
|
108449
|
+
if (level === 255) return 1;
|
|
108450
|
+
const curve = level / (60 - 3 * level);
|
|
108451
|
+
return curve + ambient * (1 - curve);
|
|
108452
|
+
}
|
|
108453
|
+
function quadLightIndex(positions, normals, quad) {
|
|
108454
|
+
const start = quad * 12;
|
|
108455
|
+
let axis = 0;
|
|
108456
|
+
if (Math.abs(normals[start + 1]) > Math.abs(normals[start + axis])) axis = 1;
|
|
108457
|
+
if (Math.abs(normals[start + 2]) > Math.abs(normals[start + axis])) axis = 2;
|
|
108458
|
+
const positive2 = normals[start + axis] > 0;
|
|
108459
|
+
const boundary = positive2 ? 8 : -8;
|
|
108460
|
+
for (let vertex2 = 0; vertex2 < 4; vertex2++) {
|
|
108461
|
+
if (Math.abs(positions[start + vertex2 * 3 + axis] - boundary) > 16e-4) return 0;
|
|
108462
|
+
}
|
|
108463
|
+
return axis * 2 + (positive2 ? 1 : 2);
|
|
108464
|
+
}
|
|
108465
|
+
function fluidLightLevel(center, neighbor) {
|
|
108466
|
+
return Math.max(center === 255 ? 15 : center, neighbor === 255 ? 15 : neighbor);
|
|
108467
|
+
}
|
|
108468
|
+
var LIGHT_SAMPLE_OFFSETS = [0, 1, -1, 324, -324, 18, -18];
|
|
108469
|
+
|
|
108470
|
+
// src/world/SectionGeometry.ts
|
|
108324
108471
|
function buildSectionGeometry(input) {
|
|
108325
|
-
const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize, fluids } = input;
|
|
108472
|
+
const { count, indices, templates, cullMasks, templateData, atlases, maxAtlasSize, fluids, light, ambientLight } = input;
|
|
108326
108473
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
108327
108474
|
if (count > indices.length || count > templates.length || count > cullMasks.length) throw new RangeError("Section entry count exceeds its arrays");
|
|
108328
108475
|
if (fluids && fluids.cells.length !== 5832) throw new RangeError("Section fluid cells must cover an 18\xD718\xD718 neighborhood");
|
|
108329
108476
|
if (fluids?.waterTints && fluids.waterTints.length !== 4096 * 3) throw new RangeError("Section water tints must contain RGB for 4096 cells");
|
|
108477
|
+
if (light && (light.length !== 5832 || light.some((level) => level > 15 && level !== 255))) {
|
|
108478
|
+
throw new RangeError("Section light must cover an 18\xD718\xD718 neighborhood with levels from 0 to 15 or 255");
|
|
108479
|
+
}
|
|
108480
|
+
if (ambientLight !== void 0 && (!Number.isFinite(ambientLight) || ambientLight < 0 || ambientLight > 1)) {
|
|
108481
|
+
throw new RangeError("Section ambient light must be a number from 0 to 1");
|
|
108482
|
+
}
|
|
108330
108483
|
for (const template of templateData) {
|
|
108331
108484
|
const { quads } = template;
|
|
108332
108485
|
if (template.positions.length !== quads * 12 || template.normals.length !== quads * 12 || template.uvs.length !== quads * 8 || template.uvBounds.length !== quads * 16 || template.colors.length !== quads * 12 || template.indices.length !== quads * 6 || template.cullFaces.length !== quads) {
|
|
@@ -108431,8 +108584,10 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108431
108584
|
const offsetX = indices[entry] % 16 * 16;
|
|
108432
108585
|
const offsetY = Math.floor(indices[entry] / 256) * 16;
|
|
108433
108586
|
const offsetZ = Math.floor(indices[entry] / 16) % 16 * 16;
|
|
108587
|
+
const lightIndex = (offsetY / 16 + 1) * 324 + (offsetZ / 16 + 1) * 18 + offsetX / 16 + 1;
|
|
108434
108588
|
for (let quad = 0; quad < template.quads; quad++) {
|
|
108435
108589
|
if (cullMasks[entry] & template.cullFaces[quad]) continue;
|
|
108590
|
+
const brightness = light ? lightBrightness(light[lightIndex + LIGHT_SAMPLE_OFFSETS[quadLightIndex(template.positions, template.normals, quad)]], ambientLight) : 1;
|
|
108436
108591
|
const start = vertex2;
|
|
108437
108592
|
for (let corner = 0; corner < 4; corner++, vertex2++) {
|
|
108438
108593
|
const source = quad * 4 + corner;
|
|
@@ -108448,9 +108603,9 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108448
108603
|
uvBounds[vertex2 * 4 + 1] = mapV(template.uvBounds[source * 4 + 1]);
|
|
108449
108604
|
uvBounds[vertex2 * 4 + 2] = mapU(template.uvBounds[source * 4 + 2]);
|
|
108450
108605
|
uvBounds[vertex2 * 4 + 3] = mapV(template.uvBounds[source * 4 + 3]);
|
|
108451
|
-
colors[vertex2 * 3] = template.colors[source * 3];
|
|
108452
|
-
colors[vertex2 * 3 + 1] = template.colors[source * 3 + 1];
|
|
108453
|
-
colors[vertex2 * 3 + 2] = template.colors[source * 3 + 2];
|
|
108606
|
+
colors[vertex2 * 3] = template.colors[source * 3] * brightness;
|
|
108607
|
+
colors[vertex2 * 3 + 1] = template.colors[source * 3 + 1] * brightness;
|
|
108608
|
+
colors[vertex2 * 3 + 2] = template.colors[source * 3 + 2] * brightness;
|
|
108454
108609
|
}
|
|
108455
108610
|
for (let corner = 0; corner < 6; corner++) outputIndices[indexOffset++] = start + template.indices[quad * 6 + corner];
|
|
108456
108611
|
}
|
|
@@ -108460,8 +108615,13 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108460
108615
|
const placement = page.placements[0];
|
|
108461
108616
|
const mapU = (u4) => (placement.x + u4 * atlas.width) / page.width;
|
|
108462
108617
|
const mapV = (v5) => 1 - (placement.y + (1 - v5) * atlas.height) / page.height;
|
|
108618
|
+
const lightIndex = (y5 + 1) * 324 + (z4 + 1) * 18 + x4 + 1;
|
|
108463
108619
|
for (let quad = 0; quad < quads.sprites.length; quad++) {
|
|
108464
108620
|
const rect = quads.sprites[quad] === 0 ? data.still : data.flow;
|
|
108621
|
+
const brightness = light ? lightBrightness(fluidLightLevel(
|
|
108622
|
+
light[lightIndex],
|
|
108623
|
+
light[lightIndex + (quads.normals[quad * 12 + 1] < 0 ? -324 : 324)]
|
|
108624
|
+
), ambientLight) : 1;
|
|
108465
108625
|
const start = vertex2;
|
|
108466
108626
|
for (let corner = 0; corner < 4; corner++, vertex2++) {
|
|
108467
108627
|
const source = quad * 4 + corner;
|
|
@@ -108479,7 +108639,9 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108479
108639
|
mapU((rect[0] + rect[2]) / atlas.width),
|
|
108480
108640
|
mapV(1 - rect[1] / atlas.height)
|
|
108481
108641
|
], vertex2 * 4);
|
|
108482
|
-
colors
|
|
108642
|
+
colors[vertex2 * 3] = tint[0] * brightness;
|
|
108643
|
+
colors[vertex2 * 3 + 1] = tint[1] * brightness;
|
|
108644
|
+
colors[vertex2 * 3 + 2] = tint[2] * brightness;
|
|
108483
108645
|
}
|
|
108484
108646
|
outputIndices.set([start, start + 1, start + 2, start, start + 2, start + 3], indexOffset);
|
|
108485
108647
|
indexOffset += 6;
|
|
@@ -108550,7 +108712,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108550
108712
|
// src/world/SectionMesh.ts
|
|
108551
108713
|
var templateCache = /* @__PURE__ */ new WeakMap();
|
|
108552
108714
|
var WATER_TINT = new Color(4159204).toArray();
|
|
108553
|
-
function toInput(entries, maxAtlasSize, fluids) {
|
|
108715
|
+
function toInput(entries, maxAtlasSize, fluids, lighting) {
|
|
108554
108716
|
if (!Number.isInteger(maxAtlasSize) || maxAtlasSize < 1) throw new RangeError("Section atlas size must be a positive integer");
|
|
108555
108717
|
const atlases = [];
|
|
108556
108718
|
const atlasIds = /* @__PURE__ */ new Map();
|
|
@@ -108562,7 +108724,8 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108562
108724
|
cullMasks: new Uint8Array(entries.length),
|
|
108563
108725
|
templateData: [],
|
|
108564
108726
|
atlases: [],
|
|
108565
|
-
maxAtlasSize
|
|
108727
|
+
maxAtlasSize,
|
|
108728
|
+
...lighting
|
|
108566
108729
|
};
|
|
108567
108730
|
for (let i4 = 0; i4 < entries.length; i4++) {
|
|
108568
108731
|
const { index, template, cullMask } = entries[i4];
|
|
@@ -108650,13 +108813,13 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108650
108813
|
this.ownedMeshes = [];
|
|
108651
108814
|
}
|
|
108652
108815
|
/** Builds section-local meshes from visible quads. `maxAtlasSize` limits each atlas dimension in pixels. */
|
|
108653
|
-
static build(entries, maxAtlasSize = 2048, fluids) {
|
|
108654
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids);
|
|
108816
|
+
static build(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
108817
|
+
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
108655
108818
|
return this.fromPages(buildSectionGeometry(input), atlases);
|
|
108656
108819
|
}
|
|
108657
108820
|
/** Builds section-local meshes in a browser worker when available, with synchronous fallback. */
|
|
108658
|
-
static async buildAsync(entries, maxAtlasSize = 2048, fluids) {
|
|
108659
|
-
const { input, atlases } = toInput(entries, maxAtlasSize, fluids);
|
|
108821
|
+
static async buildAsync(entries, maxAtlasSize = 2048, fluids, lighting) {
|
|
108822
|
+
const { input, atlases } = toInput(entries, maxAtlasSize, fluids, lighting);
|
|
108660
108823
|
const worker = SectionWorker.shared();
|
|
108661
108824
|
const pages = worker ? await worker.build(input).catch(() => buildSectionGeometry(input)) : buildSectionGeometry(input);
|
|
108662
108825
|
return this.fromPages(pages, atlases);
|
|
@@ -108726,12 +108889,15 @@ gl_FragDepth=readDepth(vUv);
|
|
|
108726
108889
|
init_CubeFace();
|
|
108727
108890
|
var WATER_TINT2 = new Color(4159204).toArray();
|
|
108728
108891
|
var Chunk = class _Chunk {
|
|
108729
|
-
constructor(scene, x4, y5, z4, onBlocksChanged, sectionModels, neighborCell, biomeAt, onBiomesChanged) {
|
|
108892
|
+
constructor(scene, x4, y5, z4, onBlocksChanged, sectionModels, neighborCell, biomeAt, onBiomesChanged, lightAt, onLightCleared, ambientLight = 0) {
|
|
108730
108893
|
this.onBlocksChanged = onBlocksChanged;
|
|
108731
108894
|
this.sectionModels = sectionModels;
|
|
108732
108895
|
this.neighborCell = neighborCell;
|
|
108733
108896
|
this.biomeAt = biomeAt;
|
|
108734
108897
|
this.onBiomesChanged = onBiomesChanged;
|
|
108898
|
+
this.lightAt = lightAt;
|
|
108899
|
+
this.onLightCleared = onLightCleared;
|
|
108900
|
+
this.ambientLight = ambientLight;
|
|
108735
108901
|
this.data = new ChunkData();
|
|
108736
108902
|
this.renderedBlocks = /* @__PURE__ */ new Map();
|
|
108737
108903
|
this.sectionBlocks = /* @__PURE__ */ new Map();
|
|
@@ -109013,6 +109179,13 @@ gl_FragDepth=readDepth(vUv);
|
|
|
109013
109179
|
positionAt(index) {
|
|
109014
109180
|
return [this.x * 16 + index % 16, this.y * 16 + Math.floor(index / 256), this.z * 16 + Math.floor(index / 16) % 16];
|
|
109015
109181
|
}
|
|
109182
|
+
/** Refreshes saved lighting after adjacent columns load or unload, including columns with only light data. */
|
|
109183
|
+
async refreshLight(indices) {
|
|
109184
|
+
if (!this.lightAt) return;
|
|
109185
|
+
for (const index of indices ?? this.renderedBlocks.keys()) {
|
|
109186
|
+
if (this.renderedBlocks.has(index)) this.meshDirty = true;
|
|
109187
|
+
}
|
|
109188
|
+
}
|
|
109016
109189
|
biomePosition(index, blockState3, stored) {
|
|
109017
109190
|
const position = this.positionAt(index), name2 = blockState3.key?.toNamespacedString();
|
|
109018
109191
|
if (stored.properties?.half === "upper" && (name2 === "minecraft:tall_grass" || name2 === "minecraft:large_fern")) position[1]--;
|
|
@@ -109190,7 +109363,23 @@ gl_FragDepth=readDepth(vUv);
|
|
|
109190
109363
|
fluids[kind] = await this.sectionModels.fluidAtlas(kind, state?.key?.root);
|
|
109191
109364
|
}
|
|
109192
109365
|
}
|
|
109193
|
-
|
|
109366
|
+
let light;
|
|
109367
|
+
if (this.lightAt) {
|
|
109368
|
+
light = new Uint8Array(18 * 18 * 18);
|
|
109369
|
+
for (let y5 = -1; y5 <= 16; y5++) {
|
|
109370
|
+
for (let z4 = -1; z4 <= 16; z4++) {
|
|
109371
|
+
for (let x4 = -1; x4 <= 16; x4++) {
|
|
109372
|
+
light[(y5 + 1) * 324 + (z4 + 1) * 18 + x4 + 1] = this.lightAt(this.x * 16 + x4, this.y * 16 + y5, this.z * 16 + z4);
|
|
109373
|
+
}
|
|
109374
|
+
}
|
|
109375
|
+
}
|
|
109376
|
+
}
|
|
109377
|
+
const next = entries.length || fluids ? await SectionMesh.buildAsync(
|
|
109378
|
+
entries,
|
|
109379
|
+
this.sectionModels.maxAtlasSize,
|
|
109380
|
+
fluids,
|
|
109381
|
+
light ? { light, ambientLight: this.ambientLight } : void 0
|
|
109382
|
+
) : void 0;
|
|
109194
109383
|
if (generation !== this.meshGeneration) {
|
|
109195
109384
|
next?.dispose();
|
|
109196
109385
|
return;
|
|
@@ -109222,6 +109411,7 @@ gl_FragDepth=readDepth(vUv);
|
|
|
109222
109411
|
this.biomes = void 0;
|
|
109223
109412
|
if (notify) {
|
|
109224
109413
|
await this.onBiomesChanged?.(void 0);
|
|
109414
|
+
await this.onLightCleared?.();
|
|
109225
109415
|
await this.onBlocksChanged?.(positions);
|
|
109226
109416
|
}
|
|
109227
109417
|
}
|