更新日志

按时间线记录"现象 → 根因 → 修法"。这些几乎都是实测撞出来的:不是猜的,每条都有对应的无头测试或截图。

引擎级修复 4 项产出逻辑 6 项 界面 3 项工具 2 项

时间线

第 1 项 · 引擎级

放上去的方块客户端不渲染

  • 现象:右键能放,服务端世界里方块真实存在(有碰撞、能站上去),屏幕上什么都没有。
  • 根因:引擎的 setBlock → markDirty → onUpdate → updateChunk → updateBlocks 里, updateBlocks 只调了一个空实现 Block.onBlockUpdate() —— 方块新增一个包都不发。 引擎只同步"整块区块第一次下发"和"挖掉方块"。
  • 修法:内核补一条通道(typeId 310):服务端记格子、tick 末读回最终方块后广播; 客户端在渲染线程 BlockManager#addBlock。任何 mod 甚至引擎自己的泥土都会渲染。
  • 验证:无头 KernelBlockSyncTest(地形阶段 0 个包、右键恰好 1 个包)+ 真客户端截图。
第 2 项 · 引擎级

方块画出来了,但穿模、没有实体

  • 根因:我第一版只带了 cutRect,把 collisionRect 传成 null。 而客户端 Block.isSolid() 是 solid && !isBackground && collisionRect != null —— 缺了就恒为 false。
  • 修法:带上碰撞矩形;并加了"渲染后读回方块问它 isSolid()"的自检日志。
第 3 项 · 引擎级

"有时候有实体、有时候没有"

  • 根因:碰撞矩形要用区块局部坐标(客户端自己会加 chunkIndex * chunkSize); 我传了世界坐标 —— chunk(0,0) 恰好相等所以测试全绿,其它区块整个偏一个区块宽。
  • 修法:改传 localCollisionRect;自检升级成"读回矩形并与期望的局部矩形逐值比对"。
  • 验证:新增"非零区块"回归用例(旧版会直接红)。
第 4 项 · mod

高速点击破坏方块:挖掉了又恢复、还破坏不了

  • 根因:客户端右键发了两条放置路径,其中兜底的 PlaceRequest 在 ModLoader.tickAll()(onTick() 之后)落地,越过了引擎同 tick 的放/挖到达顺序。
  • 修法:删除兜底通道(只保留注册、不再写世界),放置只走引擎点击包 + 内核钩子。
  • 验证:KernelDigRaceTest —— 修前 30 轮里 27 轮出现恢复,修后 restoredAfterDig=0。
第 5 项 · mod

同一坐标的背景也能无限刷方块

  • 根因:引擎生成地形写背景层用的是 Chunk.setBackgroundBlock(),它只往数组里塞、 从不设置 block.isBackground = true,所以地形背景方块全报 false;照它判断,挖不掉的背景格每点一次就白给一个方块。
  • 修法:不看那个标志,直接查前景层(引擎的挖本来也只挖前景层)。
  • 验证:同一格连挖 4 次只掉 1 个(回归测试里锁住)。
第 6 项 · mod

右键连点被连扣材料

  • 根因:先扣材料再读回校验,于是"区块没初始化导致放置被静默丢弃"也会白扣;同格连点也每次都扣。
  • 修法:只有读回确认真的放上去了才扣;同格同料不再重复放(换成别的材料仍然可覆盖、也仍然扣 1 个)。
  • 验证:同一格连点右键 3 次只扣 1 个。
第 7 项 · 内容

新方块 + 世界生成 + 产出逻辑

  • 4 种矿石(煤/铁/金/钻石):程序化生成的染色占位贴图 + mapper 条目 + 内核在 generateChunk 末尾种矿脉(只替换石头、只长在埋着的位置,位置完全确定性)。
  • 矮树(原木 + 树叶):地形生成器不产木头,而合成链需要它;区块只有 16 高,所以种矮树。
  • 掉落表 / 背包(9 列)/ 3×3 合成台 / 放置消耗 / 创造模式开关。
  • 验证:281 区块实测煤 804、铁 303、金 75、钻石 14;产出逻辑 13 项断言全过。
第 8 项 · 界面

ESC 设置面板 + 自绘 UI 的 GL 混合坑

  • 设置项:相机缩放 / HUD 透明度 / HUD 大小 / 诊断行 / 全屏 / 创造模式,写进 hotbar.settings。
  • 坑:第一版一打开面板整屏变黑 —— 引擎画完世界会 glDisable(GL_BLEND), 而 ShapeRenderer 只在构造时开一次混合,于是 60% 黑的遮罩被画成实心。 修法:每次画 shapes 前自己 glEnable(GL_BLEND)。
第 9 项 · 界面

E 键被引擎占用 → 背包改 I 键;面板改成 MC 风格

  • 根因:不是别的 mod,是引擎自己的 client.World 用 E / Q 做相机缩放。
  • 背包/合成台改用 I(全工程没人用)。
  • 面板从"标题画在面板外、下面一大片空白"改成 MC 风格的紧凑灰窗口:24px 槽位、 3×3 合成格与产物格同一行、下面 9 列背包、悬停高亮、深色文字。
第 10 项 · 工具

一键启动 + 这套网页

  • 一键启动.bat:查文件 → 起服务端(新窗口)→ 等端口就绪 → 起客户端;端口已占则只开客户端。 (踩坑:bat 必须 GBK + CRLF;等待用 ping 而不是在某些环境会失败的 timeout)
  • 本站:暗色官网风,7 个页面共用 assets/site.css 与 site.js,贴图直接引用资源包。

当前状态

6/6内核注入点全部命中
13/13产出逻辑断言
0竞态恢复次数
10/10方块同步断言
回归入口:无头自测说明 · KernelBlockSyncTest / KernelOreGenTest / KernelProductionTest / KernelDigRaceTest / KernelClickTest

改动过程与设计取舍都在开发文档里:内核 README、 MOD 开发指南、hotbar mod README。