minecraft-renderer 0.1.63 → 0.1.64
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 +1 -1
- package/dist/mesherWasm.js +22 -22
- package/dist/minecraft-renderer.js +19 -19
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +339 -339
- package/package.json +1 -1
- package/src/graphicsBackend/rendererDefaultOptions.ts +41 -24
- package/src/graphicsBackend/rendererOptionsSync.ts +23 -23
- package/src/index.ts +8 -8
- package/src/lib/worldrendererCommon.removeColumn.test.ts +182 -0
- package/src/lib/worldrendererCommon.ts +16 -6
- package/src/three/entities.ts +15 -10
- package/src/three/menuBackground/activeView.ts +1 -1
- package/src/three/menuBackground/config.ts +9 -9
- package/src/three/menuBackground/index.ts +10 -10
- package/src/three/menuBackground/renderer.ts +12 -12
- package/src/three/menuBackground/types.ts +9 -9
- package/src/three/menuBackground/{futuristic.ts → v2.ts} +110 -59
- package/src/three/menuBackground/{futuristicMeta.ts → v2Meta.ts} +6 -6
- package/src/wasm-mesher/tests/mesherWasmRequestTracker.test.ts +29 -0
- package/src/wasm-mesher/worker/mesherWasm.ts +7 -0
- package/src/wasm-mesher/worker/mesherWasmRequestTracker.ts +10 -0
- package/src/worldView/worldView.spiral.test.ts +38 -0
- package/src/worldView/worldView.ts +2 -0
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
V2_CAMERA_IDS,
|
|
4
|
+
V2_CAMERA_LABELS,
|
|
5
|
+
V2_SCENE_IDS,
|
|
6
|
+
V2_SCENE_LABELS,
|
|
7
7
|
MINECRAFT_BLOCK_GROUP_IDS,
|
|
8
8
|
MINECRAFT_BLOCK_GROUP_LABELS
|
|
9
|
-
} from '../three/menuBackground/
|
|
9
|
+
} from '../three/menuBackground/v2Meta'
|
|
10
10
|
import { MENU_BACKGROUND_OPTION_DEFAULTS } from '../three/menuBackground/config'
|
|
11
11
|
import type { RendererGpuPreference } from '../three/menuBackground/gpuPreference'
|
|
12
12
|
|
|
@@ -54,11 +54,11 @@ export const RENDERER_DEFAULT_OPTIONS = {
|
|
|
54
54
|
defaultSkybox: true as boolean,
|
|
55
55
|
menuBackgroundMode: MB.mode,
|
|
56
56
|
menuBackgroundMinecraftTextures: MB.minecraftTextures as boolean,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
menuBackgroundV2Scene: MB.v2Scene,
|
|
58
|
+
menuBackgroundV2Camera: MB.v2Camera,
|
|
59
|
+
menuBackgroundV2BlockGroup: MB.v2BlockGroup,
|
|
60
|
+
menuBackgroundV2CameraSpeed: MB.v2CameraSpeedPercent,
|
|
61
|
+
menuBackgroundV2BlockSpeed: MB.v2BlockSpeedPercent,
|
|
62
62
|
rendererFuturisticReveal: false as boolean,
|
|
63
63
|
rendererPerfDebugOverlay: false as boolean,
|
|
64
64
|
disableBlockEntityTextures: false as boolean,
|
|
@@ -110,37 +110,54 @@ export function migrateRendererOptions(saved: Record<string, unknown>): void {
|
|
|
110
110
|
}
|
|
111
111
|
delete saved.wasmExperimentalMesher
|
|
112
112
|
delete saved.rendererWasmMesher
|
|
113
|
+
|
|
114
|
+
if (saved.menuBackgroundMode === 'futuristic') {
|
|
115
|
+
saved.menuBackgroundMode = 'v2'
|
|
116
|
+
}
|
|
117
|
+
const futuristicToV2: Array<[string, string]> = [
|
|
118
|
+
['menuBackgroundFuturisticScene', 'menuBackgroundV2Scene'],
|
|
119
|
+
['menuBackgroundFuturisticCamera', 'menuBackgroundV2Camera'],
|
|
120
|
+
['menuBackgroundFuturisticBlockGroup', 'menuBackgroundV2BlockGroup'],
|
|
121
|
+
['menuBackgroundFuturisticCameraSpeed', 'menuBackgroundV2CameraSpeed'],
|
|
122
|
+
['menuBackgroundFuturisticBlockSpeed', 'menuBackgroundV2BlockSpeed'],
|
|
123
|
+
]
|
|
124
|
+
for (const [oldKey, newKey] of futuristicToV2) {
|
|
125
|
+
if (saved[oldKey] !== undefined && saved[newKey] === undefined) {
|
|
126
|
+
saved[newKey] = saved[oldKey]
|
|
127
|
+
}
|
|
128
|
+
delete saved[oldKey]
|
|
129
|
+
}
|
|
113
130
|
}
|
|
114
131
|
|
|
115
132
|
/** Settings UI metadata for {@link RENDERER_DEFAULT_OPTIONS} keys. */
|
|
116
133
|
export const RENDERER_OPTIONS_META: Partial<Record<RendererDefaultOptionKey, RendererOptionMeta>> = {
|
|
117
134
|
menuBackgroundMode: {
|
|
118
|
-
possibleValues: [['classic', 'Classic'], ['
|
|
135
|
+
possibleValues: [['classic', 'Classic'], ['v2', 'V2']],
|
|
119
136
|
requiresRestart: true
|
|
120
137
|
},
|
|
121
138
|
menuBackgroundMinecraftTextures: {
|
|
122
139
|
text: 'Minecraft block textures',
|
|
123
|
-
tooltip: 'Use block atlas on
|
|
140
|
+
tooltip: 'Use block atlas on V2 menu cubes (loads assets on menu)'
|
|
124
141
|
},
|
|
125
|
-
|
|
126
|
-
possibleValues:
|
|
142
|
+
menuBackgroundV2Scene: {
|
|
143
|
+
possibleValues: V2_SCENE_IDS.map(id => [id, V2_SCENE_LABELS[id]] as [string, string])
|
|
127
144
|
},
|
|
128
|
-
|
|
129
|
-
possibleValues:
|
|
145
|
+
menuBackgroundV2Camera: {
|
|
146
|
+
possibleValues: V2_CAMERA_IDS.map(id => [id, V2_CAMERA_LABELS[id]] as [string, string])
|
|
130
147
|
},
|
|
131
|
-
|
|
148
|
+
menuBackgroundV2BlockGroup: {
|
|
132
149
|
possibleValues: MINECRAFT_BLOCK_GROUP_IDS.map(id => [id, MINECRAFT_BLOCK_GROUP_LABELS[id]] as [string, string]),
|
|
133
150
|
text: 'Block pool',
|
|
134
151
|
tooltip: 'Block set for textured menu cubes (requires Minecraft textures)'
|
|
135
152
|
},
|
|
136
|
-
|
|
153
|
+
menuBackgroundV2CameraSpeed: {
|
|
137
154
|
text: 'Camera speed',
|
|
138
155
|
tooltip: 'Orbit / fly-through camera path speed. 0 freezes the path; mouse parallax still works.',
|
|
139
156
|
min: 0,
|
|
140
157
|
max: 200,
|
|
141
158
|
unit: '%'
|
|
142
159
|
},
|
|
143
|
-
|
|
160
|
+
menuBackgroundV2BlockSpeed: {
|
|
144
161
|
text: 'Block speed',
|
|
145
162
|
tooltip: 'Floating blocks and sky rotation. Independent of camera path speed.',
|
|
146
163
|
min: 0,
|
|
@@ -315,11 +332,11 @@ export const RENDERER_RENDER_GUI_SECTIONS: ReadonlyArray<{
|
|
|
315
332
|
keys: [
|
|
316
333
|
'menuBackgroundMode',
|
|
317
334
|
'menuBackgroundMinecraftTextures',
|
|
318
|
-
'
|
|
319
|
-
'
|
|
320
|
-
'
|
|
321
|
-
'
|
|
322
|
-
'
|
|
335
|
+
'menuBackgroundV2Scene',
|
|
336
|
+
'menuBackgroundV2Camera',
|
|
337
|
+
'menuBackgroundV2BlockGroup',
|
|
338
|
+
'menuBackgroundV2CameraSpeed',
|
|
339
|
+
'menuBackgroundV2BlockSpeed'
|
|
323
340
|
]
|
|
324
341
|
},
|
|
325
342
|
{
|
|
@@ -11,7 +11,7 @@ import { rendererShaderCubeDebugModeToValue } from './rendererDefaultOptions'
|
|
|
11
11
|
import type { MenuBackgroundOptions } from '../three/menuBackground/types'
|
|
12
12
|
import type { MenuBackgroundRenderer } from '../three/menuBackground/renderer'
|
|
13
13
|
import { menuBackgroundSpeedToMultiplier } from '../three/menuBackground/config'
|
|
14
|
-
import type {
|
|
14
|
+
import type { V2CameraId, V2SceneId, MinecraftBlockGroupId } from '../three/menuBackground/v2'
|
|
15
15
|
import { setSkinsConfig } from '../lib/utils/skins'
|
|
16
16
|
|
|
17
17
|
export type { RendererStorageOptions } from './rendererDefaultOptions'
|
|
@@ -37,20 +37,20 @@ export function menuBackgroundOptionsFromStorage(o: Pick<
|
|
|
37
37
|
RendererStorageOptions,
|
|
38
38
|
| 'menuBackgroundMode'
|
|
39
39
|
| 'menuBackgroundMinecraftTextures'
|
|
40
|
-
| '
|
|
41
|
-
| '
|
|
42
|
-
| '
|
|
43
|
-
| '
|
|
44
|
-
| '
|
|
40
|
+
| 'menuBackgroundV2Scene'
|
|
41
|
+
| 'menuBackgroundV2Camera'
|
|
42
|
+
| 'menuBackgroundV2BlockGroup'
|
|
43
|
+
| 'menuBackgroundV2CameraSpeed'
|
|
44
|
+
| 'menuBackgroundV2BlockSpeed'
|
|
45
45
|
>): MenuBackgroundOptions {
|
|
46
46
|
return {
|
|
47
47
|
mode: o.menuBackgroundMode as MenuBackgroundOptions['mode'],
|
|
48
48
|
useMinecraftTextures: o.menuBackgroundMinecraftTextures,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
v2Scene: o.menuBackgroundV2Scene as V2SceneId,
|
|
50
|
+
v2Camera: o.menuBackgroundV2Camera as V2CameraId,
|
|
51
|
+
v2BlockGroup: o.menuBackgroundV2BlockGroup as MinecraftBlockGroupId,
|
|
52
|
+
v2CameraSpeed: menuBackgroundSpeedToMultiplier(o.menuBackgroundV2CameraSpeed),
|
|
53
|
+
v2BlockSpeed: menuBackgroundSpeedToMultiplier(o.menuBackgroundV2BlockSpeed),
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
@@ -58,20 +58,20 @@ export function applyMenuBackgroundLiveOptions(
|
|
|
58
58
|
menu: MenuBackgroundRenderer,
|
|
59
59
|
o: Pick<
|
|
60
60
|
RendererStorageOptions,
|
|
61
|
-
| '
|
|
62
|
-
| '
|
|
63
|
-
| '
|
|
64
|
-
| '
|
|
65
|
-
| '
|
|
61
|
+
| 'menuBackgroundV2Scene'
|
|
62
|
+
| 'menuBackgroundV2Camera'
|
|
63
|
+
| 'menuBackgroundV2BlockGroup'
|
|
64
|
+
| 'menuBackgroundV2CameraSpeed'
|
|
65
|
+
| 'menuBackgroundV2BlockSpeed'
|
|
66
66
|
>
|
|
67
67
|
): void {
|
|
68
|
-
const
|
|
69
|
-
if (!
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
void
|
|
73
|
-
|
|
74
|
-
|
|
68
|
+
const v2 = menu.v2
|
|
69
|
+
if (!v2) return
|
|
70
|
+
v2.setScene?.(o.menuBackgroundV2Scene)
|
|
71
|
+
v2.setCamera?.(o.menuBackgroundV2Camera)
|
|
72
|
+
void v2.setBlockGroup?.(o.menuBackgroundV2BlockGroup)
|
|
73
|
+
v2.setCameraSpeed?.(menuBackgroundSpeedToMultiplier(o.menuBackgroundV2CameraSpeed))
|
|
74
|
+
v2.setBlockSpeed?.(menuBackgroundSpeedToMultiplier(o.menuBackgroundV2BlockSpeed))
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function resolveWasmMesherActive(o: RendererStorageOptions): boolean {
|
package/src/index.ts
CHANGED
|
@@ -85,21 +85,21 @@ export type {
|
|
|
85
85
|
MenuBackgroundMode,
|
|
86
86
|
MenuBackgroundOptions,
|
|
87
87
|
MenuBackgroundView,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
V2SceneId,
|
|
89
|
+
V2CameraId,
|
|
90
|
+
V2MenuBackgroundOptions,
|
|
91
91
|
MinecraftBlockGroupId
|
|
92
92
|
} from './three/menuBackground'
|
|
93
93
|
export {
|
|
94
94
|
MenuBackgroundRenderer,
|
|
95
95
|
ClassicMenuBackground,
|
|
96
|
-
|
|
96
|
+
V2MenuBackground,
|
|
97
97
|
WorldBlocksMenuBackground,
|
|
98
98
|
MENU_BACKGROUND_MC_VERSION,
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
99
|
+
V2_SCENE_IDS,
|
|
100
|
+
V2_CAMERA_IDS,
|
|
101
|
+
V2_SCENE_LABELS,
|
|
102
|
+
V2_CAMERA_LABELS,
|
|
103
103
|
MINECRAFT_BLOCK_GROUPS,
|
|
104
104
|
MINECRAFT_BLOCK_GROUP_IDS,
|
|
105
105
|
MINECRAFT_BLOCK_GROUP_LABELS,
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { EventEmitter } from 'events'
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from 'vitest'
|
|
4
|
+
import { Vec3 } from 'vec3'
|
|
5
|
+
import { proxy } from 'valtio'
|
|
6
|
+
import { WorldRendererCommon } from './worldrendererCommon'
|
|
7
|
+
import { defaultWorldRendererConfig } from '../graphicsBackend/config'
|
|
8
|
+
import { getInitialPlayerState } from '../playerState/playerState'
|
|
9
|
+
import type { DisplayWorldOptions, GraphicsInitOptions } from '../graphicsBackend/types'
|
|
10
|
+
|
|
11
|
+
vi.mock('./ui/newStats', () => ({
|
|
12
|
+
addNewStat: vi.fn(() => ({ updateText: vi.fn(), setVisibility: vi.fn() })),
|
|
13
|
+
updateStatText: vi.fn(),
|
|
14
|
+
removeAllStats: vi.fn(),
|
|
15
|
+
updatePanesVisibility: vi.fn(),
|
|
16
|
+
MC_RENDERER_DEBUG_OVERLAY_CLASS: 'mc-renderer-debug-overlay',
|
|
17
|
+
}))
|
|
18
|
+
|
|
19
|
+
vi.mock('./utils/skins', () => ({
|
|
20
|
+
setSkinsConfig: vi.fn(),
|
|
21
|
+
steveTexture: {},
|
|
22
|
+
stevePngUrl: '',
|
|
23
|
+
}))
|
|
24
|
+
|
|
25
|
+
function ensurePromiseWithResolvers() {
|
|
26
|
+
if (!Promise.withResolvers) {
|
|
27
|
+
Promise.withResolvers = function <T>() {
|
|
28
|
+
let resolve!: (value: T | PromiseLike<T>) => void
|
|
29
|
+
let reject!: (reason?: unknown) => void
|
|
30
|
+
const promise = new Promise<T>((res, rej) => {
|
|
31
|
+
resolve = res
|
|
32
|
+
reject = rej
|
|
33
|
+
})
|
|
34
|
+
return { promise, resolve, reject }
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
class TestWorldRenderer extends WorldRendererCommon {
|
|
40
|
+
outputFormat = 'threeJs' as const
|
|
41
|
+
|
|
42
|
+
changeBackgroundColor() {}
|
|
43
|
+
changeCardinalLight() {}
|
|
44
|
+
handleWorkerMessage() {}
|
|
45
|
+
updateCamera() {}
|
|
46
|
+
render() {}
|
|
47
|
+
updateShowChunksBorder() {}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function createRenderer() {
|
|
51
|
+
const rendererState = proxy({
|
|
52
|
+
world: {
|
|
53
|
+
chunksLoaded: new Set<string>(),
|
|
54
|
+
heightmaps: new Map<string, Int16Array>(),
|
|
55
|
+
allChunksLoaded: false,
|
|
56
|
+
mesherWork: false,
|
|
57
|
+
instabilityFactors: {},
|
|
58
|
+
intersectMedia: null,
|
|
59
|
+
},
|
|
60
|
+
renderer: '',
|
|
61
|
+
preventEscapeMenu: false,
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const displayOptions = {
|
|
65
|
+
version: '1.21.1',
|
|
66
|
+
worldView: new EventEmitter() as DisplayWorldOptions['worldView'],
|
|
67
|
+
inWorldRenderingConfig: { ...defaultWorldRendererConfig },
|
|
68
|
+
playerStateReactive: getInitialPlayerState(),
|
|
69
|
+
rendererState,
|
|
70
|
+
nonReactiveState: {
|
|
71
|
+
fps: 0,
|
|
72
|
+
worstRenderTime: 0,
|
|
73
|
+
avgRenderTime: 0,
|
|
74
|
+
world: {
|
|
75
|
+
chunksLoaded: new Set<string>(),
|
|
76
|
+
chunksTotalNumber: 0,
|
|
77
|
+
chunksFullInfo: '',
|
|
78
|
+
},
|
|
79
|
+
renderer: {
|
|
80
|
+
timeline: { live: [], frozen: [], lastSecond: [] },
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
resourcesManager: {} as DisplayWorldOptions['resourcesManager'],
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const initOptions: GraphicsInitOptions = {
|
|
87
|
+
config: { sceneBackground: '#000' },
|
|
88
|
+
rendererSpecificSettings: {},
|
|
89
|
+
callbacks: {
|
|
90
|
+
displayCriticalError: vi.fn(),
|
|
91
|
+
setRendererSpecificSettings: vi.fn(),
|
|
92
|
+
fireCustomEvent: vi.fn(),
|
|
93
|
+
},
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const renderer = new TestWorldRenderer(displayOptions.resourcesManager, displayOptions, initOptions)
|
|
97
|
+
renderer.active = true
|
|
98
|
+
renderer.workers = [{ postMessage: vi.fn() }, { postMessage: vi.fn() }]
|
|
99
|
+
renderer.viewDistance = 16
|
|
100
|
+
renderer.viewerChunkPosition = new Vec3(0, 64, 0)
|
|
101
|
+
renderer.worldSizeParams = { minY: 0, worldHeight: 256 }
|
|
102
|
+
renderer.loadedChunks['160,0'] = true
|
|
103
|
+
return renderer
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function sectionKeysForColumn(renderer: TestWorldRenderer, x: number, z: number): string[] {
|
|
107
|
+
const keys: string[] = []
|
|
108
|
+
const sectionHeight = renderer.getSectionHeight()
|
|
109
|
+
for (let y = renderer.worldMinYRender; y < renderer.worldSizeParams.worldHeight; y += sectionHeight) {
|
|
110
|
+
keys.push(`${x},${y},${z}`)
|
|
111
|
+
}
|
|
112
|
+
return keys
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
describe('WorldRendererCommon.removeColumn sectionsWaiting reconciliation', () => {
|
|
116
|
+
beforeEach(() => {
|
|
117
|
+
ensurePromiseWithResolvers()
|
|
118
|
+
vi.useFakeTimers()
|
|
119
|
+
vi.stubGlobal('location', { href: 'http://localhost/' })
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
afterEach(() => {
|
|
123
|
+
vi.useRealTimers()
|
|
124
|
+
vi.unstubAllGlobals()
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
test('clears sectionsWaiting when viewDistance gate blocks setSectionDirty(false)', () => {
|
|
128
|
+
const renderer = createRenderer()
|
|
129
|
+
const columnX = 160
|
|
130
|
+
const columnZ = 0
|
|
131
|
+
const sectionPos = new Vec3(columnX, 64, columnZ)
|
|
132
|
+
|
|
133
|
+
renderer.setSectionDirty(sectionPos, true)
|
|
134
|
+
expect(renderer.sectionsWaiting.get(`${columnX},64,${columnZ}`)).toBe(1)
|
|
135
|
+
|
|
136
|
+
renderer.viewDistance = 4
|
|
137
|
+
renderer.removeColumn(columnX, columnZ)
|
|
138
|
+
|
|
139
|
+
for (const key of sectionKeysForColumn(renderer, columnX, columnZ)) {
|
|
140
|
+
expect(renderer.sectionsWaiting.has(key)).toBe(false)
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
test('treats late sectionFinished as a no-op after removeColumn', () => {
|
|
145
|
+
const renderer = createRenderer()
|
|
146
|
+
const sectionKey = '160,64,0'
|
|
147
|
+
const debugSpy = vi.spyOn(console, 'debug').mockImplementation(() => {})
|
|
148
|
+
|
|
149
|
+
renderer.sectionsWaiting.set(sectionKey, 1)
|
|
150
|
+
renderer.viewDistance = 4
|
|
151
|
+
renderer.removeColumn(160, 0)
|
|
152
|
+
|
|
153
|
+
expect(() => {
|
|
154
|
+
renderer.handleMessage({ type: 'sectionFinished', key: sectionKey, workerIndex: 0 })
|
|
155
|
+
}).not.toThrow()
|
|
156
|
+
|
|
157
|
+
expect(renderer.sectionsWaiting.has(sectionKey)).toBe(false)
|
|
158
|
+
expect(debugSpy).toHaveBeenCalledWith(
|
|
159
|
+
expect.stringContaining('sectionFinished for non-outstanding section'),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
debugSpy.mockRestore()
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
test('clears sectionsWaiting when unload happens before batched dirty flush', () => {
|
|
166
|
+
const renderer = createRenderer()
|
|
167
|
+
renderer.forceCallFromMesherReplayer = false
|
|
168
|
+
const columnX = 160
|
|
169
|
+
const columnZ = 0
|
|
170
|
+
|
|
171
|
+
renderer.setSectionDirty(new Vec3(columnX, 64, columnZ), true)
|
|
172
|
+
expect(renderer.sectionsWaiting.get(`${columnX},64,${columnZ}`)).toBe(1)
|
|
173
|
+
|
|
174
|
+
renderer.viewDistance = 4
|
|
175
|
+
renderer.removeColumn(columnX, columnZ)
|
|
176
|
+
vi.advanceTimersByTime(0)
|
|
177
|
+
|
|
178
|
+
for (const key of sectionKeysForColumn(renderer, columnX, columnZ)) {
|
|
179
|
+
expect(renderer.sectionsWaiting.has(key)).toBe(false)
|
|
180
|
+
}
|
|
181
|
+
})
|
|
182
|
+
})
|
|
@@ -424,7 +424,10 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
|
|
424
424
|
}
|
|
425
425
|
if (data.type === 'sectionFinished') { // on after load & unload section
|
|
426
426
|
this.logWorkerWork(`<- ${data.workerIndex} sectionFinished ${data.key} ${JSON.stringify({ processTime: data.processTime })}`)
|
|
427
|
-
if (!this.sectionsWaiting.has(data.key))
|
|
427
|
+
if (!this.sectionsWaiting.has(data.key)) {
|
|
428
|
+
console.debug(`sectionFinished for non-outstanding section ${data.key} (viewDistance=${this.viewDistance})`)
|
|
429
|
+
return
|
|
430
|
+
}
|
|
428
431
|
this.sectionsWaiting.set(data.key, this.sectionsWaiting.get(data.key)! - 1)
|
|
429
432
|
if (this.sectionsWaiting.get(data.key) === 0) {
|
|
430
433
|
this.sectionsWaiting.delete(data.key)
|
|
@@ -787,9 +790,11 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
|
|
787
790
|
this.sectionDirtyPendingArgs.delete(key)
|
|
788
791
|
}
|
|
789
792
|
}
|
|
790
|
-
for (
|
|
791
|
-
|
|
793
|
+
for (let i = 0; i < this.workers.length; i++) {
|
|
794
|
+
this.toWorkerMessagesQueue[i] ??= []
|
|
795
|
+
this.toWorkerMessagesQueue[i].push({ type: 'unloadChunk', x, z })
|
|
792
796
|
}
|
|
797
|
+
this.dispatchMessages()
|
|
793
798
|
this.logWorkerWork(`-> unloadChunk ${JSON.stringify({ x, z })}`)
|
|
794
799
|
delete this.finishedChunks[`${x},${z}`]
|
|
795
800
|
this.allChunksFinished = Object.keys(this.finishedChunks).length === this.chunksLength
|
|
@@ -798,9 +803,14 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
|
|
798
803
|
this.initialChunkLoadWasStartedIn = undefined
|
|
799
804
|
}
|
|
800
805
|
const sectionHeight = this.getSectionHeight()
|
|
801
|
-
for (let y = this.
|
|
802
|
-
|
|
803
|
-
|
|
806
|
+
for (let y = this.worldMinYRender; y < this.worldSizeParams.worldHeight; y += sectionHeight) {
|
|
807
|
+
const sectionKey = `${x},${y},${z}`
|
|
808
|
+
const waitingCount = this.sectionsWaiting.get(sectionKey)
|
|
809
|
+
if (waitingCount !== undefined && waitingCount > 0) {
|
|
810
|
+
console.debug(`[removeColumn] clearing non-zero sectionsWaiting for ${sectionKey}: ${waitingCount} (chunk ${x},${z}, viewDistance=${this.viewDistance})`)
|
|
811
|
+
}
|
|
812
|
+
this.sectionsWaiting.delete(sectionKey)
|
|
813
|
+
delete this.finishedSections[sectionKey]
|
|
804
814
|
}
|
|
805
815
|
this.highestBlocksByChunks.delete(`${x},${z}`)
|
|
806
816
|
const heightmapKey = `${Math.floor(x / 16)},${Math.floor(z / 16)}`
|
package/src/three/entities.ts
CHANGED
|
@@ -1393,8 +1393,20 @@ export class Entities {
|
|
|
1393
1393
|
})
|
|
1394
1394
|
.start()
|
|
1395
1395
|
}
|
|
1396
|
-
|
|
1397
|
-
|
|
1396
|
+
/** World yaw for the whole model: for PlayerObject skins, rotate body to head look dir; head mesh stays yaw-fixed (pitch only). */
|
|
1397
|
+
let targetYaw: number | undefined
|
|
1398
|
+
if (e.playerObject && overrides?.rotation?.head) {
|
|
1399
|
+
const hy = overrides.rotation.head.y
|
|
1400
|
+
const headYawWorld =
|
|
1401
|
+
typeof hy === 'number' && Number.isFinite(hy) ? hy : entity.yaw
|
|
1402
|
+
if (typeof headYawWorld === 'number' && Number.isFinite(headYawWorld)) {
|
|
1403
|
+
targetYaw = headYawWorld
|
|
1404
|
+
}
|
|
1405
|
+
} else if (typeof entity.yaw === 'number' && Number.isFinite(entity.yaw)) {
|
|
1406
|
+
targetYaw = entity.yaw
|
|
1407
|
+
}
|
|
1408
|
+
if (typeof targetYaw === 'number' && Number.isFinite(targetYaw)) {
|
|
1409
|
+
const dy = shortestYawRadians(e.rotation.y, targetYaw)
|
|
1398
1410
|
// Stop previous rotation tween to prevent accumulation (mirror _posTween)
|
|
1399
1411
|
e.userData._rotTween?.stop()
|
|
1400
1412
|
e.userData._rotTween = new TWEEN.Tween(e.rotation)
|
|
@@ -1404,14 +1416,7 @@ export class Entities {
|
|
|
1404
1416
|
|
|
1405
1417
|
if (e?.playerObject && overrides?.rotation?.head) {
|
|
1406
1418
|
const { playerObject } = e
|
|
1407
|
-
|
|
1408
|
-
const headYawWorld =
|
|
1409
|
-
typeof hy === 'number' && Number.isFinite(hy) ? hy : entity.yaw
|
|
1410
|
-
const headYawOffset =
|
|
1411
|
-
typeof headYawWorld === 'number' && typeof entity.yaw === 'number' && Number.isFinite(headYawWorld) && Number.isFinite(entity.yaw)
|
|
1412
|
-
? shortestYawRadians(entity.yaw, headYawWorld)
|
|
1413
|
-
: 0
|
|
1414
|
-
playerObject.skin.head.rotation.y = headYawOffset
|
|
1419
|
+
playerObject.skin.head.rotation.y = 0
|
|
1415
1420
|
|
|
1416
1421
|
const hp = overrides.rotation.head.x
|
|
1417
1422
|
playerObject.skin.head.rotation.x =
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
2
|
import * as THREE from 'three'
|
|
3
3
|
|
|
4
|
-
/** Contract for a main-menu background implementation (classic cubemap,
|
|
4
|
+
/** Contract for a main-menu background implementation (classic cubemap, v2 scene, etc.). */
|
|
5
5
|
export interface MenuBackgroundView {
|
|
6
6
|
readonly scene: THREE.Scene
|
|
7
7
|
readonly camera: THREE.PerspectiveCamera
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
2
|
import type { MenuBackgroundMode } from './types'
|
|
3
|
-
import type {
|
|
3
|
+
import type { V2CameraId, V2SceneId, MinecraftBlockGroupId } from './v2'
|
|
4
4
|
|
|
5
5
|
/** Single source of truth for menu-background defaults (settings + runtime fallbacks). */
|
|
6
6
|
export const MENU_BACKGROUND_OPTION_DEFAULTS = {
|
|
7
|
-
mode: '
|
|
7
|
+
mode: 'v2' as MenuBackgroundMode,
|
|
8
8
|
minecraftTextures: true as boolean,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
v2Scene: 'light' as V2SceneId,
|
|
10
|
+
v2Camera: 'dive' as V2CameraId,
|
|
11
|
+
v2BlockGroup: 'stainedGlass' as MinecraftBlockGroupId,
|
|
12
12
|
/** 0–200 (%). 100 = 1× motion. */
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
v2CameraSpeedPercent: 80,
|
|
14
|
+
v2BlockSpeedPercent: 40
|
|
15
15
|
} as const
|
|
16
16
|
|
|
17
17
|
export const menuBackgroundSpeedToMultiplier = (percent: number) => percent / 100
|
|
18
18
|
|
|
19
19
|
/** Default camera / block motion multipliers (1 = 100%). */
|
|
20
20
|
export const MENU_BACKGROUND_MOTION_DEFAULTS = {
|
|
21
|
-
camera: menuBackgroundSpeedToMultiplier(MENU_BACKGROUND_OPTION_DEFAULTS.
|
|
22
|
-
block: menuBackgroundSpeedToMultiplier(MENU_BACKGROUND_OPTION_DEFAULTS.
|
|
21
|
+
camera: menuBackgroundSpeedToMultiplier(MENU_BACKGROUND_OPTION_DEFAULTS.v2CameraSpeedPercent),
|
|
22
|
+
block: menuBackgroundSpeedToMultiplier(MENU_BACKGROUND_OPTION_DEFAULTS.v2BlockSpeedPercent)
|
|
23
23
|
} as const
|
|
@@ -6,21 +6,21 @@ export type { MenuBackgroundMode, MenuBackgroundOptions } from './types'
|
|
|
6
6
|
export { resolveMenuBackgroundMode } from './types'
|
|
7
7
|
export { ClassicMenuBackground } from './classic'
|
|
8
8
|
export type {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
V2SceneId,
|
|
10
|
+
V2CameraId,
|
|
11
|
+
V2MenuBackgroundOptions,
|
|
12
12
|
MinecraftBlockGroupId
|
|
13
|
-
} from './
|
|
13
|
+
} from './v2'
|
|
14
14
|
export {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
V2MenuBackground,
|
|
16
|
+
V2_SCENE_IDS,
|
|
17
|
+
V2_CAMERA_IDS,
|
|
18
|
+
V2_SCENE_LABELS,
|
|
19
|
+
V2_CAMERA_LABELS,
|
|
20
20
|
MINECRAFT_BLOCK_GROUPS,
|
|
21
21
|
MINECRAFT_BLOCK_GROUP_IDS,
|
|
22
22
|
MINECRAFT_BLOCK_GROUP_LABELS
|
|
23
|
-
} from './
|
|
23
|
+
} from './v2'
|
|
24
24
|
export { WorldBlocksMenuBackground } from './worldBlocks'
|
|
25
25
|
export { MenuBackgroundRenderer } from './renderer'
|
|
26
26
|
export {
|
|
@@ -3,14 +3,14 @@ import * as THREE from 'three'
|
|
|
3
3
|
import type { GraphicsInitOptions } from '../../graphicsBackend/types'
|
|
4
4
|
import type { DocumentRenderer } from '../documentRenderer'
|
|
5
5
|
import { ClassicMenuBackground } from './classic'
|
|
6
|
-
import {
|
|
6
|
+
import { V2MenuBackground } from './v2'
|
|
7
7
|
import { WorldBlocksMenuBackground } from './worldBlocks'
|
|
8
8
|
import type { MenuBackgroundView } from './activeView'
|
|
9
9
|
import type { MenuBackgroundOptions } from './types'
|
|
10
10
|
import { resolveMenuBackgroundMode } from './types'
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Orchestrates main-menu background rendering (dispatches to classic /
|
|
13
|
+
* Orchestrates main-menu background rendering (dispatches to classic / v2 / world-blocks).
|
|
14
14
|
*/
|
|
15
15
|
export class MenuBackgroundRenderer {
|
|
16
16
|
private active?: MenuBackgroundView
|
|
@@ -27,9 +27,9 @@ export class MenuBackgroundRenderer {
|
|
|
27
27
|
this.mode = resolveMenuBackgroundMode(menuBackgroundOptions, singleFileBuild)
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
/** Active
|
|
31
|
-
get
|
|
32
|
-
return this.active instanceof
|
|
30
|
+
/** Active v2 instance when that style is running. */
|
|
31
|
+
get v2(): V2MenuBackground | undefined {
|
|
32
|
+
return this.active instanceof V2MenuBackground ? this.active : undefined
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
get scene(): THREE.Scene | undefined {
|
|
@@ -64,16 +64,16 @@ export class MenuBackgroundRenderer {
|
|
|
64
64
|
|
|
65
65
|
private createImplementation(options: MenuBackgroundOptions): MenuBackgroundView {
|
|
66
66
|
switch (this.mode) {
|
|
67
|
-
case '
|
|
68
|
-
return new
|
|
67
|
+
case 'v2':
|
|
68
|
+
return new V2MenuBackground(
|
|
69
69
|
this.documentRenderer,
|
|
70
70
|
{
|
|
71
71
|
useMinecraftTextures: options.useMinecraftTextures,
|
|
72
|
-
initialScene: options.
|
|
73
|
-
initialCamera: options.
|
|
74
|
-
initialBlockGroup: options.
|
|
75
|
-
initialCameraSpeed: options.
|
|
76
|
-
initialBlockSpeed: options.
|
|
72
|
+
initialScene: options.v2Scene,
|
|
73
|
+
initialCamera: options.v2Camera,
|
|
74
|
+
initialBlockGroup: options.v2BlockGroup,
|
|
75
|
+
initialCameraSpeed: options.v2CameraSpeed,
|
|
76
|
+
initialBlockSpeed: options.v2BlockSpeed,
|
|
77
77
|
resourcesManager: options.resourcesManager
|
|
78
78
|
},
|
|
79
79
|
this.abortController.signal
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
2
|
import type { ResourcesManager } from '../../resourcesManager/resourcesManager'
|
|
3
|
-
import type {
|
|
3
|
+
import type { V2CameraId, V2SceneId, MinecraftBlockGroupId } from './v2'
|
|
4
4
|
import { MENU_BACKGROUND_OPTION_DEFAULTS } from './config'
|
|
5
5
|
|
|
6
|
-
export type {
|
|
6
|
+
export type { V2CameraId, V2SceneId, MinecraftBlockGroupId } from './v2'
|
|
7
7
|
|
|
8
|
-
export type MenuBackgroundMode = 'classic' | '
|
|
8
|
+
export type MenuBackgroundMode = 'classic' | 'v2' | 'worldBlocks'
|
|
9
9
|
|
|
10
10
|
export interface MenuBackgroundOptions {
|
|
11
11
|
/** Visual style. Defaults to {@link MENU_BACKGROUND_OPTION_DEFAULTS.mode}, or `worldBlocks` in single-file build. */
|
|
12
12
|
mode?: MenuBackgroundMode
|
|
13
|
-
/**
|
|
13
|
+
/** V2 style: load block atlas and render textured cubes (requires assets / mcData). */
|
|
14
14
|
useMinecraftTextures?: boolean
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
v2Scene?: V2SceneId
|
|
16
|
+
v2Camera?: V2CameraId
|
|
17
17
|
/** Block pool when {@link useMinecraftTextures} is enabled. */
|
|
18
|
-
|
|
18
|
+
v2BlockGroup?: MinecraftBlockGroupId
|
|
19
19
|
/** Camera path speed (1 = 100%). */
|
|
20
|
-
|
|
20
|
+
v2CameraSpeed?: number
|
|
21
21
|
/** Block fly-through + sky drift speed (1 = 100%). */
|
|
22
|
-
|
|
22
|
+
v2BlockSpeed?: number
|
|
23
23
|
/**
|
|
24
24
|
* Optional shared resource manager (e.g. appViewer.resourcesManager).
|
|
25
25
|
* Caller should run `updateAssetsData` after mcData is loaded when using textured cubes.
|