fix(game): 崩溃修复(卸载区块实体冻结)+ 立面光照、掉落可见、打击感、水下效果、空手拳头、血条左/饥饿右

- 崩溃(index out of range):实体所在区块卸载后失去碰撞支撑无限下坠到
  负坐标,光查询越界 panic——WorldView 增 ChunkLoaded,未加载区块实体冻结;
  chunk 光查询加越界防御(双保险)
- 立面光照:mesh 每面取**邻格**光照(原版光照模型)——此前用方块自身光照
  (sky=0)导致悬崖/矿洞立面全黑(泥土竖向黑色根因)
- 掉落可见:生成后 1 秒拾取延迟 + 图标加大到 0.45
- 打击感:攻击命中音(block.hit)+ 实体受击白闪(uTint)+ 手持挥动动画
- 水下效果:相机入水蓝色叠加(渲染.md §8 水体)
- 空手显示肤色拳头(白羊毛 × 肤色 tint),持方块正常显示
- HUD 布局:血条左下、饥饿右下(经典布局)
This commit is contained in:
NianGao Dev
2026-08-16 20:59:28 +08:00
parent 5da460c9a2
commit 9e2f5a6186
16 changed files with 223 additions and 36 deletions

View File

@@ -33,6 +33,9 @@ type WorldView interface {
Block(x, y, z int32) block.State
SkyLight(x, y, z int32) uint8
BlockLight(x, y, z int32) uint8
// ChunkLoaded 实体所在区块是否已加载(卸载区块冻结实体——
// 否则实体失去碰撞支撑会无限下坠到负数坐标,见 实体系统.md §2)
ChunkLoaded(x, z int32) bool
}
// Entity 实体。
@@ -45,6 +48,9 @@ type Entity struct {
Health float64
Dead bool
// HitFlash 受击白闪剩余秒数(客户端渲染用,打击反馈)
HitFlash float64
// AI 状态(实体系统.md §3 状态机)
state uint8
decisionIn float64 // 下次决策倒计时(限频)
@@ -116,12 +122,19 @@ func (m *Manager) List() []*Entity {
return out
}
// Tick 每 tick 更新全部实体(激活区块内;冻结区由调用方过滤)。
// Tick 每 tick 更新全部实体(激活区块内;冻结区跳过,实体系统.md §2
// ——未加载区块无碰撞支撑,实体继续 tick 会无限下坠并越界崩溃)。
func (m *Manager) Tick(dt float64, w WorldView, playerPos [3]float64) {
for _, e := range m.List() {
if e.Dead {
continue
}
if !w.ChunkLoaded(int32(e.Pos[0]), int32(e.Pos[2])) {
continue // 区块卸载:冻结
}
if e.HitFlash > 0 {
e.HitFlash -= dt // 受击白闪衰减
}
switch e.Kind {
case KindZombie:
e.tickZombie(dt, w, playerPos)