minerender 2.1.0-beta.6 → 2.1.0-beta.8
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/README.md +10 -1
- package/dist/browser/esm/Materials.mjs +3 -1
- package/dist/browser/esm/Materials.mjs.map +1 -1
- package/dist/browser/esm/Ticker.mjs +3 -1
- package/dist/browser/esm/Ticker.mjs.map +1 -1
- package/dist/browser/esm/UVMapper.mjs +9 -9
- package/dist/browser/esm/UVMapper.mjs.map +1 -1
- package/dist/browser/esm/armor/Armor.mjs +84 -0
- package/dist/browser/esm/armor/Armor.mjs.map +1 -0
- package/dist/browser/esm/armor/index.mjs +3 -0
- package/dist/browser/esm/armor/index.mjs.map +1 -0
- package/dist/browser/esm/assets/AssetDefaults.mjs +8 -0
- package/dist/browser/esm/assets/AssetDefaults.mjs.map +1 -0
- package/dist/browser/esm/assets/AssetKey.mjs +1 -1
- package/dist/browser/esm/assets/AssetKey.mjs.map +1 -1
- package/dist/browser/esm/assets/AssetLoader.mjs +5 -5
- package/dist/browser/esm/assets/AssetLoader.mjs.map +1 -1
- package/dist/browser/esm/assets/Assets.mjs +1 -5
- package/dist/browser/esm/assets/Assets.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockEntities.mjs +5 -1
- package/dist/browser/esm/assets/BlockEntities.mjs.map +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs +1 -1
- package/dist/browser/esm/assets/BlockStates.mjs.map +1 -1
- package/dist/browser/esm/assets/Entities.mjs +40 -12
- package/dist/browser/esm/assets/Entities.mjs.map +1 -1
- package/dist/browser/esm/assets/MineRenderData.mjs +8 -17
- package/dist/browser/esm/assets/MineRenderData.mjs.map +1 -1
- package/dist/browser/esm/assets/ModelTextures.mjs +13 -7
- package/dist/browser/esm/assets/ModelTextures.mjs.map +1 -1
- package/dist/browser/esm/assets/Models.mjs +1 -1
- package/dist/browser/esm/assets/Models.mjs.map +1 -1
- package/dist/browser/esm/assets/_fonts/Unihex.mjs +5 -3
- package/dist/browser/esm/assets/_fonts/Unihex.mjs.map +1 -1
- package/dist/browser/esm/assets/_versions/DatasetVersions.mjs +22 -0
- package/dist/browser/esm/assets/_versions/DatasetVersions.mjs.map +1 -0
- package/dist/browser/esm/assets/index.mjs +1 -0
- package/dist/browser/esm/assets/index.mjs.map +1 -1
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs +7 -8
- package/dist/browser/esm/assets/source/HostedAssetSource.mjs.map +1 -1
- package/dist/browser/esm/cache/Caching.mjs +8 -0
- package/dist/browser/esm/cache/Caching.mjs.map +1 -1
- package/dist/browser/esm/entity/scene/EntityObject.mjs +31 -5
- package/dist/browser/esm/entity/scene/EntityObject.mjs.map +1 -1
- package/dist/browser/esm/env/browser/BrowserCache.mjs +3 -3
- package/dist/browser/esm/env/browser/BrowserCache.mjs.map +1 -1
- package/dist/browser/esm/env/browser/BrowserEnv.mjs +11 -4
- package/dist/browser/esm/env/browser/BrowserEnv.mjs.map +1 -1
- package/dist/browser/esm/image/ImageLoader.mjs +3 -3
- package/dist/browser/esm/image/ImageLoader.mjs.map +1 -1
- package/dist/browser/esm/index.browser.d.mts +191 -22
- package/dist/browser/esm/index.browser.mjs.map +1 -1
- package/dist/browser/esm/index.mjs +1 -0
- package/dist/browser/esm/index.mjs.map +1 -1
- package/dist/browser/esm/inspector/SceneInspector.mjs +3 -3
- package/dist/browser/esm/inspector/SceneInspector.mjs.map +1 -1
- package/dist/browser/esm/instance/InstanceManager.mjs +4 -4
- package/dist/browser/esm/instance/InstanceManager.mjs.map +1 -1
- package/dist/browser/esm/model/ItemGlint.mjs +7 -6
- package/dist/browser/esm/model/ItemGlint.mjs.map +1 -1
- package/dist/browser/esm/model/block/scene/BlockObject.mjs +19 -6
- package/dist/browser/esm/model/block/scene/BlockObject.mjs.map +1 -1
- package/dist/browser/esm/model/multiblock/StructureParser.mjs +7 -4
- package/dist/browser/esm/model/multiblock/StructureParser.mjs.map +1 -1
- package/dist/browser/esm/model/scene/ModelObject.mjs +4 -4
- package/dist/browser/esm/model/scene/ModelObject.mjs.map +1 -1
- package/dist/browser/esm/nbt/NBTHelper.mjs +5 -2
- package/dist/browser/esm/nbt/NBTHelper.mjs.map +1 -1
- package/dist/browser/esm/renderer/Renderer.mjs +4 -2
- package/dist/browser/esm/renderer/Renderer.mjs.map +1 -1
- package/dist/browser/esm/renderer/SceneObject.mjs +0 -6
- package/dist/browser/esm/renderer/SceneObject.mjs.map +1 -1
- package/dist/browser/esm/request/Requests.mjs +3 -3
- package/dist/browser/esm/request/Requests.mjs.map +1 -1
- package/dist/browser/esm/scene/SceneDocument.mjs +35 -5
- package/dist/browser/esm/scene/SceneDocument.mjs.map +1 -1
- package/dist/browser/esm/scene/SceneDocumentLoader.mjs +14 -3
- package/dist/browser/esm/scene/SceneDocumentLoader.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinGeometries.mjs +4 -1
- package/dist/browser/esm/skin/SkinGeometries.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinPart.mjs +2 -0
- package/dist/browser/esm/skin/SkinPart.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinTextureCoordinates.mjs +11 -1
- package/dist/browser/esm/skin/SkinTextureCoordinates.mjs.map +1 -1
- package/dist/browser/esm/skin/SkinTextures.mjs +1 -1
- package/dist/browser/esm/skin/SkinTextures.mjs.map +1 -1
- package/dist/browser/esm/skin/Skins.mjs +6 -4
- package/dist/browser/esm/skin/Skins.mjs.map +1 -1
- package/dist/browser/esm/skin/scene/SkinObject.mjs +119 -7
- package/dist/browser/esm/skin/scene/SkinObject.mjs.map +1 -1
- package/dist/browser/esm/texture/PalettedTextures.mjs +46 -0
- package/dist/browser/esm/texture/PalettedTextures.mjs.map +1 -0
- package/dist/browser/esm/texture/TextureLoader.mjs +4 -2
- package/dist/browser/esm/texture/TextureLoader.mjs.map +1 -1
- package/dist/browser/esm/texture/index.mjs +1 -0
- package/dist/browser/esm/texture/index.mjs.map +1 -1
- package/dist/browser/esm/util/log.mjs +75 -0
- package/dist/browser/esm/util/log.mjs.map +1 -1
- package/dist/browser/esm/util/performance.mjs.map +1 -1
- package/dist/browser/esm/util/util.mjs +0 -2
- package/dist/browser/esm/util/util.mjs.map +1 -1
- package/dist/browser/esm/world/Chunk.mjs +70 -38
- package/dist/browser/esm/world/Chunk.mjs.map +1 -1
- package/dist/browser/esm/world/MineRenderWorld.mjs +187 -60
- package/dist/browser/esm/world/MineRenderWorld.mjs.map +1 -1
- package/dist/browser/esm/world/SectionMesh.mjs +65 -9
- package/dist/browser/esm/world/SectionMesh.mjs.map +1 -1
- package/dist/browser/esm/world/SectionModels.mjs +21 -15
- package/dist/browser/esm/world/SectionModels.mjs.map +1 -1
- package/dist/browser/esm/world/SectionWorker.mjs +8 -2
- package/dist/browser/esm/world/SectionWorker.mjs.map +1 -1
- package/dist/browser/esm/world/WorldStreamer.mjs +129 -34
- package/dist/browser/esm/world/WorldStreamer.mjs.map +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs +1 -1
- package/dist/browser/esm/world/_culling/BlockCulling.mjs.map +1 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs +3 -1
- package/dist/browser/esm/world/_entities/WorldEntities.mjs.map +1 -1
- package/dist/browser/index.d.ts +191 -22
- package/dist/browser/index.js +4461 -3648
- package/dist/browser/index.js.map +1 -1
- package/dist/bundle.js +13482 -12651
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +179 -21
- package/dist/node/index.d.ts +179 -21
- package/dist/node/index.js +4495 -3666
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +4412 -3586
- package/dist/node/index.mjs.map +1 -1
- package/package.json +2 -1
|
@@ -3,8 +3,10 @@ import { Vector3 } from "three";
|
|
|
3
3
|
import { isTripleArray } from "../model/Model.mjs";
|
|
4
4
|
import { yieldToEventLoop } from "../util/util.mjs";
|
|
5
5
|
import { Chunk } from "./Chunk.mjs";
|
|
6
|
+
import { ChunkData } from "./ChunkData.mjs";
|
|
6
7
|
import { AssetKey } from "../assets/AssetKey.mjs";
|
|
7
8
|
import { BlockStates } from "../assets/BlockStates.mjs";
|
|
9
|
+
import { BlockEntities } from "../assets/BlockEntities.mjs";
|
|
8
10
|
import { CUBE_FACE_OFFSETS } from "../CubeFace.mjs";
|
|
9
11
|
import { SectionModels } from "./SectionModels.mjs";
|
|
10
12
|
import { WorldEntities } from "./_entities/WorldEntities.mjs";
|
|
@@ -12,6 +14,9 @@ import { fluidKindOf } from "../model/fluid/FluidQuads.mjs";
|
|
|
12
14
|
import { BiomeBlend, validateBiomeBlendRadius } from "./_biomes/BiomeBlend.mjs";
|
|
13
15
|
import { copySectionLight, sampleSectionLight } from "./WorldLight.mjs";
|
|
14
16
|
import { loadBlockCulling } from "./_culling/BlockCulling.mjs";
|
|
17
|
+
import { logger } from "../util/log.mjs";
|
|
18
|
+
var log = logger("MineRenderWorld");
|
|
19
|
+
var YIELD_INTERVAL_MS = 8;
|
|
15
20
|
var MineRenderWorld = class {
|
|
16
21
|
constructor(scene, options = {}) {
|
|
17
22
|
this._chunks = /* @__PURE__ */ new Map();
|
|
@@ -101,8 +106,14 @@ var MineRenderWorld = class {
|
|
|
101
106
|
}
|
|
102
107
|
return queued;
|
|
103
108
|
}
|
|
104
|
-
async refreshBiomes() {
|
|
105
|
-
if (this.biomeRefreshing)
|
|
109
|
+
async refreshBiomes(deferCulling = false) {
|
|
110
|
+
if (this.biomeRefreshing) {
|
|
111
|
+
await this.biomeRefreshing;
|
|
112
|
+
if (!deferCulling) {
|
|
113
|
+
if (this.pendingCulling.size) await this.updateCulling([]);
|
|
114
|
+
else await this.culling;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
106
117
|
if (!this.pendingBiomes.size) return /* @__PURE__ */ new Map();
|
|
107
118
|
return this.biomeRefreshing ?? (this.biomeRefreshing = Promise.resolve().then(async () => {
|
|
108
119
|
const failures = /* @__PURE__ */ new Map();
|
|
@@ -114,12 +125,12 @@ var MineRenderWorld = class {
|
|
|
114
125
|
this.pendingBiomes.delete(chunk);
|
|
115
126
|
if (this._chunks.get(`${chunk.x}_${chunk.y}_${chunk.z}`) !== chunk) continue;
|
|
116
127
|
try {
|
|
117
|
-
await chunk.refreshBiomes(columns);
|
|
128
|
+
await chunk.refreshBiomes(columns, deferCulling);
|
|
118
129
|
} catch (error) {
|
|
119
130
|
failures.set(chunk, error);
|
|
120
131
|
if (this._chunks.get(`${chunk.x}_${chunk.y}_${chunk.z}`) === chunk) this.pendingBiomes.set(chunk, void 0);
|
|
121
132
|
}
|
|
122
|
-
if (performance.now() - sliceStart >
|
|
133
|
+
if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
|
|
123
134
|
await yieldToEventLoop();
|
|
124
135
|
sliceStart = performance.now();
|
|
125
136
|
}
|
|
@@ -220,15 +231,18 @@ var MineRenderWorld = class {
|
|
|
220
231
|
const key = AssetKey.parse("blockstates", block.type);
|
|
221
232
|
keys.set(key.serialize(), key);
|
|
222
233
|
}
|
|
223
|
-
await BlockStates.getAll(keys.values());
|
|
234
|
+
const loaded = await BlockStates.getAll(keys.values());
|
|
235
|
+
const states = new Map([...keys.keys()].map((key, i) => [key, loaded[i]]));
|
|
224
236
|
if (!useBatches) {
|
|
225
237
|
for (const block of multiblock.blocks) await place(block);
|
|
226
238
|
return;
|
|
227
239
|
}
|
|
228
240
|
if (!executor) {
|
|
229
241
|
const groups2 = /* @__PURE__ */ new Map();
|
|
242
|
+
const distinct = /* @__PURE__ */ new Map();
|
|
230
243
|
const position = new Vector3();
|
|
231
244
|
for (const block of multiblock.blocks) {
|
|
245
|
+
if (this.sectionModels && !Chunk.isAir(block)) distinct.set(ChunkData.paletteKey(block), block);
|
|
232
246
|
const [x, y, z] = block.position;
|
|
233
247
|
this.validatePosBounds(position.set(x, y, z));
|
|
234
248
|
const cx = Math.floor(x / 16), cy = Math.floor(y / 16), cz = Math.floor(z / 16);
|
|
@@ -239,6 +253,16 @@ var MineRenderWorld = class {
|
|
|
239
253
|
if (!group) groups2.set(chunk, group = []);
|
|
240
254
|
group.push({ index: (y - cy * 16) * 256 + (z - cz * 16) * 16 + x - cx * 16, block });
|
|
241
255
|
}
|
|
256
|
+
if (this.sectionModels) {
|
|
257
|
+
for (const block of distinct.values()) {
|
|
258
|
+
const state = states.get(AssetKey.parse("blockstates", block.type).serialize());
|
|
259
|
+
if (!state) continue;
|
|
260
|
+
void (async () => {
|
|
261
|
+
if (state.key && BlockEntities.entry(await BlockEntities.getIndex(state.key.root), state.key.toNamespacedString())) return;
|
|
262
|
+
await this.sectionModels.preload(state, block.properties);
|
|
263
|
+
})().catch(() => void 0);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
242
266
|
await this.placeChunkGroups(groups2, changes);
|
|
243
267
|
return;
|
|
244
268
|
}
|
|
@@ -274,7 +298,7 @@ var MineRenderWorld = class {
|
|
|
274
298
|
)));
|
|
275
299
|
for (const pos of positions) changes.set(`${pos.x},${pos.y},${pos.z}`, pos);
|
|
276
300
|
}
|
|
277
|
-
if (performance.now() - sliceStart >
|
|
301
|
+
if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
|
|
278
302
|
await yieldToEventLoop();
|
|
279
303
|
sliceStart = performance.now();
|
|
280
304
|
}
|
|
@@ -282,6 +306,62 @@ var MineRenderWorld = class {
|
|
|
282
306
|
}
|
|
283
307
|
/** Replaces a chunk column's blocks, biomes, and saved light and, with `renderEntities`, its supported saved mobs. */
|
|
284
308
|
async placeChunk(chunk, executor) {
|
|
309
|
+
return this.placeColumn(chunk, executor);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Replaces parsed columns in input order, then refreshes neighboring geometry once.
|
|
313
|
+
* Duplicate coordinates retain their order. A failed column stops placement; queued refreshes finish before rejection.
|
|
314
|
+
*/
|
|
315
|
+
async placeChunks(chunks) {
|
|
316
|
+
const columns = [];
|
|
317
|
+
for (const chunk of chunks) {
|
|
318
|
+
const { x, z } = chunk ?? {};
|
|
319
|
+
if (![x, z].every(Number.isSafeInteger)) {
|
|
320
|
+
throw new RangeError("Chunk column coordinates must be safe integers");
|
|
321
|
+
}
|
|
322
|
+
const sections = Array.from(chunk.sections, (section) => {
|
|
323
|
+
const { y } = section ?? {};
|
|
324
|
+
if (!Number.isSafeInteger(y)) throw new RangeError("Chunk section coordinates must be safe integers");
|
|
325
|
+
return { ...section, y };
|
|
326
|
+
});
|
|
327
|
+
columns.push({ ...chunk, x, z, sections });
|
|
328
|
+
}
|
|
329
|
+
if (!columns.length) return;
|
|
330
|
+
await this.culling;
|
|
331
|
+
let failed = false, failure, sliceStart = performance.now();
|
|
332
|
+
try {
|
|
333
|
+
for (const column of columns) {
|
|
334
|
+
await this.placeColumn(column, void 0, true);
|
|
335
|
+
if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
|
|
336
|
+
await yieldToEventLoop();
|
|
337
|
+
sliceStart = performance.now();
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
} catch (error) {
|
|
341
|
+
failed = true;
|
|
342
|
+
failure = error;
|
|
343
|
+
} finally {
|
|
344
|
+
try {
|
|
345
|
+
const failures = await this.refreshBiomes(true);
|
|
346
|
+
if (failures.size) log.warn("Failed to refresh biome colors", failures.values().next().value);
|
|
347
|
+
} catch (error) {
|
|
348
|
+
if (!failed) {
|
|
349
|
+
failed = true;
|
|
350
|
+
failure = error;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
try {
|
|
354
|
+
await this.updateCulling([]);
|
|
355
|
+
} catch (error) {
|
|
356
|
+
if (!failed) {
|
|
357
|
+
failed = true;
|
|
358
|
+
failure = error;
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
if (failed) throw failure;
|
|
363
|
+
}
|
|
364
|
+
async placeColumn(chunk, executor, deferCulling = false) {
|
|
285
365
|
if (![chunk.x, chunk.z].every(Number.isSafeInteger)) {
|
|
286
366
|
throw new RangeError("Chunk column coordinates must be safe integers");
|
|
287
367
|
}
|
|
@@ -343,7 +423,7 @@ var MineRenderWorld = class {
|
|
|
343
423
|
} finally {
|
|
344
424
|
this.markSectionChanged(target);
|
|
345
425
|
}
|
|
346
|
-
if (performance.now() - sliceStart >
|
|
426
|
+
if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
|
|
347
427
|
await yieldToEventLoop();
|
|
348
428
|
sliceStart = performance.now();
|
|
349
429
|
}
|
|
@@ -366,9 +446,12 @@ var MineRenderWorld = class {
|
|
|
366
446
|
await placeEntities?.();
|
|
367
447
|
} finally {
|
|
368
448
|
this.markBiomesChanged(chunk.x, chunk.z, void 0, false);
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
449
|
+
if (deferCulling) await this.updateCulling([...changes.values()], true);
|
|
450
|
+
else {
|
|
451
|
+
const failures = await this.refreshBiomes();
|
|
452
|
+
if (failures.size) log.warn("Failed to refresh biome colors", failures.values().next().value);
|
|
453
|
+
await this.updateCulling([...changes.values()]);
|
|
454
|
+
}
|
|
372
455
|
}
|
|
373
456
|
}
|
|
374
457
|
/**
|
|
@@ -376,16 +459,36 @@ var MineRenderWorld = class {
|
|
|
376
459
|
* Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.
|
|
377
460
|
*/
|
|
378
461
|
async unloadChunkColumn(x, z) {
|
|
379
|
-
|
|
380
|
-
|
|
462
|
+
return this.unloadChunkColumns([{ x, z }]);
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Removes chunk columns together and refreshes surviving neighbors once.
|
|
466
|
+
* Coordinates are absolute chunk columns. Duplicate and missing columns are ignored.
|
|
467
|
+
*/
|
|
468
|
+
async unloadChunkColumns(positions) {
|
|
469
|
+
const columns = /* @__PURE__ */ new Map();
|
|
470
|
+
for (const position of positions) {
|
|
471
|
+
const { x, z } = position ?? {};
|
|
472
|
+
if (!Number.isInteger(x) || !Number.isInteger(z)) {
|
|
473
|
+
throw new RangeError("Chunk column coordinates must be integers");
|
|
474
|
+
}
|
|
475
|
+
columns.set(`${x}_${z}`, { x, z });
|
|
381
476
|
}
|
|
382
|
-
|
|
477
|
+
if (!columns.size) return;
|
|
383
478
|
await this.culling;
|
|
479
|
+
let sliceStart = performance.now();
|
|
384
480
|
try {
|
|
385
|
-
|
|
481
|
+
for (const { x, z } of columns.values()) {
|
|
482
|
+
this.entities?.clearColumn(x, z);
|
|
483
|
+
await this.clearChunkColumn(x, z);
|
|
484
|
+
if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
|
|
485
|
+
await yieldToEventLoop();
|
|
486
|
+
sliceStart = performance.now();
|
|
487
|
+
}
|
|
488
|
+
}
|
|
386
489
|
} finally {
|
|
387
|
-
const failures = await this.refreshBiomes();
|
|
388
|
-
if (failures.size)
|
|
490
|
+
const failures = await this.refreshBiomes(true);
|
|
491
|
+
if (failures.size) log.warn("Failed to refresh biome colors", failures.values().next().value);
|
|
389
492
|
await this.updateCulling([]);
|
|
390
493
|
}
|
|
391
494
|
}
|
|
@@ -447,7 +550,7 @@ var MineRenderWorld = class {
|
|
|
447
550
|
}
|
|
448
551
|
this.sectionModels?.clear();
|
|
449
552
|
}
|
|
450
|
-
updateCulling(positions) {
|
|
553
|
+
updateCulling(positions, defer = false) {
|
|
451
554
|
const neighbor = new Vector3();
|
|
452
555
|
for (const pos of positions) {
|
|
453
556
|
const cx = Math.floor(pos.x / 16), cy = Math.floor(pos.y / 16), cz = Math.floor(pos.z / 16);
|
|
@@ -469,58 +572,82 @@ var MineRenderWorld = class {
|
|
|
469
572
|
}
|
|
470
573
|
}
|
|
471
574
|
}
|
|
575
|
+
if (defer) return Promise.resolve();
|
|
472
576
|
return this.culling ?? (this.culling = Promise.resolve().then(async () => {
|
|
473
577
|
let sliceStart = performance.now();
|
|
474
578
|
try {
|
|
475
579
|
const culling = await loadBlockCulling();
|
|
476
580
|
while (this.pendingCulling.size) {
|
|
477
|
-
const batch =
|
|
581
|
+
const batch = new Map(this.pendingCulling);
|
|
478
582
|
this.pendingCulling.clear();
|
|
479
|
-
|
|
480
|
-
const
|
|
481
|
-
|
|
482
|
-
const
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
const
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
583
|
+
try {
|
|
584
|
+
for (const [chunk, indices] of batch) {
|
|
585
|
+
const neighbors = CUBE_FACE_OFFSETS.map(([x, y, z]) => this._chunks.get(`${chunk.x + x}_${chunk.y + y}_${chunk.z + z}`));
|
|
586
|
+
const neighborAt = (x, y, z) => {
|
|
587
|
+
const lx = x - chunk.x * 16, ly = y - chunk.y * 16, lz = z - chunk.z * 16;
|
|
588
|
+
const section = neighbors[lx >= 16 ? 0 : lx < 0 ? 1 : ly >= 16 ? 2 : ly < 0 ? 3 : lz >= 16 ? 4 : 5];
|
|
589
|
+
return [section, (ly & 15) * 256 + (lz & 15) * 16 + (lx & 15)];
|
|
590
|
+
};
|
|
591
|
+
const masks = chunk.updateCullMasks(indices === "all" ? void 0 : indices, (x, y, z) => {
|
|
592
|
+
const [section, i] = neighborAt(x, y, z);
|
|
593
|
+
return section?.isOccludingIndex(i) ?? false;
|
|
594
|
+
}, culling, (x, y, z) => {
|
|
595
|
+
const [section, i] = neighborAt(x, y, z);
|
|
596
|
+
return section?.visibleBlockIndex(i);
|
|
597
|
+
});
|
|
598
|
+
const fluidIndices = indices === "all" ? function* () {
|
|
599
|
+
for (let index = 0; index < 4096; index++) yield index;
|
|
600
|
+
}() : indices;
|
|
601
|
+
for (const index of fluidIndices) {
|
|
602
|
+
if (!chunk.fluidByteIndex(index) || !chunk.isBlockVisibleIndex(index)) continue;
|
|
603
|
+
const lx = index % 16, ly = Math.floor(index / 256), lz = Math.floor(index / 16) % 16;
|
|
604
|
+
const wx = chunk.x * 16 + lx, wy = chunk.y * 16 + ly, wz = chunk.z * 16 + lz;
|
|
605
|
+
const block = chunk.getBlockAt(neighbor.set(wx, wy, wz));
|
|
606
|
+
if (block.object?.fluidKind) {
|
|
607
|
+
await block.object.updateFluid((x, y, z) => {
|
|
608
|
+
const nx = lx + x, ny = ly + y, nz = lz + z;
|
|
609
|
+
const section = nx >= 0 && nx < 16 && ny >= 0 && ny < 16 && nz >= 0 && nz < 16 ? chunk : this._chunks.get(`${chunk.x + Math.floor(nx / 16)}_${chunk.y + Math.floor(ny / 16)}_${chunk.z + Math.floor(nz / 16)}`);
|
|
610
|
+
const neighborIndex = (ny & 15) * 256 + (nz & 15) * 16 + (nx & 15);
|
|
611
|
+
const byte = section?.fluidByteIndex(neighborIndex) ?? 0;
|
|
612
|
+
return {
|
|
613
|
+
fluid: fluidKindOf(byte),
|
|
614
|
+
level: byte & 15,
|
|
615
|
+
solid: section?.isOccludingIndex(neighborIndex) ?? false
|
|
616
|
+
};
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
for (const [index, mask] of masks) await chunk.setCullMaskIndex(index, mask);
|
|
621
|
+
await chunk.refreshLight(indices === "all" ? void 0 : indices);
|
|
622
|
+
chunk.refreshAmbientOcclusion(this._ambientOcclusion);
|
|
623
|
+
if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
|
|
624
|
+
await yieldToEventLoop();
|
|
625
|
+
sliceStart = performance.now();
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
const pending = [];
|
|
629
|
+
for (const chunk of [...batch.keys()]) {
|
|
630
|
+
const build = (async () => {
|
|
631
|
+
await chunk.rebuildSectionMesh();
|
|
632
|
+
batch.delete(chunk);
|
|
633
|
+
})();
|
|
634
|
+
void build.catch(() => void 0);
|
|
635
|
+
pending.push(build);
|
|
636
|
+
if (performance.now() - sliceStart > YIELD_INTERVAL_MS) {
|
|
637
|
+
await yieldToEventLoop();
|
|
638
|
+
sliceStart = performance.now();
|
|
513
639
|
}
|
|
514
640
|
}
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
641
|
+
const builds = await Promise.allSettled(pending);
|
|
642
|
+
const failure = builds.find((result) => result.status === "rejected");
|
|
643
|
+
if (failure?.status === "rejected") throw failure.reason;
|
|
644
|
+
} catch (error) {
|
|
645
|
+
for (const [chunk, indices] of batch) {
|
|
646
|
+
const pending = this.pendingCulling.get(chunk);
|
|
647
|
+
this.pendingCulling.set(chunk, indices === "all" || pending === "all" ? "all" : /* @__PURE__ */ new Set([...indices, ...pending ?? []]));
|
|
521
648
|
}
|
|
649
|
+
throw error;
|
|
522
650
|
}
|
|
523
|
-
await Promise.all(batch.map(([chunk]) => chunk.rebuildSectionMesh()));
|
|
524
651
|
}
|
|
525
652
|
} finally {
|
|
526
653
|
this.culling = void 0;
|
|
@@ -537,7 +664,7 @@ var MineRenderWorld = class {
|
|
|
537
664
|
x,
|
|
538
665
|
y,
|
|
539
666
|
z,
|
|
540
|
-
(positions) => this.updateCulling(positions),
|
|
667
|
+
(positions, defer) => this.updateCulling(positions, defer),
|
|
541
668
|
this.sectionModels,
|
|
542
669
|
(x2, y2, z2) => {
|
|
543
670
|
const cx = Math.floor(x2 / 16), cy = Math.floor(y2 / 16), cz = Math.floor(z2 / 16);
|