Skip to content

refactor(world): blockData 权威统一与派生数据生命周期优化#77

Merged
jayli merged 17 commits into
mainfrom
blockdata_refactor
May 14, 2026
Merged

refactor(world): blockData 权威统一与派生数据生命周期优化#77
jayli merged 17 commits into
mainfrom
blockdata_refactor

Conversation

@jayli

@jayli jayli commented May 14, 2026

Copy link
Copy Markdown
Owner

Summary

  • blockData 权威统一: 引入三层容器架构(WorldBlockDataStore / WorldChunkPayloadRegistry / WorldChunkRegistry),将分散的方块数据写入口收敛为单一权威源,消除 MemoryWorldStore,建立 epoch/version 协议保障数据一致性
  • 派生数据生命周期收紧: RegionCache 去冗余、chunk unload 时清理派生数据、增量更新优化,减少内存泄漏风险
  • 性能优化: chunk 装配 entries 快照缓存 + _assemblyEpoch 失效闭环;O 键 AO 开关全链路支持,关闭 AO 时跳过计算
  • Bug 修复: 修复 cold import / scatter 新增路径的三个 bug

变更范围

  • 新增 WorldBlockDataStoreWorldChunkPayloadRegistryWorldChunkRegistry 三个核心模块
  • 删除 MemoryWorldStore(已被统一架构替代)
  • 重构 Chunk.jsWorld.jsWorldRuntime.js 等核心文件
  • 新增/扩展测试覆盖(test-chunk.jstest-world-runtime.jstest-world.js
  • 包含 5 个设计/计划文档记录决策过程

Test plan

  • 运行 node command/run-tests.js 确认所有测试通过
  • 启动游戏验证区块加载/卸载正常
  • 验证方块放置/删除操作正常
  • 验证 AO 开关(O 键)功能正常
  • 验证存档/读档不受影响

🤖 Generated with Claude Code

jayli and others added 17 commits May 8, 2026 00:18
核心变更:
- 删除 MemoryWorldStore,以 WorldBlockDataStore 作为唯一世界级 blockData 权威
- Chunk.blockData 降级为 chunk 运行时视图,不再是第二权威
- 推迟 IndexedDB / 导入导出 / 冷存储到后续阶段
- 新增写入口清单(Section 8)和 clone 边界约束(Section 9)
- 新增测试迁移矩阵(Section 11)
- 计划新增 Task 6 收紧 clone/序列化边界,Task 7 推迟冷存储

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- 明确 Chunk.blockData 与 WorldBlockDataStore 共享同一个 Map 实例
- 新增 deleteBlockEntry API,约束 replaceChunkSlice 仅用于低频整块装载
- 新增 Scatter/Cross-Chunk Patch 写入流程(7.2.1)
- 热路径禁止双写、禁止 staging 副本、禁止 replaceChunkSlice 滥用
- 扩展保留清单覆盖 blockPalette/lightSourceCoords/dirtyAOPositions 等
- 新增 entityCollisionIndex 独立保留约束

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
新增内容包括:
- 阶段边界与 runtime-only 验收前提
- WorldBlockDataStore 完整存储契约(peek/ensure/replace 语义与 attached slice 引用稳定性)
- 共享 Map 兼容性规则与 clear/replace 硬约束
- loadFromRecord/_injectBlockData 迁移矩阵
- RegionCache 降级方案
- AO Worker mirror 派生副本契约
- WorldGenerationService 到 WorldBlockDataStore 的单写入路径
- bootstrap 预生成链路(Task 3.5)
- attach/hydrate/rebuild 装配协议(Task 2.5)
- 统一 mutation 原语与写机制切换
- snapshot consumer 去留矩阵
- Worker 回包边界与读路径契约
- 新增 invariant 与竞态/生命周期测试清单

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
补充了计划文档的大粒度缺口:
- 新增 WorldChunkPayloadRegistry + WorldChunkRegistry 两个 world-level 容器,
  明确 non-block payload(runtimeSeedData、staticEntities)的持有语义
- 新增 BlockScatterManager 和 ChunkAssemblyScheduler 的改造文件列表与约束
- 新增 Task 1.2(registry 语义固定)、Task 3.2(dirty 拆分为
  runtime dirty 与 save dirty)、Task 3.6(authority codec 边界)、
  Task 2.9(detach/dispose + epoch 协议)
- 新增旧测试删除/重写策略与中止条件初稿
- 设计文档补充特殊实体兼容层边界、resolveBlockOwner 权威来源、
  写入口收敛收束范围和序列化 codec 草案
- 验收矩阵增加特殊实体功能回退禁止项

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
基于对当前代码基线(1ed3544)的深入对照分析,补齐设计和计划文档的以下缺口:

1. Consolidation 协议:新增完整的 7.4.3 小节(send/receive/concurrency/shared-map 四个子协议)+ Task 2.6
2. Chunk → WorldBlockDataStore 访问路径:新增 5.3.4 访问契约 + Task 1 Step 4.2
3. Authority Version / Assembly Epoch 机制:细化 7.4.2 为完整实现契约 + Task 2.5 Step 2.85/2.9
4. 未加载目标 chunk 的写入语义:新增 5.3.5 契约 + 7.2.3 语义定义 + Task 3 Step 3.35
5. 旧热路径退出验收标准:新增 5.4.2 退出标准 + Task 5 Step 5.2
6. 查询边界固定:新增 5.3.6 契约 + Task 3 Step 3.7

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
新增 WorldBlockDataStore / WorldChunkRegistry / WorldChunkPayloadRegistry 三层权威容器,
建立 Chunk.blockData 到 world-level authority 的共享 Map 装配协议(attach/rebuild/detach),
清理 runtime 热路径中的 blockDataSnapshot 构造,降级 flushChunk/flushBeforeUnload。

新文件:
- WorldBlockDataStore: world-level blockData 唯一权威(Map<chunkKey, Map<number, entry>>)
- WorldChunkRegistry: chunk 存在/生成状态注册表
- WorldChunkPayloadRegistry: non-block payload 权威持有者

核心变更:
- Chunk.js: attachAuthoritySlice / rebuildDerivedIndexesFromAuthority / detachAuthoritySlice
  三段式装配协议;_updateBlockState 双写到新旧两层权威
- World.js: _requestRuntimeChunkRecord 新增 authority 优先路径,
  走 record-ready → runtime-hydrate → runtime-build-mesh 标准管线构建 mesh
- WorldGenerationService.js: 双写到新权威容器 + 旧 MemoryWorldStore
- WorldRuntime.js: recordBlockMutation 仅标记 dirty,不再构造 blockDataSnapshot
- ChunkRenderUtils.js: dispose 前执行 detachAuthoritySlice
- test-world-runtime.js: 7 个测试迁移到新 authority 语义

339/339 测试通过。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…drails

变更:
- 删除 MemoryWorldStore.js 及全部 ~8 处双写引用(Chunk/World/WorldGenerationService)
- Consolidation 回包增加 assemblyEpoch + authorityVersion 过期校验,过期回包直接丢弃
- AO 回包增加 disposed / assemblyEpoch 校验(原有 aoSourceVersion 保留)
- ChunkGenerator / acceptWorkerResult 增加 disposed 检查
- WorldBlockDataStore.replaceChunkSlice 增加 callSource 追踪与统计
- Chunk.attachAuthoritySlice 增加 slice integrity 验证
- WorldRuntime 增加 _callStats 调用计数器

⚠️ 有待进一步测试验证

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ort 统一、scatter 未加载 chunk 写入与 flush 链路退出

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…uthority、flush/save 退出热路径

- WorldBlockDataStore: setBlockEntry/deleteBlockEntry/applyChunkPatch 作为唯一合法 mutation primitive,统一 entry 规范化、version 递增与统计
- Chunk: _updateBlockState/acceptScatteredBlocks/appendScatteredBlocks 收敛为 store 编排调用方,不再直接操作 authority slice;hydrate 状态机清理死代码,_isAuthorityAttached 显式标志区分路径
- World: cold import 路径统一为 plain object → deserializeBlockData → replaceChunkSlice → payload registry → chunk registry → attach + rebuild
- BlockScatterManager: scatter() 对未加载目标 chunk 先写入 authority,再保留 buffer 作为派生层队列
- WorldRuntime: markChunkDirty 不再自动调度 _scheduleFlush,deprecated flush 链路退出热路径
- ChunkPersistence: saveDebounced 退化为 no-op shell
- 新增 guardrail: replaceChunkSlice attached 保护、_verifySliceIntegrity/_assertNotAttached 开发期断言、_callStats 迁移期路径命中计数
- 测试: 更新 flush/save 退出型测试,新增 4 个 guardrail 测试 + 6 个 authority 语义测试

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- WorldChunkRegistry: 新增 markChunkKnown() 通用标记方法,cold-import → imported,scatter → generated,已标记则跳过
- World.js: cold import 存在 runtimeEntities 时直接注入 shadow store,不再设 _isAuthorityAttached=false 退回旧注入分支,避免 blockData/staticEntities 重复写入
- Chunk.js: acceptScatteredBlocks 添加 blockData.has(code) 守卫,scatter 先写 authority 后不再重复 applyChunkPatch,防止 version bump 与 stats 放大

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- MaterialManager: 重构 toggleAO/setAOEnabled,提取 _syncAOShaderState 和 _notifyAOSettingChanged,开关变更时通知 World 系统
- World: 新增 onAOSettingChanged,AO关闭清理全部chunk的脏状态和定时器,AO开启触发已就绪chunk的全量刷新
- Chunk: _refreshAOFromStableSource/_executeAORefresh/_applyAOResults 入口处检查AO开关,关闭时跳过fullSync/flush/attribute覆写
- Chunk: _buildMeshFromExistingBlockDataIncremental 新增分阶段性能打点(iterate/convert/visible/build-mesh),便于定位瓶颈
- 测试: 覆盖AO关闭跳过fullSync、关闭不覆写attribute、关闭清理脏状态、开启触发刷新四个场景

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 缓存 blockData entries 数组到 _cachedEntries,避免 iterate 阶段每次 invocation 重新展开整个 Map(大 chunk 从 ~50 次快照降到 1 次)
- 新增 resetBuildMeshProgressState():当 _sourceEpoch 与当前 _assemblyEpoch 不一致时,整段 buildMesh 进度作废从头开始,避免 convert-group/visible 继续消费旧数据
- _updateBlockState 中补充 _assemblyEpoch 递增,使运行时 blockData 变更能正确触发装配快照失效
- 失效重启时同步清理 this.visibleKeys,防止过期可见性数据污染 face culling
- 新增 invocationProfile / group.perf / staleRestartCount 等诊断埋点,iterate-pass、convert-group.batch、visible-pass 日志现在携带增量/总量/剩余计数器

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
出现了地表空洞后的首次代码整理,by opus 4.6

- 提取 _ensureAuthorityAttached() 消除 3 处延迟 attach 重复代码
- 提取 _migrateRuntimeEntities() 消除 4 处 entity 迁移重复逻辑
- World.onAOSettingChanged(false) 复用 Chunk._clearPendingAOState()
- buildMesh perf 辅助(stageThresholds/pushTopSlowItem/createInvocationStats/
  resetBuildMeshProgressState)提升到 module level,避免每次调用重建闭包
- 修复 _updateBlockState 中 attach 路径的双重 _assemblyEpoch 递增
- acceptScatteredBlocks 从全量重建 solidBlocks 改为增量更新

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
以"blockData 全量永驻 + 派生按距离释放"为原则,识别并规划 6 项改动:
- M1: RegionCache 剥离 blockData 冗余副本(统一 helper + 6 个写入点)
- M2: chunk unload 时清理 _dirtyChunks / pendingUnloadFlushQueue / _flushTimers
- M3: topology 变化后从已加载 chunks 重建 _staticTreeTerrainBoostChunkKeys
- M5: appendScatteredBlocks 增量更新 blockDataArray(O(n)→O(k))
- M6: _applyConsolidateResult 去除多余全量重建,前置修复 solidBlockIds 共享 id 误删 bug
- M4 已撤回(WorldChunkPayloadRegistry 实为独立权威数据)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
M1: RegionCache 通过 _stripBlockDataFromRegionRecord 统一剥离 blockData 冗余副本,
覆盖全部 _regionCache.set 调用点,修复 full-save 路径丢数据风险。
M2: chunk unload 时清理 _dirtyChunks / pendingUnloadFlushQueue / _flushTimers 残留。
M3: chunk topology 变化后从已加载 chunks 重建 _staticTreeTerrainBoostChunkKeys,
避免 Set 无限增长。
M5: appendScatteredBlocks 增量更新 blockDataArray,O(n)→O(k)。
M6: 修复 solidBlockIds 共享 id 误删 bug(_updateBlockState / _registerSpecialEntityCollision);
_applyConsolidateResult 去除多余的 _initArrayStorageFromBlockData 全量重建。

361/361 测试通过,零新增 lint 警告。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jayli jayli merged commit 4992aeb into main May 14, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant