minecraft-renderer 0.1.71 → 0.1.73
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 +3 -3
- package/dist/mesher.js +81 -81
- package/dist/mesher.js.map +3 -3
- package/dist/mesherWasm.js +1183 -943
- package/dist/minecraft-renderer.js +250 -79
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +1732 -1001
- package/package.json +3 -3
- package/src/graphicsBackend/rendererDefaultOptions.ts +5 -10
- package/src/graphicsBackend/rendererOptionsSync.ts +1 -1
- package/src/lib/bakeLegacyLight.ts +17 -0
- package/src/lib/blockEntityLightRegistry.test.ts +18 -0
- package/src/lib/blockEntityLightRegistry.ts +75 -0
- package/src/lib/blockEntityLighting.test.ts +30 -0
- package/src/lib/blockEntityLighting.ts +53 -0
- package/src/lib/worldrendererCommon.reconfigure.test.ts +202 -0
- package/src/lib/worldrendererCommon.ts +152 -22
- package/src/mesher-shared/blockEntityMetadata.test.ts +33 -0
- package/src/mesher-shared/blockEntityMetadata.ts +19 -3
- package/src/mesher-shared/exportedGeometryTypes.ts +11 -0
- package/src/mesher-shared/models.ts +161 -92
- package/src/mesher-shared/shared.ts +15 -4
- package/src/mesher-shared/tests/liquidQuadInvariant.test.ts +40 -0
- package/src/mesher-shared/world.ts +12 -0
- package/src/mesher-shared/worldLighting.test.ts +54 -0
- package/src/playground/baseScene.ts +1 -1
- package/src/three/bannerRenderer.ts +10 -3
- package/src/three/chunkMeshManager.ts +663 -69
- package/src/three/cubeDrawSpans.ts +74 -0
- package/src/three/cubeMultiDraw.ts +119 -0
- package/src/three/documentRenderer.ts +0 -2
- package/src/three/entities.ts +5 -6
- package/src/three/entity/EntityMesh.ts +7 -5
- package/src/three/entity/gltfAnimationUtils.ts +5 -3
- package/src/three/globalBlockBuffer.ts +208 -12
- package/src/three/globalLegacyBuffer.ts +701 -0
- package/src/three/graphicsBackendOffThread.ts +16 -1
- package/src/three/itemMesh.ts +5 -2
- package/src/three/legacySectionCull.ts +85 -0
- package/src/three/modules/sciFiWorldReveal.ts +347 -703
- package/src/three/modules/starfield.ts +3 -2
- package/src/three/sectionRaycastAabb.ts +25 -0
- package/src/three/shaders/cubeBlockShader.ts +80 -17
- package/src/three/shaders/legacyBlockShader.ts +292 -0
- package/src/three/skyboxRenderer.ts +1 -1
- package/src/three/tests/chunkMeshManagerLegacy.test.ts +286 -0
- package/src/three/tests/cubeDrawSpans.test.ts +73 -0
- package/src/three/tests/globalLegacyBuffer.test.ts +360 -0
- package/src/three/tests/legacySectionCull.test.ts +80 -0
- package/src/three/tests/signTextureCache.test.ts +83 -0
- package/src/three/threeJsMedia.ts +2 -2
- package/src/three/waypointSprite.ts +2 -2
- package/src/three/world/cursorBlock.ts +1 -0
- package/src/three/world/vr.ts +2 -2
- package/src/three/worldGeometryExport.ts +83 -26
- package/src/three/worldRendererThree.ts +94 -25
- package/src/wasm-mesher/bridge/render-from-wasm.ts +214 -72
- package/src/wasm-mesher/bridge/shaderCubeBridge.ts +18 -6
- package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm +0 -0
- package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +20 -0
- package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +67 -5
- package/src/wasm-mesher/worker/mesherWasm.ts +70 -14
- package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +11 -0
- package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +15 -0
- package/src/worldView/worldView.ts +11 -0
|
@@ -8,6 +8,7 @@ import { worldColumnKey, World } from '../../mesher-shared/world'
|
|
|
8
8
|
import { handleGetHeightmap, EMPTY_COLUMN_HEIGHTMAP_SENTINEL } from '../../mesher-shared/computeHeightmap'
|
|
9
9
|
import { collectBlockEntityMetadata, type SignMeta, type HeadMeta, type BannerMeta } from '../../mesher-shared/blockEntityMetadata'
|
|
10
10
|
import { SectionRequestTracker } from './mesherWasmRequestTracker'
|
|
11
|
+
import { sectionYsForLightColumnDirty } from './mesherWasmLightDirty'
|
|
11
12
|
import {
|
|
12
13
|
CONVERSION_CACHE_LIMIT,
|
|
13
14
|
clearConversionCache,
|
|
@@ -18,6 +19,7 @@ import {
|
|
|
18
19
|
|
|
19
20
|
let wasm: typeof import('../runtime-build/wasm_mesher.js') | null = null
|
|
20
21
|
let wasmInitialized = false
|
|
22
|
+
let wasmReady = false // true ONLY after wasm.default() instantiates the module; gates light-packet parsing
|
|
21
23
|
|
|
22
24
|
// Pending raw `update_light` packets that arrived before WASM finished
|
|
23
25
|
// loading. Parsed and drained once `initWasm` resolves. Without this queue
|
|
@@ -33,7 +35,7 @@ const pendingUpdateLightV17: Array<{ rawPacket: Uint8Array, numSections: number
|
|
|
33
35
|
const pendingUpdateLightV16: Array<{ rawPacket: Uint8Array }> = []
|
|
34
36
|
|
|
35
37
|
function processUpdateLightV17 (rawPacket: Uint8Array, numSections: number): void {
|
|
36
|
-
if (!
|
|
38
|
+
if (!wasmReady) {
|
|
37
39
|
pendingUpdateLightV17.push({ rawPacket, numSections })
|
|
38
40
|
return
|
|
39
41
|
}
|
|
@@ -41,11 +43,13 @@ function processUpdateLightV17 (rawPacket: Uint8Array, numSections: number): voi
|
|
|
41
43
|
const parsed: any = (wasm as any).parseUpdateLightV17(rawPacket, numSections)
|
|
42
44
|
const x = (parsed.x as number) * 16
|
|
43
45
|
const z = (parsed.z as number) * 16
|
|
46
|
+
const skyLight = parsed.skyLight as Uint8Array
|
|
44
47
|
updateLightV17Cache.set(rawCacheKey(x, z), {
|
|
45
|
-
skyLight
|
|
48
|
+
skyLight,
|
|
46
49
|
blockLight: parsed.blockLight as Uint8Array,
|
|
47
50
|
})
|
|
48
51
|
invalidateConversion(x, z)
|
|
52
|
+
dirtyColumnSectionsForLightUpdate(x, z)
|
|
49
53
|
} catch (err) {
|
|
50
54
|
console.warn('[WASM Mesher] parseUpdateLightV17 failed:', err)
|
|
51
55
|
}
|
|
@@ -57,7 +61,7 @@ function processUpdateLightV17 (rawPacket: Uint8Array, numSections: number): voi
|
|
|
57
61
|
// chunk cache has the entry, and crossing the streams could mismatch a
|
|
58
62
|
// stale 1.17 column with 1.16 light or vice versa during version switches.
|
|
59
63
|
function processUpdateLightV16 (rawPacket: Uint8Array): void {
|
|
60
|
-
if (!
|
|
64
|
+
if (!wasmReady) {
|
|
61
65
|
pendingUpdateLightV16.push({ rawPacket })
|
|
62
66
|
return
|
|
63
67
|
}
|
|
@@ -70,6 +74,7 @@ function processUpdateLightV16 (rawPacket: Uint8Array): void {
|
|
|
70
74
|
blockLight: parsed.blockLight as Uint8Array,
|
|
71
75
|
})
|
|
72
76
|
invalidateConversion(x, z)
|
|
77
|
+
dirtyColumnSectionsForLightUpdate(x, z)
|
|
73
78
|
} catch (err) {
|
|
74
79
|
console.warn('[WASM Mesher] parseUpdateLightV17 (v16) failed:', err)
|
|
75
80
|
}
|
|
@@ -81,6 +86,7 @@ async function initWasm() {
|
|
|
81
86
|
wasmInitialized = true
|
|
82
87
|
wasm = await import('../runtime-build/wasm_mesher.js')
|
|
83
88
|
await wasm.default('/wasm_mesher_bg.wasm') as any
|
|
89
|
+
wasmReady = true // instance is now usable; drained packets below will pass the guard
|
|
84
90
|
|
|
85
91
|
if (pendingUpdateLightV17.length > 0) {
|
|
86
92
|
console.log('[WASM Mesher] draining', pendingUpdateLightV17.length, 'pending update_light v17 packets')
|
|
@@ -94,7 +100,10 @@ async function initWasm() {
|
|
|
94
100
|
for (const item of queue) processUpdateLightV16(item.rawPacket)
|
|
95
101
|
}
|
|
96
102
|
} catch (err) {
|
|
97
|
-
console.error(
|
|
103
|
+
console.error(
|
|
104
|
+
'[WASM Mesher] Failed to initialize WASM mesher — block lighting may stay at full brightness:',
|
|
105
|
+
err,
|
|
106
|
+
)
|
|
98
107
|
wasmInitialized = true // Don't try to initialize again
|
|
99
108
|
// Don't throw - allow worker to continue without WASM (will fail on first use)
|
|
100
109
|
}
|
|
@@ -195,6 +204,15 @@ function setSectionDirty(pos: Vec3, value = true) {
|
|
|
195
204
|
}
|
|
196
205
|
}
|
|
197
206
|
|
|
207
|
+
/** Re-mesh every section in a column after `update_light` updates the light cache. */
|
|
208
|
+
function dirtyColumnSectionsForLightUpdate (x: number, z: number) {
|
|
209
|
+
const worldMinY = config?.worldMinY ?? 0
|
|
210
|
+
const worldMaxY = config?.worldMaxY ?? 256
|
|
211
|
+
for (const y of sectionYsForLightColumnDirty(worldMinY, worldMaxY, SECTION_HEIGHT)) {
|
|
212
|
+
setSectionDirty(new Vec3(x, y, z))
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
198
216
|
const softCleanup = () => {
|
|
199
217
|
world = new World(world.config.version)
|
|
200
218
|
globalThis.world = world
|
|
@@ -340,7 +358,7 @@ const convertParsedV17ToWasm = (
|
|
|
340
358
|
} else {
|
|
341
359
|
blockLight = new Uint8Array(totalBlocks)
|
|
342
360
|
skyLight = new Uint8Array(totalBlocks)
|
|
343
|
-
skyLight.fill(15)
|
|
361
|
+
skyLight.fill(config?.skyLight ?? 15)
|
|
344
362
|
}
|
|
345
363
|
const biomesArray: Uint8Array = parsed.biomes
|
|
346
364
|
let blockCount = 0
|
|
@@ -406,7 +424,7 @@ const convertParsedV16ToWasm = (
|
|
|
406
424
|
} else {
|
|
407
425
|
blockLight = new Uint8Array(totalBlocks)
|
|
408
426
|
skyLight = new Uint8Array(totalBlocks)
|
|
409
|
-
skyLight.fill(15)
|
|
427
|
+
skyLight.fill(config?.skyLight ?? 15)
|
|
410
428
|
}
|
|
411
429
|
const biomesArray: Uint8Array = parsed.biomes
|
|
412
430
|
let blockCount = 0
|
|
@@ -465,7 +483,7 @@ const meshColumnFromRawV18Plus = (
|
|
|
465
483
|
meta.occludingBlocks,
|
|
466
484
|
config?.enableLighting !== false,
|
|
467
485
|
config?.smoothLighting !== false,
|
|
468
|
-
config?.skyLight
|
|
486
|
+
config?.skyLight ?? 15
|
|
469
487
|
)
|
|
470
488
|
} catch (err) {
|
|
471
489
|
console.warn('[WASM Mesher] generateGeometryFromMapChunkV18Plus failed, falling back:', err)
|
|
@@ -511,7 +529,7 @@ const meshColumnFromParsedV16V17 = (
|
|
|
511
529
|
meta.occludingBlocks,
|
|
512
530
|
config?.enableLighting !== false,
|
|
513
531
|
config?.smoothLighting !== false,
|
|
514
|
-
config?.skyLight
|
|
532
|
+
config?.skyLight ?? 15
|
|
515
533
|
)
|
|
516
534
|
} catch (err) {
|
|
517
535
|
console.warn('[WASM Mesher] generateGeometryFromParsedV16V17 failed, falling back:', err)
|
|
@@ -572,7 +590,7 @@ const meshMultiColumnsFromRawV18Plus = (
|
|
|
572
590
|
meta.occludingBlocks,
|
|
573
591
|
config?.enableLighting !== false,
|
|
574
592
|
config?.smoothLighting !== false,
|
|
575
|
-
config?.skyLight
|
|
593
|
+
config?.skyLight ?? 15
|
|
576
594
|
)
|
|
577
595
|
} catch (err) {
|
|
578
596
|
console.warn('[WASM Mesher] generateGeometryFromMapChunkV18PlusMulti failed:', err)
|
|
@@ -672,7 +690,7 @@ const meshMultiColumnsFromParsedV16V17 = (
|
|
|
672
690
|
meta.occludingBlocks,
|
|
673
691
|
config?.enableLighting !== false,
|
|
674
692
|
config?.smoothLighting !== false,
|
|
675
|
-
config?.skyLight
|
|
693
|
+
config?.skyLight ?? 15
|
|
676
694
|
)
|
|
677
695
|
} catch (err) {
|
|
678
696
|
console.warn('[WASM Mesher] generateGeometryFromParsedV16V17Multi failed:', err)
|
|
@@ -976,6 +994,8 @@ function makeEmptyColumnGeometry(sx: number, sy: number, sz: number, sectionHeig
|
|
|
976
994
|
positions: new Float32Array(0),
|
|
977
995
|
normals: new Float32Array(0),
|
|
978
996
|
colors: new Float32Array(0),
|
|
997
|
+
skyLights: new Float32Array(0),
|
|
998
|
+
blockLights: new Float32Array(0),
|
|
979
999
|
uvs: new Float32Array(0),
|
|
980
1000
|
indices: new Uint32Array(0),
|
|
981
1001
|
indicesCount: 0,
|
|
@@ -1033,6 +1053,7 @@ function processColumnTick() {
|
|
|
1033
1053
|
let preCacheHits = 0
|
|
1034
1054
|
let preCacheMisses = 0
|
|
1035
1055
|
let hadError = false
|
|
1056
|
+
let columnMeshPath = 'none'
|
|
1036
1057
|
// Outer-scope timestamps so we can finalize `processTime` and
|
|
1037
1058
|
// `postPhase` AFTER the per-section emit loop runs (the loop builds
|
|
1038
1059
|
// typed arrays, walks block-entity metadata, and calls postMessage —
|
|
@@ -1052,6 +1073,7 @@ function processColumnTick() {
|
|
|
1052
1073
|
let wasmResult: any
|
|
1053
1074
|
let t1 = 0
|
|
1054
1075
|
let usedFusedPath = false
|
|
1076
|
+
columnMeshPath = 'none'
|
|
1055
1077
|
|
|
1056
1078
|
const meta = getBlockMeta(version)
|
|
1057
1079
|
|
|
@@ -1067,6 +1089,7 @@ function processColumnTick() {
|
|
|
1067
1089
|
|
|
1068
1090
|
if (rawEntry) {
|
|
1069
1091
|
wasmResult = meshColumnFromRawV18Plus(rawEntry, x, z, worldMinY, worldMaxY, meta)
|
|
1092
|
+
if (wasmResult) columnMeshPath = 'v18_fused'
|
|
1070
1093
|
} else if (v17Entry) {
|
|
1071
1094
|
const v17Light = updateLightV17Cache.get(rawCacheKey(x, z))
|
|
1072
1095
|
wasmResult = meshColumnFromParsedV16V17(
|
|
@@ -1075,6 +1098,7 @@ function processColumnTick() {
|
|
|
1075
1098
|
v17Light?.skyLight ?? null, v17Light?.blockLight ?? null,
|
|
1076
1099
|
x, z, worldMinY, worldMaxY, meta
|
|
1077
1100
|
)
|
|
1101
|
+
if (wasmResult) columnMeshPath = 'v17_fused'
|
|
1078
1102
|
} else if (v16Entry) {
|
|
1079
1103
|
const v16Light = updateLightV16Cache.get(rawCacheKey(x, z))
|
|
1080
1104
|
const bitMapLoHi = new Uint32Array([v16Entry.bitMap >>> 0, 0])
|
|
@@ -1084,6 +1108,7 @@ function processColumnTick() {
|
|
|
1084
1108
|
v16Light?.skyLight ?? null, v16Light?.blockLight ?? null,
|
|
1085
1109
|
x, z, worldMinY, worldMaxY, meta
|
|
1086
1110
|
)
|
|
1111
|
+
if (wasmResult) columnMeshPath = 'v16_fused'
|
|
1087
1112
|
}
|
|
1088
1113
|
|
|
1089
1114
|
if (wasmResult) {
|
|
@@ -1104,6 +1129,7 @@ function processColumnTick() {
|
|
|
1104
1129
|
wasmResult = meshMultiColumnsFromRawV18Plus(chunksToUse, x, z, worldMinY, worldMaxY, meta)
|
|
1105
1130
|
?? meshMultiColumnsFromParsedV16V17(chunksToUse, x, z, worldMinY, worldMaxY, meta)
|
|
1106
1131
|
if (wasmResult) {
|
|
1132
|
+
columnMeshPath = 'multi_fused'
|
|
1107
1133
|
usedFusedPath = true
|
|
1108
1134
|
t1 = performance.now()
|
|
1109
1135
|
wasmPhase = t1 - t0
|
|
@@ -1181,8 +1207,9 @@ function processColumnTick() {
|
|
|
1181
1207
|
invisibleBlocks, transparentBlocks, noAoBlocks, cullIdenticalBlocks, occludingBlocks,
|
|
1182
1208
|
config?.enableLighting !== false,
|
|
1183
1209
|
config?.smoothLighting !== false,
|
|
1184
|
-
config?.skyLight
|
|
1210
|
+
config?.skyLight ?? 15
|
|
1185
1211
|
)
|
|
1212
|
+
columnMeshPath = 'two_step_single'
|
|
1186
1213
|
} else {
|
|
1187
1214
|
const tBuildStart = performance.now()
|
|
1188
1215
|
const perChunkLen = conversions[0].blockStates.length
|
|
@@ -1214,8 +1241,9 @@ function processColumnTick() {
|
|
|
1214
1241
|
invisibleBlocks, transparentBlocks, noAoBlocks, cullIdenticalBlocks, occludingBlocks,
|
|
1215
1242
|
config?.enableLighting !== false,
|
|
1216
1243
|
config?.smoothLighting !== false,
|
|
1217
|
-
config?.skyLight
|
|
1244
|
+
config?.skyLight ?? 15
|
|
1218
1245
|
)
|
|
1246
|
+
columnMeshPath = 'two_step_multi'
|
|
1219
1247
|
}
|
|
1220
1248
|
}
|
|
1221
1249
|
|
|
@@ -1306,14 +1334,16 @@ function processColumnTick() {
|
|
|
1306
1334
|
for (cursor.x = sx; cursor.x < sx + 16; cursor.x++) {
|
|
1307
1335
|
const b = world.getBlock(cursor)
|
|
1308
1336
|
if (!b) continue
|
|
1309
|
-
collectBlockEntityMetadata(b, cursor.x, cursor.y, cursor.z, beTarget, beOpts)
|
|
1337
|
+
collectBlockEntityMetadata(b, cursor.x, cursor.y, cursor.z, beTarget, beOpts, world)
|
|
1310
1338
|
}
|
|
1311
1339
|
}
|
|
1312
1340
|
}
|
|
1313
1341
|
|
|
1314
1342
|
let geometry: MesherGeometryOutput
|
|
1315
1343
|
let transferable: any[] = []
|
|
1316
|
-
const
|
|
1344
|
+
const hasOpaqueMesh = (exported?.geometry.indices.length ?? 0) > 0
|
|
1345
|
+
const hasBlendMesh = (exported?.blendGeometry?.indices.length ?? 0) > 0
|
|
1346
|
+
const hasLegacyMesh = hasOpaqueMesh || hasBlendMesh
|
|
1317
1347
|
const hasShaderCubes = (exported?.shaderCubes?.count ?? 0) > 0
|
|
1318
1348
|
if (exported && (hasLegacyMesh || hasShaderCubes)) {
|
|
1319
1349
|
const maxIndex = exported.geometry.indices.length > 0
|
|
@@ -1335,6 +1365,8 @@ function processColumnTick() {
|
|
|
1335
1365
|
positions: new Float32Array(exported.geometry.positions),
|
|
1336
1366
|
normals: new Float32Array(exported.geometry.normals),
|
|
1337
1367
|
colors: new Float32Array(exported.geometry.colors),
|
|
1368
|
+
skyLights: new Float32Array(exported.geometry.skyLights),
|
|
1369
|
+
blockLights: new Float32Array(exported.geometry.blockLights),
|
|
1338
1370
|
uvs: new Float32Array(exported.geometry.uvs),
|
|
1339
1371
|
indices: using32Array
|
|
1340
1372
|
? new Uint32Array(exported.geometry.indices)
|
|
@@ -1360,13 +1392,37 @@ function processColumnTick() {
|
|
|
1360
1392
|
formatVersion: 3,
|
|
1361
1393
|
}
|
|
1362
1394
|
}
|
|
1395
|
+
if (exported.blendGeometry && hasBlendMesh) {
|
|
1396
|
+
const blendMax = Math.max(...exported.blendGeometry.indices)
|
|
1397
|
+
geometry.blend = {
|
|
1398
|
+
positions: new Float32Array(exported.blendGeometry.positions),
|
|
1399
|
+
normals: new Float32Array(exported.blendGeometry.normals),
|
|
1400
|
+
colors: new Float32Array(exported.blendGeometry.colors),
|
|
1401
|
+
skyLights: new Float32Array(exported.blendGeometry.skyLights),
|
|
1402
|
+
blockLights: new Float32Array(exported.blendGeometry.blockLights),
|
|
1403
|
+
uvs: new Float32Array(exported.blendGeometry.uvs),
|
|
1404
|
+
indices: blendMax > 65535
|
|
1405
|
+
? new Uint32Array(exported.blendGeometry.indices)
|
|
1406
|
+
: new Uint16Array(exported.blendGeometry.indices),
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1363
1409
|
transferable = [
|
|
1364
1410
|
geometry.positions?.buffer,
|
|
1365
1411
|
geometry.normals?.buffer,
|
|
1366
1412
|
geometry.colors?.buffer,
|
|
1413
|
+
geometry.skyLights?.buffer,
|
|
1414
|
+
geometry.blockLights?.buffer,
|
|
1367
1415
|
geometry.uvs?.buffer,
|
|
1368
1416
|
//@ts-ignore
|
|
1369
1417
|
geometry.indices?.buffer,
|
|
1418
|
+
geometry.blend?.positions?.buffer,
|
|
1419
|
+
geometry.blend?.normals?.buffer,
|
|
1420
|
+
geometry.blend?.colors?.buffer,
|
|
1421
|
+
geometry.blend?.skyLights?.buffer,
|
|
1422
|
+
geometry.blend?.blockLights?.buffer,
|
|
1423
|
+
geometry.blend?.uvs?.buffer,
|
|
1424
|
+
//@ts-ignore
|
|
1425
|
+
geometry.blend?.indices?.buffer,
|
|
1370
1426
|
geometry.shaderCubes?.words?.buffer,
|
|
1371
1427
|
].filter(Boolean)
|
|
1372
1428
|
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import { sectionYsForLightColumnDirty } from './mesherWasmLightDirty'
|
|
4
|
+
|
|
5
|
+
describe('sectionYsForLightColumnDirty', () => {
|
|
6
|
+
it('covers every section in a 256-high overworld column', () => {
|
|
7
|
+
expect(sectionYsForLightColumnDirty(0, 256)).toEqual(
|
|
8
|
+
Array.from({ length: 16 }, (_, i) => i * 16),
|
|
9
|
+
)
|
|
10
|
+
})
|
|
11
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { SECTION_HEIGHT } from '../../mesher-shared/shared'
|
|
3
|
+
|
|
4
|
+
/** Section Y values to dirty for a column after `update_light` updates the light cache. */
|
|
5
|
+
export function sectionYsForLightColumnDirty (
|
|
6
|
+
worldMinY: number,
|
|
7
|
+
worldMaxY: number,
|
|
8
|
+
sectionHeight = SECTION_HEIGHT,
|
|
9
|
+
): number[] {
|
|
10
|
+
const ys: number[] = []
|
|
11
|
+
for (let y = worldMinY; y < worldMaxY; y += sectionHeight) {
|
|
12
|
+
ys.push(y)
|
|
13
|
+
}
|
|
14
|
+
return ys
|
|
15
|
+
}
|
|
@@ -320,6 +320,17 @@ export class WorldView extends (EventEmitter as new () => TypedEmitter<WorldView
|
|
|
320
320
|
}
|
|
321
321
|
}
|
|
322
322
|
|
|
323
|
+
/**
|
|
324
|
+
* Re-fetch and re-emit every loaded chunk (e.g. after mesher workers are recreated).
|
|
325
|
+
*/
|
|
326
|
+
async reloadLoadedChunks(): Promise<void> {
|
|
327
|
+
const coords = Object.keys(this.loadedChunks)
|
|
328
|
+
for (const key of coords) {
|
|
329
|
+
const [x, z] = key.split(',').map(Number)
|
|
330
|
+
await this.loadChunk({ x, z }, false, 'mesher-reconfigure')
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
323
334
|
/**
|
|
324
335
|
* Unload all chunks.
|
|
325
336
|
*/
|