minecraft-renderer 0.1.63 → 0.1.65
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 +59 -59
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +415 -415
- 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 +54 -170
- package/src/three/entity/animations.js +92 -185
- 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
|
@@ -8,31 +8,31 @@ import { resizeMenuBackgroundCamera } from './activeView'
|
|
|
8
8
|
import { loadThreeJsTextureFromBitmap } from '../threeJsUtils'
|
|
9
9
|
import { MENU_BACKGROUND_MOTION_DEFAULTS, MENU_BACKGROUND_OPTION_DEFAULTS } from './config'
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
V2_CAMERA_IDS,
|
|
12
|
+
V2_SCENE_IDS,
|
|
13
13
|
MINECRAFT_BLOCK_GROUP_IDS,
|
|
14
|
-
type
|
|
15
|
-
type
|
|
14
|
+
type V2CameraId,
|
|
15
|
+
type V2SceneId,
|
|
16
16
|
type MinecraftBlockGroupId,
|
|
17
|
-
} from './
|
|
17
|
+
} from './v2Meta'
|
|
18
18
|
|
|
19
19
|
export {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
V2_SCENE_IDS,
|
|
21
|
+
V2_SCENE_LABELS,
|
|
22
|
+
V2_CAMERA_IDS,
|
|
23
|
+
V2_CAMERA_LABELS,
|
|
24
24
|
MINECRAFT_BLOCK_GROUP_IDS,
|
|
25
25
|
MINECRAFT_BLOCK_GROUP_LABELS,
|
|
26
|
-
} from './
|
|
27
|
-
export type {
|
|
26
|
+
} from './v2Meta'
|
|
27
|
+
export type { V2SceneId, V2CameraId, MinecraftBlockGroupId } from './v2Meta'
|
|
28
28
|
|
|
29
29
|
/** Mouse parallax scale (HTML prototype uses 1). */
|
|
30
30
|
const MOUSE_INFLUENCE = 0.1
|
|
31
31
|
|
|
32
|
-
export interface
|
|
32
|
+
export interface V2MenuBackgroundOptions {
|
|
33
33
|
useMinecraftTextures?: boolean
|
|
34
|
-
initialScene?:
|
|
35
|
-
initialCamera?:
|
|
34
|
+
initialScene?: V2SceneId
|
|
35
|
+
initialCamera?: V2CameraId
|
|
36
36
|
initialBlockGroup?: MinecraftBlockGroupId
|
|
37
37
|
/** Camera path speed multiplier (0 = frozen path; mouse parallax unchanged). */
|
|
38
38
|
initialCameraSpeed?: number
|
|
@@ -41,7 +41,7 @@ export interface FuturisticMenuBackgroundOptions {
|
|
|
41
41
|
resourcesManager?: ResourcesManager
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
/** Block pools for textured floating cubes (selected via {@link
|
|
44
|
+
/** Block pools for textured floating cubes (selected via {@link V2MenuBackground.setBlockGroup}). */
|
|
45
45
|
export const MINECRAFT_BLOCK_GROUPS = {
|
|
46
46
|
mixed: [
|
|
47
47
|
'white_wool', 'cyan_wool', 'blue_wool', 'purple_wool',
|
|
@@ -123,7 +123,7 @@ interface FloatingBlock {
|
|
|
123
123
|
minecraftBlockName?: string
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
const PAL: Record<
|
|
126
|
+
const PAL: Record<V2SceneId, ScenePalette> = {
|
|
127
127
|
galaxy: {
|
|
128
128
|
bg: 0x02_04_12, fog: 0x02_04_12, fogD: 0.011,
|
|
129
129
|
blocks: [0x00_f0_ff, 0x00_d4_ff, 0x00_b8_ff, 0x00_e8_ff, 0x22_cc_ff, 0x00_a8_ff],
|
|
@@ -192,7 +192,7 @@ const PAL: Record<FuturisticSceneId, ScenePalette> = {
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
const CAMS: Record<
|
|
195
|
+
const CAMS: Record<V2CameraId, CameraMode> = {
|
|
196
196
|
cruise: {
|
|
197
197
|
pos: (t, mx, my) => ({ x: Math.sin(t * 0.28) * 18 + Math.cos(t * 0.11) * 7 + mx * 10, y: Math.sin(t * 0.19) * 6 + Math.cos(t * 0.31) * 3 + my * 6, z: 0 }),
|
|
198
198
|
look: (t, mx, my) => ({ x: Math.sin((t + 0.18) * 0.28) * 18 + mx * 8, y: Math.sin((t + 0.18) * 0.19) * 6 + my * 4, z: -25 }),
|
|
@@ -232,7 +232,7 @@ const CAMS: Record<FuturisticCameraId, CameraMode> = {
|
|
|
232
232
|
}
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
const CAM_SPD: Record<
|
|
235
|
+
const CAM_SPD: Record<V2CameraId, number> = {
|
|
236
236
|
cruise: 1,
|
|
237
237
|
barrel: 1.6,
|
|
238
238
|
dive: 2.2,
|
|
@@ -270,7 +270,7 @@ const makeSkyGradientTexture = (gradient: NonNullable<ScenePalette['gradientBg']
|
|
|
270
270
|
return tex
|
|
271
271
|
}
|
|
272
272
|
|
|
273
|
-
export class
|
|
273
|
+
export class V2MenuBackground implements MenuBackgroundView {
|
|
274
274
|
readonly scene: THREE.Scene
|
|
275
275
|
readonly camera: THREE.PerspectiveCamera
|
|
276
276
|
|
|
@@ -288,8 +288,8 @@ export class FuturisticMenuBackground implements MenuBackgroundView {
|
|
|
288
288
|
private readonly bGeo = new THREE.BoxGeometry(1, 1, 1)
|
|
289
289
|
private readonly eGeo = new THREE.EdgesGeometry(this.bGeo)
|
|
290
290
|
|
|
291
|
-
private curScene:
|
|
292
|
-
private curCam:
|
|
291
|
+
private curScene: V2SceneId
|
|
292
|
+
private curCam: V2CameraId
|
|
293
293
|
private blockGroup: MinecraftBlockGroupId
|
|
294
294
|
private cameraSpeed: number
|
|
295
295
|
private blockSpeed: number
|
|
@@ -307,16 +307,19 @@ export class FuturisticMenuBackground implements MenuBackgroundView {
|
|
|
307
307
|
private gradientSkyTexture: THREE.CanvasTexture | null = null
|
|
308
308
|
private disposed = false
|
|
309
309
|
private animTime = 0
|
|
310
|
+
private texturesApplied = false
|
|
311
|
+
private textureLoadInProgress = false
|
|
312
|
+
private onAssetsTexturesUpdated?: () => void
|
|
310
313
|
|
|
311
314
|
constructor(
|
|
312
315
|
private readonly documentRenderer: DocumentRenderer,
|
|
313
|
-
options:
|
|
316
|
+
options: V2MenuBackgroundOptions = {},
|
|
314
317
|
private readonly abortSignal?: AbortSignal
|
|
315
318
|
) {
|
|
316
319
|
const d = MENU_BACKGROUND_OPTION_DEFAULTS
|
|
317
|
-
this.curScene = options.initialScene ?? d.
|
|
318
|
-
this.curCam = options.initialCamera ?? d.
|
|
319
|
-
this.blockGroup = options.initialBlockGroup ?? d.
|
|
320
|
+
this.curScene = options.initialScene ?? d.v2Scene
|
|
321
|
+
this.curCam = options.initialCamera ?? d.v2Camera
|
|
322
|
+
this.blockGroup = options.initialBlockGroup ?? d.v2BlockGroup
|
|
320
323
|
this.cameraSpeed = options.initialCameraSpeed ?? MENU_BACKGROUND_MOTION_DEFAULTS.camera
|
|
321
324
|
this.blockSpeed = options.initialBlockSpeed ?? MENU_BACKGROUND_MOTION_DEFAULTS.block
|
|
322
325
|
this.useMinecraftTextures = options.useMinecraftTextures ?? d.minecraftTextures
|
|
@@ -420,13 +423,79 @@ export class FuturisticMenuBackground implements MenuBackgroundView {
|
|
|
420
423
|
}
|
|
421
424
|
|
|
422
425
|
async init() {
|
|
423
|
-
if (this.useMinecraftTextures)
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
426
|
+
if (!this.useMinecraftTextures) return
|
|
427
|
+
void this.scheduleMinecraftTextureLoad()
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
private scheduleMinecraftTextureLoad() {
|
|
431
|
+
if (!this.useMinecraftTextures || this.disposed || this.texturesApplied || this.textureLoadInProgress) return
|
|
432
|
+
void this.tryApplyMinecraftTextures()
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
private attachAssetsListener() {
|
|
436
|
+
const rm = this.resourcesManager
|
|
437
|
+
if (!rm || this.onAssetsTexturesUpdated) return
|
|
438
|
+
this.onAssetsTexturesUpdated = () => this.scheduleMinecraftTextureLoad()
|
|
439
|
+
rm.on('assetsTexturesUpdated', this.onAssetsTexturesUpdated)
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
private detachAssetsListener() {
|
|
443
|
+
const rm = this.resourcesManager
|
|
444
|
+
if (!rm || !this.onAssetsTexturesUpdated) return
|
|
445
|
+
rm.off('assetsTexturesUpdated', this.onAssetsTexturesUpdated)
|
|
446
|
+
this.onAssetsTexturesUpdated = undefined
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
private hasBlockAtlas(resourcesManager: ResourcesManager): boolean {
|
|
450
|
+
const resources = resourcesManager.currentResources
|
|
451
|
+
return !!(resources?.blocksAtlasImage && resources.blocksAtlasJson)
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
private async ensureAtlasReady(resourcesManager: ResourcesManager): Promise<boolean> {
|
|
455
|
+
await this.ensureMcDataLoaded()
|
|
456
|
+
if (this.hasBlockAtlas(resourcesManager)) return true
|
|
457
|
+
|
|
458
|
+
if (typeof document === 'undefined' && resourcesManager !== this.resourcesManager) {
|
|
459
|
+
return false
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
resourcesManager.currentConfig = {
|
|
463
|
+
...resourcesManager.currentConfig,
|
|
464
|
+
version: MENU_BACKGROUND_MC_VERSION,
|
|
465
|
+
noInventoryGui: true
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
try {
|
|
469
|
+
await resourcesManager.updateAssetsData?.({})
|
|
470
|
+
} catch {
|
|
471
|
+
return false
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
return this.hasBlockAtlas(resourcesManager)
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
private async tryApplyMinecraftTextures() {
|
|
478
|
+
if (this.disposed || !this.useMinecraftTextures || this.texturesApplied) return
|
|
479
|
+
|
|
480
|
+
this.textureLoadInProgress = true
|
|
481
|
+
try {
|
|
482
|
+
const resourcesManager = this.resourcesManager ?? new ResourcesManager()
|
|
483
|
+
const ready = await this.ensureAtlasReady(resourcesManager)
|
|
484
|
+
if (!ready) {
|
|
485
|
+
if (this.resourcesManager) this.attachAssetsListener()
|
|
486
|
+
return
|
|
429
487
|
}
|
|
488
|
+
if (this.disposed) return
|
|
489
|
+
|
|
490
|
+
this.applyMinecraftTexturesFromAtlas(resourcesManager)
|
|
491
|
+
this.texturesApplied = true
|
|
492
|
+
this.detachAssetsListener()
|
|
493
|
+
} catch (err) {
|
|
494
|
+
console.warn('[V2MenuBackground] Failed to load Minecraft textures, using solid colors:', err)
|
|
495
|
+
this.useMinecraftTextures = false
|
|
496
|
+
this.detachAssetsListener()
|
|
497
|
+
} finally {
|
|
498
|
+
this.textureLoadInProgress = false
|
|
430
499
|
}
|
|
431
500
|
}
|
|
432
501
|
|
|
@@ -626,23 +695,7 @@ export class FuturisticMenuBackground implements MenuBackgroundView {
|
|
|
626
695
|
return null
|
|
627
696
|
}
|
|
628
697
|
|
|
629
|
-
private
|
|
630
|
-
await this.ensureMcDataLoaded()
|
|
631
|
-
|
|
632
|
-
const resourcesManager = this.resourcesManager ?? new ResourcesManager()
|
|
633
|
-
const needsAssetUpdate = !resourcesManager.currentResources?.blocksAtlasImage
|
|
634
|
-
if (needsAssetUpdate) {
|
|
635
|
-
if (typeof document === 'undefined') {
|
|
636
|
-
throw new Error('Menu atlas missing in worker; pass resourcesManager from main thread')
|
|
637
|
-
}
|
|
638
|
-
resourcesManager.currentConfig = {
|
|
639
|
-
...resourcesManager.currentConfig,
|
|
640
|
-
version: MENU_BACKGROUND_MC_VERSION,
|
|
641
|
-
noInventoryGui: true
|
|
642
|
-
}
|
|
643
|
-
await resourcesManager.updateAssetsData?.({})
|
|
644
|
-
}
|
|
645
|
-
|
|
698
|
+
private applyMinecraftTexturesFromAtlas(resourcesManager: ResourcesManager) {
|
|
646
699
|
const resources = resourcesManager.currentResources
|
|
647
700
|
if (!resources?.blocksAtlasImage || !resources.blocksAtlasJson) {
|
|
648
701
|
throw new Error('Block atlas not available')
|
|
@@ -690,8 +743,8 @@ export class FuturisticMenuBackground implements MenuBackgroundView {
|
|
|
690
743
|
}
|
|
691
744
|
}
|
|
692
745
|
|
|
693
|
-
setScene(name:
|
|
694
|
-
if (!(
|
|
746
|
+
setScene(name: V2SceneId) {
|
|
747
|
+
if (!(V2_SCENE_IDS as readonly string[]).includes(name)) return
|
|
695
748
|
if (name === this.curScene || this.transitioning) return
|
|
696
749
|
this.transitioning = true
|
|
697
750
|
this.curScene = name
|
|
@@ -726,8 +779,8 @@ export class FuturisticMenuBackground implements MenuBackgroundView {
|
|
|
726
779
|
}, 150)
|
|
727
780
|
}
|
|
728
781
|
|
|
729
|
-
setCamera(name:
|
|
730
|
-
if (!(
|
|
782
|
+
setCamera(name: V2CameraId) {
|
|
783
|
+
if (!(V2_CAMERA_IDS as readonly string[]).includes(name)) return
|
|
731
784
|
this.curCam = name
|
|
732
785
|
}
|
|
733
786
|
|
|
@@ -749,18 +802,15 @@ export class FuturisticMenuBackground implements MenuBackgroundView {
|
|
|
749
802
|
mat.dispose()
|
|
750
803
|
}
|
|
751
804
|
this.blockMaterialPool.clear()
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
} catch (err) {
|
|
755
|
-
console.warn('[FuturisticMenuBackground] Failed to reload block group textures:', err)
|
|
756
|
-
}
|
|
805
|
+
this.texturesApplied = false
|
|
806
|
+
this.scheduleMinecraftTextureLoad()
|
|
757
807
|
}
|
|
758
808
|
|
|
759
|
-
getSceneId():
|
|
809
|
+
getSceneId(): V2SceneId {
|
|
760
810
|
return this.curScene
|
|
761
811
|
}
|
|
762
812
|
|
|
763
|
-
getCameraId():
|
|
813
|
+
getCameraId(): V2CameraId {
|
|
764
814
|
return this.curCam
|
|
765
815
|
}
|
|
766
816
|
|
|
@@ -830,6 +880,7 @@ export class FuturisticMenuBackground implements MenuBackgroundView {
|
|
|
830
880
|
|
|
831
881
|
dispose() {
|
|
832
882
|
this.disposed = true
|
|
883
|
+
this.detachAssetsListener()
|
|
833
884
|
this.scene.clear()
|
|
834
885
|
this.bGeo.dispose()
|
|
835
886
|
this.eGeo.dispose()
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
2
|
/** Settings / labels only — no Three.js or DocumentRenderer (safe for defaultOptions imports). */
|
|
3
3
|
|
|
4
|
-
export const
|
|
5
|
-
export type
|
|
4
|
+
export const V2_SCENE_IDS = ['galaxy', 'nether', 'end', 'cyber', 'light'] as const
|
|
5
|
+
export type V2SceneId = typeof V2_SCENE_IDS[number]
|
|
6
6
|
|
|
7
|
-
export const
|
|
8
|
-
export type
|
|
7
|
+
export const V2_CAMERA_IDS = ['cruise', 'barrel', 'dive', 'orbit', 'snake'] as const
|
|
8
|
+
export type V2CameraId = typeof V2_CAMERA_IDS[number]
|
|
9
9
|
|
|
10
|
-
export const
|
|
10
|
+
export const V2_SCENE_LABELS: Record<V2SceneId, string> = {
|
|
11
11
|
galaxy: 'Galaxy',
|
|
12
12
|
nether: 'Nether',
|
|
13
13
|
end: 'The End',
|
|
@@ -15,7 +15,7 @@ export const FUTURISTIC_SCENE_LABELS: Record<FuturisticSceneId, string> = {
|
|
|
15
15
|
light: 'Light Space'
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
export const
|
|
18
|
+
export const V2_CAMERA_LABELS: Record<V2CameraId, string> = {
|
|
19
19
|
cruise: 'Cruise',
|
|
20
20
|
barrel: 'Barrel',
|
|
21
21
|
dive: 'Dive',
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { describe, expect, test } from 'vitest'
|
|
3
|
+
import { SectionRequestTracker } from '../worker/mesherWasmRequestTracker'
|
|
4
|
+
|
|
5
|
+
describe('SectionRequestTracker.clearColumn', () => {
|
|
6
|
+
test('removes all pending keys for the column', () => {
|
|
7
|
+
const tracker = new SectionRequestTracker()
|
|
8
|
+
tracker.addRequest('160,64,0')
|
|
9
|
+
tracker.addRequest('160,80,0')
|
|
10
|
+
tracker.addRequest('0,64,0')
|
|
11
|
+
|
|
12
|
+
tracker.clearColumn(160, 0)
|
|
13
|
+
|
|
14
|
+
expect(tracker.hasPending('160,64,0')).toBe(false)
|
|
15
|
+
expect(tracker.hasPending('160,80,0')).toBe(false)
|
|
16
|
+
expect(tracker.hasPending('0,64,0')).toBe(true)
|
|
17
|
+
expect(tracker.size()).toBe(1)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
test('is a no-op when the column has no pending keys', () => {
|
|
21
|
+
const tracker = new SectionRequestTracker()
|
|
22
|
+
tracker.addRequest('0,64,0')
|
|
23
|
+
|
|
24
|
+
tracker.clearColumn(160, 0)
|
|
25
|
+
|
|
26
|
+
expect(tracker.hasPending('0,64,0')).toBe(true)
|
|
27
|
+
expect(tracker.size()).toBe(1)
|
|
28
|
+
})
|
|
29
|
+
})
|
|
@@ -767,6 +767,13 @@ const handleMessage = async (data: any) => {
|
|
|
767
767
|
if (!world) break
|
|
768
768
|
world.removeColumn(data.x, data.z)
|
|
769
769
|
world.customBlockModels.delete(`${data.x},${data.z}`)
|
|
770
|
+
requestTracker.clearColumn(data.x, data.z)
|
|
771
|
+
for (const key of [...dirtySections.keys()]) {
|
|
772
|
+
const [sx, , sz] = key.split(',').map(Number)
|
|
773
|
+
if (sx === data.x && sz === data.z) {
|
|
774
|
+
dirtySections.delete(key)
|
|
775
|
+
}
|
|
776
|
+
}
|
|
770
777
|
if (Object.keys(world.columns).length === 0) softCleanup()
|
|
771
778
|
break
|
|
772
779
|
}
|
|
@@ -49,6 +49,16 @@ export class SectionRequestTracker {
|
|
|
49
49
|
this.counts.clear()
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
/** Drop all pending requests for one column (`cx`,`cz` = column origin in block coords). */
|
|
53
|
+
clearColumn (cx: number, cz: number): void {
|
|
54
|
+
for (const key of [...this.counts.keys()]) {
|
|
55
|
+
const [x, , z] = key.split(',').map(Number)
|
|
56
|
+
if (x === cx && z === cz) {
|
|
57
|
+
this.counts.delete(key)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
52
62
|
/** Number of distinct keys with pending requests. */
|
|
53
63
|
size (): number {
|
|
54
64
|
return this.counts.size
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
3
|
+
import { Vec3 } from 'vec3'
|
|
4
|
+
import { WorldView } from './worldView'
|
|
5
|
+
|
|
6
|
+
describe('WorldView._loadChunks spiral guard', () => {
|
|
7
|
+
it('does not let a superseded spiral reset inLoading or panic state', async () => {
|
|
8
|
+
const world = {
|
|
9
|
+
getColumnAt: () => null,
|
|
10
|
+
setBlockStateId: vi.fn(),
|
|
11
|
+
}
|
|
12
|
+
const view = new WorldView(world, 8, new Vec3(0, 64, 0))
|
|
13
|
+
view.addWaitTime = 0
|
|
14
|
+
view.loadChunk = vi.fn(async () => {})
|
|
15
|
+
|
|
16
|
+
const positions = [new Vec3(0, 0, 0)]
|
|
17
|
+
const spiralA = view._loadChunks(positions, new Vec3(0, 64, 0))
|
|
18
|
+
await Promise.resolve()
|
|
19
|
+
|
|
20
|
+
expect(view.inLoading).toBe(true)
|
|
21
|
+
expect(view.spiralNumber).toBe(1)
|
|
22
|
+
|
|
23
|
+
const spiralB = view._loadChunks(positions, new Vec3(0, 64, 0))
|
|
24
|
+
await Promise.resolve()
|
|
25
|
+
|
|
26
|
+
expect(view.spiralNumber).toBe(2)
|
|
27
|
+
expect(view.inLoading).toBe(true)
|
|
28
|
+
expect(view.gotPanicLastTime).toBe(false)
|
|
29
|
+
|
|
30
|
+
await spiralA
|
|
31
|
+
expect(view.inLoading).toBe(true)
|
|
32
|
+
expect(view.gotPanicLastTime).toBe(false)
|
|
33
|
+
|
|
34
|
+
view.waitingSpiralChunksLoad['0,0']?.(true)
|
|
35
|
+
await spiralB
|
|
36
|
+
expect(view.inLoading).toBe(false)
|
|
37
|
+
})
|
|
38
|
+
})
|
|
@@ -265,6 +265,8 @@ export class WorldView extends (EventEmitter as new () => TypedEmitter<WorldView
|
|
|
265
265
|
this.chunkProgress()
|
|
266
266
|
})
|
|
267
267
|
|
|
268
|
+
if (spiralNumber !== this.spiralNumber) return
|
|
269
|
+
|
|
268
270
|
if (this.panicTimeout) clearTimeout(this.panicTimeout)
|
|
269
271
|
this.inLoading = false
|
|
270
272
|
this.gotPanicLastTime = false
|