minecraft-renderer 0.1.79 → 0.1.80
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 +29 -25
- package/dist/mesher.js +36 -36
- package/dist/mesher.js.map +4 -4
- package/dist/mesherWasm.js +217 -217
- package/dist/minecraft-renderer.js +27 -27
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +133 -133
- package/package.json +5 -2
- package/src/bundler/bundlePrepare.ts +3 -8
- package/src/graphicsBackend/appViewer.ts +10 -7
- package/src/graphicsBackend/config.ts +1 -5
- package/src/graphicsBackend/playerState.ts +35 -34
- package/src/graphicsBackend/preloadWorkers.ts +43 -41
- package/src/graphicsBackend/rendererDefaultOptions.ts +68 -70
- package/src/graphicsBackend/rendererOptionsSync.ts +24 -50
- package/src/graphicsBackend/types.ts +2 -2
- package/src/index.ts +6 -27
- package/src/lib/DebugGui.ts +34 -31
- package/src/lib/animationController.ts +9 -9
- package/src/lib/bakeLegacyLight.ts +1 -6
- package/src/lib/bindAbortableListener.test.ts +32 -12
- package/src/lib/bindAbortableListener.ts +14 -6
- package/src/lib/blockEntityLightRegistry.ts +11 -20
- package/src/lib/blockEntityLighting.test.ts +1 -6
- package/src/lib/blockEntityLighting.ts +5 -5
- package/src/lib/buildSharedConfig.mjs +4 -4
- package/src/lib/buildWorkerMcDataIndexes.test.ts +4 -4
- package/src/lib/buildWorkerMcDataIndexes.ts +11 -19
- package/src/lib/cameraBobbing.ts +1 -1
- package/src/lib/canvas2DOverlay.example.ts +13 -33
- package/src/lib/canvas2DOverlay.quickstart.ts +24 -54
- package/src/lib/canvas2DOverlay.ts +28 -47
- package/src/lib/cleanupDecorator.ts +2 -2
- package/src/lib/createPlayerObject.test.ts +2 -7
- package/src/lib/createPlayerObject.ts +18 -25
- package/src/lib/frameTimingCollector.ts +2 -5
- package/src/lib/guiRenderer.ts +57 -42
- package/src/lib/items.ts +15 -9
- package/src/lib/mesherlogReader.ts +5 -6
- package/src/lib/simpleUtils.ts +5 -5
- package/src/lib/skyLight.ts +3 -3
- package/src/lib/smoothSwitcher.ts +11 -18
- package/src/lib/ui/newStats.ts +10 -12
- package/src/lib/utils/proxy.ts +7 -1
- package/src/lib/utils/skins.ts +4 -4
- package/src/lib/utils.ts +1 -1
- package/src/lib/workerMessageSanitize.ts +5 -12
- package/src/lib/workerProxy.ts +52 -42
- package/src/lib/workerSyncOps.test.ts +58 -41
- package/src/lib/worldrendererCommon.reconfigure.test.ts +24 -21
- package/src/lib/worldrendererCommon.removeColumn.test.ts +11 -13
- package/src/lib/worldrendererCommon.ts +338 -211
- package/src/mesher-legacy/mesher.ts +9 -4
- package/src/mesher-legacy/test/a.ts +1 -1
- package/src/mesher-legacy/test/mesherTester.ts +2 -2
- package/src/mesher-legacy/test/playground.ts +1 -1
- package/src/mesher-legacy/test/run/test-js.ts +1 -1
- package/src/mesher-legacy/test/snapshotUtils.ts +3 -8
- package/src/mesher-legacy/test/test-perf.ts +1 -1
- package/src/mesher-legacy/test/tests.test.ts +2 -2
- package/src/mesher-shared/blockEntityMetadata.test.ts +7 -5
- package/src/mesher-shared/blockEntityMetadata.ts +28 -19
- package/src/mesher-shared/blockPropertiesForMeshing.ts +2 -2
- package/src/mesher-shared/computeHeightmap.ts +2 -4
- package/src/mesher-shared/exportedGeometryTypes.ts +3 -3
- package/src/mesher-shared/faceOcclusion.ts +324 -0
- package/src/mesher-shared/models.ts +80 -131
- package/src/mesher-shared/modelsGeometryCommon.ts +30 -15
- package/src/mesher-shared/shared.ts +46 -46
- package/src/mesher-shared/standaloneRenderer.ts +40 -44
- package/src/mesher-shared/tests/faceOcclusion.test.ts +179 -0
- package/src/mesher-shared/tests/liquidQuadInvariant.test.ts +12 -8
- package/src/mesher-shared/vertexShading.ts +2 -11
- package/src/mesher-shared/world.ts +19 -19
- package/src/mesher-shared/worldLighting.test.ts +2 -2
- package/src/performanceMonitor/PerformanceMonitor.ts +4 -13
- package/src/performanceMonitor/formatPerformanceFactorsDebug.ts +2 -2
- package/src/performanceMonitor/index.ts +1 -5
- package/src/performanceMonitor/types.ts +1 -1
- package/src/playerState/playerState.ts +55 -50
- package/src/playerState/types.ts +2 -8
- package/src/playground/allEntitiesDebug.ts +19 -16
- package/src/playground/baseScene.ts +29 -32
- package/src/playground/mobileControls.tsx +133 -129
- package/src/playground/playground.html +76 -73
- package/src/playground/playground.ts +14 -1
- package/src/playground/playgroundUi.tsx +100 -74
- package/src/playground/reactUtils.ts +3 -7
- package/src/playground/scenes/entities.ts +10 -7
- package/src/playground/scenes/frequentUpdates.ts +5 -5
- package/src/playground/scenes/geometryExport.ts +6 -20
- package/src/playground/scenes/highPosEntityUpdates.ts +2 -10
- package/src/playground/scenes/index.ts +1 -1
- package/src/playground/scenes/lightingStarfield.ts +18 -12
- package/src/playground/scenes/main.ts +15 -11
- package/src/playground/scenes/partialBlockCulling.ts +31 -0
- package/src/playground/scenes/railsCobweb.ts +1 -1
- package/src/playground/scenes/rotationIssue.ts +1 -1
- package/src/playground/scenes/slabsOptimization.ts +1 -2
- package/src/playground/scenes/transparencyIssue.ts +1 -1
- package/src/playground/shared.ts +2 -2
- package/src/resourcesManager/resourcesManager.ts +29 -54
- package/src/resourcesManager/resourcesManager.worker.test.ts +6 -10
- package/src/shims/minecraftData.ts +70 -24
- package/src/sign-renderer/index.html +10 -12
- package/src/sign-renderer/index.ts +29 -29
- package/src/sign-renderer/playground.ts +22 -15
- package/src/sign-renderer/tests.test.ts +16 -13
- package/src/sign-renderer/vite.config.ts +2 -2
- package/src/three/appShared.ts +46 -25
- package/src/three/bannerRenderer.ts +33 -61
- package/src/three/cameraShake.ts +15 -6
- package/src/three/chunkMeshManager.ts +239 -282
- package/src/three/cinimaticScript.ts +26 -15
- package/src/three/cubeDrawSpans.ts +27 -37
- package/src/three/cubeMultiDraw.ts +9 -22
- package/src/three/documentRenderer.ts +15 -18
- package/src/three/entities.ts +175 -150
- package/src/three/entity/EntityMesh.ts +114 -108
- package/src/three/entity/animations.js +3 -3
- package/src/three/entity/armorModels.ts +15 -15
- package/src/three/entity/gltfAnimationUtils.ts +2 -5
- package/src/three/fireworks.ts +34 -32
- package/src/three/fireworksRenderer.ts +32 -29
- package/src/three/globalBlockBuffer.ts +167 -100
- package/src/three/globalLegacyBuffer.ts +257 -166
- package/src/three/graphicsBackendBase.ts +19 -25
- package/src/three/graphicsBackendOffThread.ts +12 -15
- package/src/three/hand.ts +21 -21
- package/src/three/handLegacy.ts +3 -13
- package/src/three/holdingBlock.ts +116 -79
- package/src/three/holdingBlockFactory.ts +1 -4
- package/src/three/holdingBlockItemIdentity.test.ts +25 -17
- package/src/three/holdingBlockItemIdentity.ts +9 -6
- package/src/three/holdingBlockLegacy.ts +113 -132
- package/src/three/itemMesh.ts +20 -29
- package/src/three/legacyMultiDraw.ts +10 -16
- package/src/three/legacySectionCull.ts +8 -14
- package/src/three/menuBackground/activeView.ts +1 -4
- package/src/three/menuBackground/assetUrl.ts +1 -1
- package/src/three/menuBackground/classic.ts +4 -12
- package/src/three/menuBackground/gpuPreference.ts +1 -3
- package/src/three/menuBackground/index.ts +2 -11
- package/src/three/menuBackground/renderer.ts +1 -5
- package/src/three/menuBackground/types.ts +1 -4
- package/src/three/menuBackground/v2.ts +196 -96
- package/src/three/menuBackground/v2Meta.ts +3 -3
- package/src/three/menuBackground/worldBlocks.ts +37 -35
- package/src/three/modules/blockBreakParticles.ts +59 -28
- package/src/three/modules/cameraBobbing.ts +3 -6
- package/src/three/modules/index.ts +1 -1
- package/src/three/modules/rain.ts +10 -23
- package/src/three/modules/sciFiWorldReveal.ts +11 -25
- package/src/three/modules/starfield.ts +7 -13
- package/src/three/renderSlot.ts +28 -16
- package/src/three/rendererModuleSystem.ts +1 -3
- package/src/three/sceneOrigin.ts +96 -33
- package/src/three/sectionRaycastAabb.ts +30 -18
- package/src/three/shaderCubeMesh.ts +6 -17
- package/src/three/shaders/cubeBlockShader.ts +85 -96
- package/src/three/shaders/legacyBlockShader.ts +21 -43
- package/src/three/shaders/textureIndexMapping.ts +89 -95
- package/src/three/shaders/tintPalette.ts +156 -170
- package/src/three/signTextureCache.ts +9 -12
- package/src/three/skyboxRenderer.ts +62 -70
- package/src/three/tests/chunkMeshManagerLegacy.test.ts +34 -34
- package/src/three/tests/cubeDrawSpans.test.ts +55 -25
- package/src/three/tests/globalBlockBuffer.test.ts +217 -0
- package/src/three/tests/globalLegacyBuffer.test.ts +300 -41
- package/src/three/tests/legacyMultiDraw.test.ts +8 -29
- package/src/three/tests/pr3PerFrameCpuCuts.test.ts +106 -29
- package/src/three/tests/signTextureCache.test.ts +4 -4
- package/src/three/threeJsMedia.ts +55 -72
- package/src/three/threeJsParticles.ts +32 -41
- package/src/three/threeJsSound.ts +3 -3
- package/src/three/threeJsUtils.ts +3 -3
- package/src/three/threeWorker.ts +2 -2
- package/src/three/waypointSprite.ts +55 -82
- package/src/three/waypoints.ts +20 -23
- package/src/three/world/cursorBlock.ts +25 -12
- package/src/three/world/vr.ts +11 -17
- package/src/three/worldGeometryExport.ts +15 -34
- package/src/three/worldRendererThree.ts +117 -129
- package/src/wasm-mesher/bridge/convertChunk.ts +3 -9
- package/src/wasm-mesher/bridge/render-from-wasm.ts +204 -229
- package/src/wasm-mesher/bridge/shaderCubeBridge.ts +26 -67
- package/src/wasm-mesher/tests/cullingRegression.test.ts +307 -0
- package/src/wasm-mesher/tests/heightmapParity.test.ts +8 -18
- package/src/wasm-mesher/tests/mesherWasmConversionCache.test.ts +2 -2
- package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +17 -4
- package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +103 -141
- package/src/wasm-mesher/tests/splitColumnWasmOutput.test.ts +14 -22
- package/src/wasm-mesher/worker/mesherWasm.ts +150 -141
- package/src/wasm-mesher/worker/mesherWasmConversionCache.ts +2 -8
- package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +1 -3
- package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +1 -5
- package/src/wasm-mesher/worker/mesherWasmRequestTracker.ts +42 -42
- package/src/worldView/worldView.spiral.test.ts +1 -1
- package/src/worldView/worldView.ts +34 -39
- package/src/worldView/worldViewWorkerBridge.test.ts +4 -4
|
@@ -9,13 +9,7 @@ import { handleGetHeightmap, EMPTY_COLUMN_HEIGHTMAP_SENTINEL } from '../../meshe
|
|
|
9
9
|
import { collectBlockEntityMetadata, type SignMeta, type HeadMeta, type BannerMeta } from '../../mesher-shared/blockEntityMetadata'
|
|
10
10
|
import { SectionRequestTracker } from './mesherWasmRequestTracker'
|
|
11
11
|
import { sectionYsForLightColumnDirty } from './mesherWasmLightDirty'
|
|
12
|
-
import {
|
|
13
|
-
CONVERSION_CACHE_LIMIT,
|
|
14
|
-
clearConversionCache,
|
|
15
|
-
getOrConvertColumn,
|
|
16
|
-
invalidateConversion,
|
|
17
|
-
setConversionCacheLimit,
|
|
18
|
-
} from './mesherWasmConversionCache'
|
|
12
|
+
import { CONVERSION_CACHE_LIMIT, clearConversionCache, getOrConvertColumn, invalidateConversion, setConversionCacheLimit } from './mesherWasmConversionCache'
|
|
19
13
|
|
|
20
14
|
let wasm: typeof import('../runtime-build/wasm_mesher.js') | null = null
|
|
21
15
|
let wasmInitialized = false
|
|
@@ -28,13 +22,13 @@ let wasmReady = false // true ONLY after wasm.default() instantiates the module;
|
|
|
28
22
|
// (under trees, cliff edges) look brighter than vanilla, and after the
|
|
29
23
|
// renderer interpolates with neighbour chunks that DO have real light,
|
|
30
24
|
// the seams look like "local night".
|
|
31
|
-
const pendingUpdateLightV17: Array<{ rawPacket: Uint8Array
|
|
25
|
+
const pendingUpdateLightV17: Array<{ rawPacket: Uint8Array; numSections: number }> = []
|
|
32
26
|
// Separate v16 pending queue so 1.16 update_light packets that arrive
|
|
33
27
|
// before WASM is initialised land in the v16 light cache (not v17) on
|
|
34
28
|
// drain — the mesh hot path looks them up per protocol family.
|
|
35
29
|
const pendingUpdateLightV16: Array<{ rawPacket: Uint8Array }> = []
|
|
36
30
|
|
|
37
|
-
function processUpdateLightV17
|
|
31
|
+
function processUpdateLightV17(rawPacket: Uint8Array, numSections: number): void {
|
|
38
32
|
if (!wasmReady) {
|
|
39
33
|
pendingUpdateLightV17.push({ rawPacket, numSections })
|
|
40
34
|
return
|
|
@@ -46,7 +40,7 @@ function processUpdateLightV17 (rawPacket: Uint8Array, numSections: number): voi
|
|
|
46
40
|
const skyLight = parsed.skyLight as Uint8Array
|
|
47
41
|
updateLightV17Cache.set(rawCacheKey(x, z), {
|
|
48
42
|
skyLight,
|
|
49
|
-
blockLight: parsed.blockLight as Uint8Array
|
|
43
|
+
blockLight: parsed.blockLight as Uint8Array
|
|
50
44
|
})
|
|
51
45
|
invalidateConversion(x, z)
|
|
52
46
|
dirtyColumnSectionsForLightUpdate(x, z)
|
|
@@ -60,7 +54,7 @@ function processUpdateLightV17 (rawPacket: Uint8Array, numSections: number): voi
|
|
|
60
54
|
// families fully isolated — the mesh tick picks v16 vs v17 by which raw
|
|
61
55
|
// chunk cache has the entry, and crossing the streams could mismatch a
|
|
62
56
|
// stale 1.17 column with 1.16 light or vice versa during version switches.
|
|
63
|
-
function processUpdateLightV16
|
|
57
|
+
function processUpdateLightV16(rawPacket: Uint8Array): void {
|
|
64
58
|
if (!wasmReady) {
|
|
65
59
|
pendingUpdateLightV16.push({ rawPacket })
|
|
66
60
|
return
|
|
@@ -71,7 +65,7 @@ function processUpdateLightV16 (rawPacket: Uint8Array): void {
|
|
|
71
65
|
const z = (parsed.z as number) * 16
|
|
72
66
|
updateLightV16Cache.set(rawCacheKey(x, z), {
|
|
73
67
|
skyLight: parsed.skyLight as Uint8Array,
|
|
74
|
-
blockLight: parsed.blockLight as Uint8Array
|
|
68
|
+
blockLight: parsed.blockLight as Uint8Array
|
|
75
69
|
})
|
|
76
70
|
invalidateConversion(x, z)
|
|
77
71
|
dirtyColumnSectionsForLightUpdate(x, z)
|
|
@@ -85,7 +79,7 @@ async function initWasm() {
|
|
|
85
79
|
try {
|
|
86
80
|
wasmInitialized = true
|
|
87
81
|
wasm = await import('../runtime-build/wasm_mesher.js')
|
|
88
|
-
await wasm.default('/wasm_mesher_bg.wasm') as any
|
|
82
|
+
;(await wasm.default('/wasm_mesher_bg.wasm')) as any
|
|
89
83
|
wasmReady = true // instance is now usable; drained packets below will pass the guard
|
|
90
84
|
|
|
91
85
|
if (pendingUpdateLightV17.length > 0) {
|
|
@@ -100,23 +94,22 @@ async function initWasm() {
|
|
|
100
94
|
for (const item of queue) processUpdateLightV16(item.rawPacket)
|
|
101
95
|
}
|
|
102
96
|
} catch (err) {
|
|
103
|
-
console.error(
|
|
104
|
-
'[WASM Mesher] Failed to initialize WASM mesher — block lighting may stay at full brightness:',
|
|
105
|
-
err,
|
|
106
|
-
)
|
|
97
|
+
console.error('[WASM Mesher] Failed to initialize WASM mesher — block lighting may stay at full brightness:', err)
|
|
107
98
|
wasmInitialized = true // Don't try to initialize again
|
|
108
99
|
// Don't throw - allow worker to continue without WASM (will fail on first use)
|
|
109
100
|
}
|
|
110
101
|
}
|
|
111
102
|
|
|
112
|
-
globalThis.structuredClone ??=
|
|
103
|
+
globalThis.structuredClone ??= value => JSON.parse(JSON.stringify(value))
|
|
113
104
|
|
|
114
105
|
if (globalThis.module && module.require) {
|
|
115
106
|
// If we are in a node environment, we need to fake some env variables
|
|
116
107
|
const r = module.require
|
|
117
108
|
const { parentPort } = r('worker_threads')
|
|
118
109
|
global.self = parentPort
|
|
119
|
-
global.postMessage = (value, transferList) => {
|
|
110
|
+
global.postMessage = (value, transferList) => {
|
|
111
|
+
parentPort.postMessage(value, transferList)
|
|
112
|
+
}
|
|
120
113
|
global.performance = r('perf_hooks').performance
|
|
121
114
|
}
|
|
122
115
|
|
|
@@ -154,7 +147,10 @@ const postMessage = (data: any, transferList: any[] = []) => {
|
|
|
154
147
|
|
|
155
148
|
function drainQueue(from: number, to: number) {
|
|
156
149
|
const messages = queuedMessages.slice(from, to)
|
|
157
|
-
global.postMessage(
|
|
150
|
+
global.postMessage(
|
|
151
|
+
messages.map(m => m.data),
|
|
152
|
+
messages.flatMap(m => m.transferList) as unknown as string
|
|
153
|
+
)
|
|
158
154
|
queuedMessages = queuedMessages.slice(to)
|
|
159
155
|
}
|
|
160
156
|
|
|
@@ -165,7 +161,7 @@ function drainQueue(from: number, to: number) {
|
|
|
165
161
|
// contract violation (`WorldRendererCommon` would throw on the main thread)
|
|
166
162
|
// and we surface it via `console.warn` so it shows up in dev/CI without
|
|
167
163
|
// killing the worker.
|
|
168
|
-
const emitSectionFinished = (payload: { type: 'sectionFinished'
|
|
164
|
+
const emitSectionFinished = (payload: { type: 'sectionFinished'; key: string } & Record<string, any>) => {
|
|
169
165
|
const consumed = requestTracker.consumeOne(payload.key)
|
|
170
166
|
if (!consumed) {
|
|
171
167
|
console.warn(`[WASM Mesher] sectionFinished for non-requested key ${payload.key} (column-mode contract violation)`)
|
|
@@ -205,7 +201,7 @@ function setSectionDirty(pos: Vec3, value = true) {
|
|
|
205
201
|
}
|
|
206
202
|
|
|
207
203
|
/** Re-mesh every section in a column after `update_light` updates the light cache. */
|
|
208
|
-
function dirtyColumnSectionsForLightUpdate
|
|
204
|
+
function dirtyColumnSectionsForLightUpdate(x: number, z: number) {
|
|
209
205
|
const worldMinY = config?.worldMinY ?? 0
|
|
210
206
|
const worldMaxY = config?.worldMaxY ?? 256
|
|
211
207
|
for (const y of sectionYsForLightColumnDirty(worldMinY, worldMaxY, SECTION_HEIGHT)) {
|
|
@@ -275,10 +271,7 @@ const updateLightV16Cache = new Map<string, UpdateLightV17Entry>()
|
|
|
275
271
|
|
|
276
272
|
// Mirrors `convertChunkToWasm`'s output (same layout: x + z*16 + y*256,
|
|
277
273
|
// y outer) so it can be dropped straight into `generate_geometry`.
|
|
278
|
-
const convertRawMapChunkToWasm = (
|
|
279
|
-
raw: RawMapChunkEntry,
|
|
280
|
-
version: string
|
|
281
|
-
): ChunkConversionResult | null => {
|
|
274
|
+
const convertRawMapChunkToWasm = (raw: RawMapChunkEntry, version: string): ChunkConversionResult | null => {
|
|
282
275
|
if (!wasm || !(wasm as any).parseMapChunkV18Plus) return null
|
|
283
276
|
// 1.18 introduced the new chunk format; on earlier protocols the packet
|
|
284
277
|
// shape differs and our parser would throw. Fall back to the JS path.
|
|
@@ -289,13 +282,7 @@ const convertRawMapChunkToWasm = (
|
|
|
289
282
|
const MAX_BITS_PER_BIOME = 3
|
|
290
283
|
let parsed: any
|
|
291
284
|
try {
|
|
292
|
-
parsed = (wasm as any).parseMapChunkV18Plus(
|
|
293
|
-
raw.rawPacket,
|
|
294
|
-
raw.numSections,
|
|
295
|
-
MAX_BITS_PER_BLOCK,
|
|
296
|
-
MAX_BITS_PER_BIOME,
|
|
297
|
-
raw.protocol
|
|
298
|
-
)
|
|
285
|
+
parsed = (wasm as any).parseMapChunkV18Plus(raw.rawPacket, raw.numSections, MAX_BITS_PER_BLOCK, MAX_BITS_PER_BIOME, raw.protocol)
|
|
299
286
|
} catch (err) {
|
|
300
287
|
console.warn('[WASM Mesher] parseMapChunkV18Plus failed, falling back:', err)
|
|
301
288
|
return null
|
|
@@ -316,7 +303,7 @@ const convertRawMapChunkToWasm = (
|
|
|
316
303
|
noAoBlocks: meta.noAoBlocks,
|
|
317
304
|
cullIdenticalBlocks: meta.cullIdenticalBlocks,
|
|
318
305
|
occludingBlocks: meta.occludingBlocks,
|
|
319
|
-
blockCount
|
|
306
|
+
blockCount
|
|
320
307
|
}
|
|
321
308
|
}
|
|
322
309
|
|
|
@@ -324,11 +311,7 @@ const convertRawMapChunkToWasm = (
|
|
|
324
311
|
// (expanded from the 4×4×4 cell layout). Light comes from the paired
|
|
325
312
|
// `update_light` cache when available; otherwise we fall back to full
|
|
326
313
|
// daylight (sky=15) and no block light so geometry stays visible.
|
|
327
|
-
const convertParsedV17ToWasm = (
|
|
328
|
-
entry: ParsedV17Entry,
|
|
329
|
-
lightEntry: UpdateLightV17Entry | undefined,
|
|
330
|
-
version: string
|
|
331
|
-
): ChunkConversionResult | null => {
|
|
314
|
+
const convertParsedV17ToWasm = (entry: ParsedV17Entry, lightEntry: UpdateLightV17Entry | undefined, version: string): ChunkConversionResult | null => {
|
|
332
315
|
if (!wasm || !(wasm as any).parseChunkSectionsV16V17) return null
|
|
333
316
|
// Empty `Int32Array` signals "no biomes captured" — WASM falls back to
|
|
334
317
|
// `default_biome` for every block. Plains (id 1) matches the JS path.
|
|
@@ -336,14 +319,7 @@ const convertParsedV17ToWasm = (
|
|
|
336
319
|
const DEFAULT_BIOME = 1
|
|
337
320
|
let parsed: any
|
|
338
321
|
try {
|
|
339
|
-
parsed = (wasm as any).parseChunkSectionsV16V17(
|
|
340
|
-
entry.chunkData,
|
|
341
|
-
entry.bitMapLoHi,
|
|
342
|
-
entry.numSections,
|
|
343
|
-
entry.maxBitsPerBlock,
|
|
344
|
-
biomesCells,
|
|
345
|
-
DEFAULT_BIOME,
|
|
346
|
-
)
|
|
322
|
+
parsed = (wasm as any).parseChunkSectionsV16V17(entry.chunkData, entry.bitMapLoHi, entry.numSections, entry.maxBitsPerBlock, biomesCells, DEFAULT_BIOME)
|
|
347
323
|
} catch (err) {
|
|
348
324
|
console.warn('[WASM Mesher] parseChunkSectionsV16V17 failed, falling back:', err)
|
|
349
325
|
return null
|
|
@@ -376,7 +352,7 @@ const convertParsedV17ToWasm = (
|
|
|
376
352
|
noAoBlocks: meta.noAoBlocks,
|
|
377
353
|
cullIdenticalBlocks: meta.cullIdenticalBlocks,
|
|
378
354
|
occludingBlocks: meta.occludingBlocks,
|
|
379
|
-
blockCount
|
|
355
|
+
blockCount
|
|
380
356
|
}
|
|
381
357
|
}
|
|
382
358
|
|
|
@@ -386,11 +362,7 @@ const convertParsedV17ToWasm = (
|
|
|
386
362
|
// defaults — anything else means a non-vanilla server we don't support
|
|
387
363
|
// on the fast path, in which case we return null and fall back to the
|
|
388
364
|
// JS column-walk via `convertChunkToWasm`.
|
|
389
|
-
const convertParsedV16ToWasm = (
|
|
390
|
-
entry: ParsedV16Entry,
|
|
391
|
-
lightEntry: UpdateLightV17Entry | undefined,
|
|
392
|
-
version: string
|
|
393
|
-
): ChunkConversionResult | null => {
|
|
365
|
+
const convertParsedV16ToWasm = (entry: ParsedV16Entry, lightEntry: UpdateLightV17Entry | undefined, version: string): ChunkConversionResult | null => {
|
|
394
366
|
if (!wasm || !(wasm as any).parseChunkSectionsV16V17) return null
|
|
395
367
|
const NUM_SECTIONS = 16
|
|
396
368
|
const MAX_BITS_PER_BLOCK = 15
|
|
@@ -402,14 +374,7 @@ const convertParsedV16ToWasm = (
|
|
|
402
374
|
const biomesCells = entry.biomes ?? new Int32Array(0)
|
|
403
375
|
let parsed: any
|
|
404
376
|
try {
|
|
405
|
-
parsed = (wasm as any).parseChunkSectionsV16V17(
|
|
406
|
-
entry.chunkData,
|
|
407
|
-
bitMapLoHi,
|
|
408
|
-
NUM_SECTIONS,
|
|
409
|
-
MAX_BITS_PER_BLOCK,
|
|
410
|
-
biomesCells,
|
|
411
|
-
DEFAULT_BIOME,
|
|
412
|
-
)
|
|
377
|
+
parsed = (wasm as any).parseChunkSectionsV16V17(entry.chunkData, bitMapLoHi, NUM_SECTIONS, MAX_BITS_PER_BLOCK, biomesCells, DEFAULT_BIOME)
|
|
413
378
|
} catch (err) {
|
|
414
379
|
console.warn('[WASM Mesher] parseChunkSectionsV16V17 (v16) failed, falling back:', err)
|
|
415
380
|
return null
|
|
@@ -442,7 +407,7 @@ const convertParsedV16ToWasm = (
|
|
|
442
407
|
noAoBlocks: meta.noAoBlocks,
|
|
443
408
|
cullIdenticalBlocks: meta.cullIdenticalBlocks,
|
|
444
409
|
occludingBlocks: meta.occludingBlocks,
|
|
445
|
-
blockCount
|
|
410
|
+
blockCount
|
|
446
411
|
}
|
|
447
412
|
}
|
|
448
413
|
|
|
@@ -473,8 +438,12 @@ const meshColumnFromRawV18Plus = (
|
|
|
473
438
|
MAX_BITS_PER_BLOCK,
|
|
474
439
|
MAX_BITS_PER_BIOME,
|
|
475
440
|
raw.protocol,
|
|
476
|
-
x,
|
|
477
|
-
worldMinY,
|
|
441
|
+
x,
|
|
442
|
+
worldMinY,
|
|
443
|
+
z,
|
|
444
|
+
columnHeight,
|
|
445
|
+
worldMinY,
|
|
446
|
+
worldMaxY,
|
|
478
447
|
worldMinY,
|
|
479
448
|
meta.invisibleBlocks,
|
|
480
449
|
meta.transparentBlocks,
|
|
@@ -519,8 +488,12 @@ const meshColumnFromParsedV16V17 = (
|
|
|
519
488
|
defaultBiome,
|
|
520
489
|
skyLight ?? new Uint8Array(0),
|
|
521
490
|
blockLight ?? new Uint8Array(0),
|
|
522
|
-
x,
|
|
523
|
-
worldMinY,
|
|
491
|
+
x,
|
|
492
|
+
worldMinY,
|
|
493
|
+
z,
|
|
494
|
+
columnHeight,
|
|
495
|
+
worldMinY,
|
|
496
|
+
worldMaxY,
|
|
524
497
|
worldMinY,
|
|
525
498
|
meta.invisibleBlocks,
|
|
526
499
|
meta.transparentBlocks,
|
|
@@ -543,7 +516,7 @@ const meshColumnFromParsedV16V17 = (
|
|
|
543
516
|
// ---------------------------------------------------------------------------
|
|
544
517
|
|
|
545
518
|
const meshMultiColumnsFromRawV18Plus = (
|
|
546
|
-
chunksToUse: Array<{ x: number
|
|
519
|
+
chunksToUse: Array<{ x: number; z: number; chunk: any }>,
|
|
547
520
|
x: number,
|
|
548
521
|
z: number,
|
|
549
522
|
worldMinY: number,
|
|
@@ -580,8 +553,12 @@ const meshMultiColumnsFromRawV18Plus = (
|
|
|
580
553
|
protocol,
|
|
581
554
|
chunkXs,
|
|
582
555
|
chunkZs,
|
|
583
|
-
x,
|
|
584
|
-
worldMinY,
|
|
556
|
+
x,
|
|
557
|
+
worldMinY,
|
|
558
|
+
z,
|
|
559
|
+
columnHeight,
|
|
560
|
+
worldMinY,
|
|
561
|
+
worldMaxY,
|
|
585
562
|
worldMinY,
|
|
586
563
|
meta.invisibleBlocks,
|
|
587
564
|
meta.transparentBlocks,
|
|
@@ -599,7 +576,7 @@ const meshMultiColumnsFromRawV18Plus = (
|
|
|
599
576
|
}
|
|
600
577
|
|
|
601
578
|
const meshMultiColumnsFromParsedV16V17 = (
|
|
602
|
-
chunksToUse: Array<{ x: number
|
|
579
|
+
chunksToUse: Array<{ x: number; z: number; chunk: any }>,
|
|
603
580
|
x: number,
|
|
604
581
|
z: number,
|
|
605
582
|
worldMinY: number,
|
|
@@ -680,8 +657,12 @@ const meshMultiColumnsFromParsedV16V17 = (
|
|
|
680
657
|
blockLightList,
|
|
681
658
|
chunkXs,
|
|
682
659
|
chunkZs,
|
|
683
|
-
x,
|
|
684
|
-
worldMinY,
|
|
660
|
+
x,
|
|
661
|
+
worldMinY,
|
|
662
|
+
z,
|
|
663
|
+
columnHeight,
|
|
664
|
+
worldMinY,
|
|
665
|
+
worldMaxY,
|
|
685
666
|
worldMinY,
|
|
686
667
|
meta.invisibleBlocks,
|
|
687
668
|
meta.transparentBlocks,
|
|
@@ -768,10 +749,7 @@ const handleMessage = async (data: any) => {
|
|
|
768
749
|
}
|
|
769
750
|
if (!hasAnySection) {
|
|
770
751
|
const emptyHeightmap = new Int16Array(256).fill(EMPTY_COLUMN_HEIGHTMAP_SENTINEL)
|
|
771
|
-
postMessage(
|
|
772
|
-
{ type: 'heightmap', key: `${data.x >> 4},${data.z >> 4}`, heightmap: emptyHeightmap },
|
|
773
|
-
[emptyHeightmap.buffer]
|
|
774
|
-
)
|
|
752
|
+
postMessage({ type: 'heightmap', key: `${data.x >> 4},${data.z >> 4}`, heightmap: emptyHeightmap }, [emptyHeightmap.buffer])
|
|
775
753
|
}
|
|
776
754
|
break
|
|
777
755
|
}
|
|
@@ -828,7 +806,7 @@ const handleMessage = async (data: any) => {
|
|
|
828
806
|
rawMapChunkCache.set(rawCacheKey(data.x, data.z), {
|
|
829
807
|
rawPacket: data.rawPacket as Uint8Array,
|
|
830
808
|
protocol: data.protocol as number,
|
|
831
|
-
numSections: data.numSections as number
|
|
809
|
+
numSections: data.numSections as number
|
|
832
810
|
})
|
|
833
811
|
invalidateConversion(data.x, data.z)
|
|
834
812
|
break
|
|
@@ -841,7 +819,7 @@ const handleMessage = async (data: any) => {
|
|
|
841
819
|
maxBitsPerBlock: data.maxBitsPerBlock as number,
|
|
842
820
|
chunkData: data.chunkData as Uint8Array,
|
|
843
821
|
bitMapLoHi: data.bitMapLoHi as Uint32Array,
|
|
844
|
-
biomes: data.biomes as Int32Array | undefined
|
|
822
|
+
biomes: data.biomes as Int32Array | undefined
|
|
845
823
|
})
|
|
846
824
|
invalidateConversion(data.x, data.z)
|
|
847
825
|
break
|
|
@@ -865,7 +843,7 @@ const handleMessage = async (data: any) => {
|
|
|
865
843
|
protocol: data.protocol as number,
|
|
866
844
|
chunkData: data.chunkData as Uint8Array,
|
|
867
845
|
bitMap: data.bitMap as number,
|
|
868
|
-
biomes: data.biomes as Int32Array
|
|
846
|
+
biomes: data.biomes as Int32Array
|
|
869
847
|
})
|
|
870
848
|
invalidateConversion(data.x, data.z)
|
|
871
849
|
break
|
|
@@ -898,7 +876,7 @@ const handleMessage = async (data: any) => {
|
|
|
898
876
|
type: 'mc-web-pong',
|
|
899
877
|
workerIndex: replyWorkerIndex,
|
|
900
878
|
t: data.t,
|
|
901
|
-
recvAt: typeof performance !== 'undefined' ? performance.now() : undefined
|
|
879
|
+
recvAt: typeof performance !== 'undefined' ? performance.now() : undefined
|
|
902
880
|
})
|
|
903
881
|
break
|
|
904
882
|
}
|
|
@@ -908,7 +886,7 @@ const handleMessage = async (data: any) => {
|
|
|
908
886
|
type: 'mc-web-pong',
|
|
909
887
|
workerIndex: replyWorkerIndex,
|
|
910
888
|
t: data.t,
|
|
911
|
-
recvAt: typeof performance !== 'undefined' ? performance.now() : undefined
|
|
889
|
+
recvAt: typeof performance !== 'undefined' ? performance.now() : undefined
|
|
912
890
|
})
|
|
913
891
|
break
|
|
914
892
|
}
|
|
@@ -918,7 +896,7 @@ const handleMessage = async (data: any) => {
|
|
|
918
896
|
type: 'mc-web-pong',
|
|
919
897
|
workerIndex: replyWorkerIndex,
|
|
920
898
|
t: data.t,
|
|
921
|
-
recvAt: typeof performance !== 'undefined' ? performance.now() : undefined
|
|
899
|
+
recvAt: typeof performance !== 'undefined' ? performance.now() : undefined
|
|
922
900
|
})
|
|
923
901
|
break
|
|
924
902
|
}
|
|
@@ -958,11 +936,10 @@ self.onmessage = ({ data }) => {
|
|
|
958
936
|
// Section height is always 16 in column mode (the only WASM path).
|
|
959
937
|
const getSectionHeight = () => SECTION_HEIGHT
|
|
960
938
|
|
|
961
|
-
|
|
962
939
|
// 3x3 X/Z neighbor set for column meshing. Y-agnostic because full-column
|
|
963
940
|
// meshing converts the entire world Y range in one go.
|
|
964
941
|
function collectChunksForColumn(x: number, z: number) {
|
|
965
|
-
const result = [] as Array<{ x: number
|
|
942
|
+
const result = [] as Array<{ x: number; z: number; chunk: any }>
|
|
966
943
|
const target = world.getColumn(x, z)
|
|
967
944
|
if (target) result.push({ x, z, chunk: target })
|
|
968
945
|
const offsets = [-16, 0, 16]
|
|
@@ -1005,7 +982,7 @@ function makeEmptyColumnGeometry(sx: number, sy: number, sz: number, sectionHeig
|
|
|
1005
982
|
signs: {},
|
|
1006
983
|
banners: {},
|
|
1007
984
|
hadErrors,
|
|
1008
|
-
blocksCount: 0
|
|
985
|
+
blocksCount: 0
|
|
1009
986
|
}
|
|
1010
987
|
}
|
|
1011
988
|
|
|
@@ -1023,7 +1000,7 @@ function processColumnTick() {
|
|
|
1023
1000
|
// coords — the same units used by section keys). This guarantees a
|
|
1024
1001
|
// single WASM call per column per tick even when multiple section keys
|
|
1025
1002
|
// of the same column are dirty.
|
|
1026
|
-
const groups = new Map<string, { x: number
|
|
1003
|
+
const groups = new Map<string, { x: number; z: number; sections: Array<{ key: string; x: number; y: number; z: number; count: number }> }>()
|
|
1027
1004
|
for (const [key, count] of dirtySections) {
|
|
1028
1005
|
const [sx, sy, sz] = key.split(',').map(v => parseInt(v, 10))
|
|
1029
1006
|
const colKey = `${sx},${sz}`
|
|
@@ -1040,7 +1017,7 @@ function processColumnTick() {
|
|
|
1040
1017
|
const { x, z, sections } = group
|
|
1041
1018
|
const targetChunk = world.getColumn(x, z)
|
|
1042
1019
|
|
|
1043
|
-
let exportedMap: Map<string, { exported: import('../../three/worldGeometryExport').ExportedSection
|
|
1020
|
+
let exportedMap: Map<string, { exported: import('../../three/worldGeometryExport').ExportedSection; blocksCount: number }> | null = null
|
|
1044
1021
|
let processTime = 0
|
|
1045
1022
|
let prePhase = 0
|
|
1046
1023
|
let wasmPhase = 0
|
|
@@ -1093,20 +1070,38 @@ function processColumnTick() {
|
|
|
1093
1070
|
} else if (v17Entry) {
|
|
1094
1071
|
const v17Light = updateLightV17Cache.get(rawCacheKey(x, z))
|
|
1095
1072
|
wasmResult = meshColumnFromParsedV16V17(
|
|
1096
|
-
v17Entry.chunkData,
|
|
1097
|
-
v17Entry.
|
|
1098
|
-
|
|
1099
|
-
|
|
1073
|
+
v17Entry.chunkData,
|
|
1074
|
+
v17Entry.bitMapLoHi,
|
|
1075
|
+
v17Entry.numSections,
|
|
1076
|
+
v17Entry.maxBitsPerBlock,
|
|
1077
|
+
v17Entry.biomes,
|
|
1078
|
+
1,
|
|
1079
|
+
v17Light?.skyLight ?? null,
|
|
1080
|
+
v17Light?.blockLight ?? null,
|
|
1081
|
+
x,
|
|
1082
|
+
z,
|
|
1083
|
+
worldMinY,
|
|
1084
|
+
worldMaxY,
|
|
1085
|
+
meta
|
|
1100
1086
|
)
|
|
1101
1087
|
if (wasmResult) columnMeshPath = 'v17_fused'
|
|
1102
1088
|
} else if (v16Entry) {
|
|
1103
1089
|
const v16Light = updateLightV16Cache.get(rawCacheKey(x, z))
|
|
1104
1090
|
const bitMapLoHi = new Uint32Array([v16Entry.bitMap >>> 0, 0])
|
|
1105
1091
|
wasmResult = meshColumnFromParsedV16V17(
|
|
1106
|
-
v16Entry.chunkData,
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1092
|
+
v16Entry.chunkData,
|
|
1093
|
+
bitMapLoHi,
|
|
1094
|
+
16,
|
|
1095
|
+
15,
|
|
1096
|
+
v16Entry.biomes,
|
|
1097
|
+
1,
|
|
1098
|
+
v16Light?.skyLight ?? null,
|
|
1099
|
+
v16Light?.blockLight ?? null,
|
|
1100
|
+
x,
|
|
1101
|
+
z,
|
|
1102
|
+
worldMinY,
|
|
1103
|
+
worldMaxY,
|
|
1104
|
+
meta
|
|
1110
1105
|
)
|
|
1111
1106
|
if (wasmResult) columnMeshPath = 'v16_fused'
|
|
1112
1107
|
}
|
|
@@ -1126,8 +1121,9 @@ function processColumnTick() {
|
|
|
1126
1121
|
// or any helper returns null.
|
|
1127
1122
|
// ------------------------------------------------------------------
|
|
1128
1123
|
if (!wasmResult && chunkCount > 1) {
|
|
1129
|
-
wasmResult =
|
|
1130
|
-
|
|
1124
|
+
wasmResult =
|
|
1125
|
+
meshMultiColumnsFromRawV18Plus(chunksToUse, x, z, worldMinY, worldMaxY, meta) ??
|
|
1126
|
+
meshMultiColumnsFromParsedV16V17(chunksToUse, x, z, worldMinY, worldMaxY, meta)
|
|
1131
1127
|
if (wasmResult) {
|
|
1132
1128
|
columnMeshPath = 'multi_fused'
|
|
1133
1129
|
usedFusedPath = true
|
|
@@ -1168,7 +1164,12 @@ function processColumnTick() {
|
|
|
1168
1164
|
// JS-fallback (column walk) — still cached, since this is the
|
|
1169
1165
|
// expensive path the conversion cache was built for.
|
|
1170
1166
|
const cached = getOrConvertColumn(
|
|
1171
|
-
cx,
|
|
1167
|
+
cx,
|
|
1168
|
+
cz,
|
|
1169
|
+
chunk,
|
|
1170
|
+
version,
|
|
1171
|
+
worldMinY,
|
|
1172
|
+
worldMaxY,
|
|
1172
1173
|
() => convertChunkToWasm(chunk, version, cx, cz, worldMinY, worldMaxY),
|
|
1173
1174
|
chunk
|
|
1174
1175
|
)
|
|
@@ -1188,23 +1189,28 @@ function processColumnTick() {
|
|
|
1188
1189
|
return conv
|
|
1189
1190
|
})
|
|
1190
1191
|
|
|
1191
|
-
const {
|
|
1192
|
-
invisibleBlocks,
|
|
1193
|
-
transparentBlocks,
|
|
1194
|
-
noAoBlocks,
|
|
1195
|
-
cullIdenticalBlocks,
|
|
1196
|
-
occludingBlocks,
|
|
1197
|
-
} = conversions[0]
|
|
1192
|
+
const { invisibleBlocks, transparentBlocks, noAoBlocks, cullIdenticalBlocks, occludingBlocks } = conversions[0]
|
|
1198
1193
|
|
|
1199
1194
|
if (chunkCount === 1 || !(wasm as any).generate_geometry_multi) {
|
|
1200
1195
|
const { blockStates, blockLight, skyLight, biomesArray } = conversions[0]
|
|
1201
1196
|
t1 = performance.now()
|
|
1202
1197
|
wasmResult = wasm.generate_geometry(
|
|
1203
|
-
x,
|
|
1204
|
-
worldMinY,
|
|
1198
|
+
x,
|
|
1199
|
+
worldMinY,
|
|
1200
|
+
z,
|
|
1201
|
+
columnHeight,
|
|
1202
|
+
worldMinY,
|
|
1203
|
+
worldMaxY,
|
|
1205
1204
|
worldMinY,
|
|
1206
|
-
blockStates,
|
|
1207
|
-
|
|
1205
|
+
blockStates,
|
|
1206
|
+
blockLight,
|
|
1207
|
+
skyLight,
|
|
1208
|
+
biomesArray,
|
|
1209
|
+
invisibleBlocks,
|
|
1210
|
+
transparentBlocks,
|
|
1211
|
+
noAoBlocks,
|
|
1212
|
+
cullIdenticalBlocks,
|
|
1213
|
+
occludingBlocks,
|
|
1208
1214
|
config?.enableLighting !== false,
|
|
1209
1215
|
config?.smoothLighting !== false,
|
|
1210
1216
|
config?.skyLight ?? 15
|
|
@@ -1233,12 +1239,24 @@ function processColumnTick() {
|
|
|
1233
1239
|
|
|
1234
1240
|
t1 = performance.now()
|
|
1235
1241
|
wasmResult = (wasm as any).generate_geometry_multi(
|
|
1236
|
-
x,
|
|
1237
|
-
worldMinY, worldMaxY,
|
|
1242
|
+
x,
|
|
1238
1243
|
worldMinY,
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1244
|
+
z,
|
|
1245
|
+
columnHeight,
|
|
1246
|
+
worldMinY,
|
|
1247
|
+
worldMaxY,
|
|
1248
|
+
worldMinY,
|
|
1249
|
+
xs,
|
|
1250
|
+
zs,
|
|
1251
|
+
blockStatesAll,
|
|
1252
|
+
blockLightAll,
|
|
1253
|
+
skyLightAll,
|
|
1254
|
+
biomesAll,
|
|
1255
|
+
invisibleBlocks,
|
|
1256
|
+
transparentBlocks,
|
|
1257
|
+
noAoBlocks,
|
|
1258
|
+
cullIdenticalBlocks,
|
|
1259
|
+
occludingBlocks,
|
|
1242
1260
|
config?.enableLighting !== false,
|
|
1243
1261
|
config?.smoothLighting !== false,
|
|
1244
1262
|
config?.skyLight ?? 15
|
|
@@ -1256,16 +1274,12 @@ function processColumnTick() {
|
|
|
1256
1274
|
// intentionally skipped (the request tracker would warn if we
|
|
1257
1275
|
// emitted sectionFinished for them).
|
|
1258
1276
|
const requestedSectionKeys = sections.map(s => ({ x: s.x, y: s.y, z: s.z }))
|
|
1259
|
-
exportedMap = splitColumnWasmOutputToSections(
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
sectionHeight,
|
|
1266
|
-
shaderCubes: config?.shaderCubeBlocks === true,
|
|
1267
|
-
},
|
|
1268
|
-
)
|
|
1277
|
+
exportedMap = splitColumnWasmOutputToSections(wasmResult, requestedSectionKeys, {
|
|
1278
|
+
version,
|
|
1279
|
+
world,
|
|
1280
|
+
sectionHeight,
|
|
1281
|
+
shaderCubes: config?.shaderCubeBlocks === true
|
|
1282
|
+
})
|
|
1269
1283
|
|
|
1270
1284
|
// Push heightmap from the WASM column output. With column meshing as
|
|
1271
1285
|
// the only WASM path, the main thread does not request heightmaps
|
|
@@ -1313,7 +1327,7 @@ function processColumnTick() {
|
|
|
1313
1327
|
// finalized — otherwise the totals attached to the first event
|
|
1314
1328
|
// would miss the typed-array allocation, block-entity walk, and
|
|
1315
1329
|
// postMessage cost of every section in this column.
|
|
1316
|
-
const finished: Array<{ key: string
|
|
1330
|
+
const finished: Array<{ key: string; count: number }> = []
|
|
1317
1331
|
for (const s of sections) {
|
|
1318
1332
|
const { key, x: sx, y: sy, z: sz, count } = s
|
|
1319
1333
|
|
|
@@ -1346,9 +1360,7 @@ function processColumnTick() {
|
|
|
1346
1360
|
const hasLegacyMesh = hasOpaqueMesh || hasBlendMesh
|
|
1347
1361
|
const hasShaderCubes = (exported?.shaderCubes?.count ?? 0) > 0
|
|
1348
1362
|
if (exported && (hasLegacyMesh || hasShaderCubes)) {
|
|
1349
|
-
const maxIndex = exported.geometry.indices.length > 0
|
|
1350
|
-
? Math.max(...exported.geometry.indices)
|
|
1351
|
-
: 0
|
|
1363
|
+
const maxIndex = exported.geometry.indices.length > 0 ? Math.max(...exported.geometry.indices) : 0
|
|
1352
1364
|
const using32Array = maxIndex > 65535
|
|
1353
1365
|
geometry = {
|
|
1354
1366
|
sectionYNumber: (sy - (config?.worldMinY || 0)) >> 4,
|
|
@@ -1368,9 +1380,7 @@ function processColumnTick() {
|
|
|
1368
1380
|
skyLights: new Float32Array(exported.geometry.skyLights),
|
|
1369
1381
|
blockLights: new Float32Array(exported.geometry.blockLights),
|
|
1370
1382
|
uvs: new Float32Array(exported.geometry.uvs),
|
|
1371
|
-
indices: using32Array
|
|
1372
|
-
? new Uint32Array(exported.geometry.indices)
|
|
1373
|
-
: new Uint16Array(exported.geometry.indices),
|
|
1383
|
+
indices: using32Array ? new Uint32Array(exported.geometry.indices) : new Uint16Array(exported.geometry.indices),
|
|
1374
1384
|
indicesCount: exported.geometry.indices.length,
|
|
1375
1385
|
using32Array,
|
|
1376
1386
|
tiles: {},
|
|
@@ -1383,13 +1393,13 @@ function processColumnTick() {
|
|
|
1383
1393
|
// `B:` debug overlay stat) and matches the per-section path's
|
|
1384
1394
|
// semantics: number of blocks that contributed faces to this
|
|
1385
1395
|
// section's geometry.
|
|
1386
|
-
blocksCount: sectionBlocksCount
|
|
1396
|
+
blocksCount: sectionBlocksCount
|
|
1387
1397
|
}
|
|
1388
1398
|
if (exported.shaderCubes) {
|
|
1389
1399
|
geometry.shaderCubes = {
|
|
1390
1400
|
words: new Uint32Array(exported.shaderCubes.words),
|
|
1391
1401
|
count: exported.shaderCubes.count,
|
|
1392
|
-
formatVersion: 3
|
|
1402
|
+
formatVersion: 3
|
|
1393
1403
|
}
|
|
1394
1404
|
}
|
|
1395
1405
|
if (exported.blendGeometry && hasBlendMesh) {
|
|
@@ -1401,9 +1411,7 @@ function processColumnTick() {
|
|
|
1401
1411
|
skyLights: new Float32Array(exported.blendGeometry.skyLights),
|
|
1402
1412
|
blockLights: new Float32Array(exported.blendGeometry.blockLights),
|
|
1403
1413
|
uvs: new Float32Array(exported.blendGeometry.uvs),
|
|
1404
|
-
indices: blendMax > 65535
|
|
1405
|
-
? new Uint32Array(exported.blendGeometry.indices)
|
|
1406
|
-
: new Uint16Array(exported.blendGeometry.indices),
|
|
1414
|
+
indices: blendMax > 65535 ? new Uint32Array(exported.blendGeometry.indices) : new Uint16Array(exported.blendGeometry.indices)
|
|
1407
1415
|
}
|
|
1408
1416
|
}
|
|
1409
1417
|
transferable = [
|
|
@@ -1423,14 +1431,15 @@ function processColumnTick() {
|
|
|
1423
1431
|
geometry.blend?.uvs?.buffer,
|
|
1424
1432
|
//@ts-ignore
|
|
1425
1433
|
geometry.blend?.indices?.buffer,
|
|
1426
|
-
geometry.shaderCubes?.words?.buffer
|
|
1434
|
+
geometry.shaderCubes?.words?.buffer
|
|
1427
1435
|
].filter(Boolean)
|
|
1428
1436
|
|
|
1429
1437
|
if (exported.geometry.indices.length > 0 && config.computeWireframeEdges) {
|
|
1430
1438
|
try {
|
|
1431
|
-
const wireframeF32 =
|
|
1432
|
-
|
|
1433
|
-
|
|
1439
|
+
const wireframeF32 =
|
|
1440
|
+
geometry.indices instanceof Uint32Array
|
|
1441
|
+
? wasm!.computeWireframeEdges(geometry.positions as Float32Array, geometry.indices)
|
|
1442
|
+
: wasm!.computeWireframeEdgesU16(geometry.positions as Float32Array, geometry.indices as Uint16Array)
|
|
1434
1443
|
if (wireframeF32.length > 0) {
|
|
1435
1444
|
geometry.wireframePositions = wireframeF32
|
|
1436
1445
|
transferable.push(wireframeF32.buffer)
|
|
@@ -1488,7 +1497,7 @@ function processColumnTick() {
|
|
|
1488
1497
|
preTypedArrayBuild: !attributed ? preTypedArrayBuild : 0,
|
|
1489
1498
|
preOther: !attributed ? preOther : 0,
|
|
1490
1499
|
preCacheHits: !attributed ? preCacheHits : 0,
|
|
1491
|
-
preCacheMisses: !attributed ? preCacheMisses : 0
|
|
1500
|
+
preCacheMisses: !attributed ? preCacheMisses : 0
|
|
1492
1501
|
})
|
|
1493
1502
|
attributed = true
|
|
1494
1503
|
}
|
|
@@ -78,13 +78,7 @@ export function getOrConvertColumn(
|
|
|
78
78
|
return { result: convert(), hit: false }
|
|
79
79
|
}
|
|
80
80
|
const e = cache.get(k)
|
|
81
|
-
if (
|
|
82
|
-
e
|
|
83
|
-
&& e.chunkRef === chunkRef
|
|
84
|
-
&& e.version === version
|
|
85
|
-
&& e.worldMinY === worldMinY
|
|
86
|
-
&& e.worldMaxY === worldMaxY
|
|
87
|
-
) {
|
|
81
|
+
if (e && e.chunkRef === chunkRef && e.version === version && e.worldMinY === worldMinY && e.worldMaxY === worldMaxY) {
|
|
88
82
|
// Defense-in-depth: if the live world ref no longer matches the stored
|
|
89
83
|
// ref, the explicit invalidation path was missed somewhere upstream.
|
|
90
84
|
if (liveChunkRef !== undefined && liveChunkRef !== e.chunkRef) {
|
|
@@ -142,7 +136,7 @@ export function getConversionCacheSize(): number {
|
|
|
142
136
|
return cache.size
|
|
143
137
|
}
|
|
144
138
|
|
|
145
|
-
export function consumeConversionCacheStats(): { hits: number
|
|
139
|
+
export function consumeConversionCacheStats(): { hits: number; misses: number } {
|
|
146
140
|
const r = { hits, misses }
|
|
147
141
|
hits = 0
|
|
148
142
|
misses = 0
|