feat(mpsync): 实体位置广播(EntityMove)与客户端在线玩家显示;mesh 顶点池复用(性能与内存.md §2)

This commit is contained in:
NianGao Dev
2026-08-16 00:05:17 +08:00
parent e70314fb3f
commit 95c8d677ea
10 changed files with 146 additions and 21 deletions

View File

@@ -57,6 +57,10 @@ type clientApp struct {
net *netclient.Client
log *logx.Logger
// 其他玩家位置(多人同步.md §3;渲染插值后置)
remoteMu sync.Mutex
remotePlayers map[uint32][3]float64
meshBuilder *mesh.Builder
mu sync.Mutex
@@ -90,6 +94,11 @@ func (a *clientApp) Tick(dt float64) {
} else {
a.screen = 1
a.rend.SetCursorMode(true)
a.hud.OnlineCount = func() int {
a.remoteMu.Lock()
defer a.remoteMu.Unlock()
return len(a.remotePlayers) + 1 // 含自己
}
a.logf("已连接服务器")
}
case "quit":
@@ -174,6 +183,7 @@ func (a *clientApp) Render() {
a.mu.Unlock()
for _, j := range pending {
a.rend.UploadChunk(j.cx, j.cz, j.m)
mesh.Release(j.m) // 上传完毕归还顶点池(性能与内存.md §2)
}
// 视图投影
@@ -365,19 +375,20 @@ func main() {
in := newInputState(rend.Window())
app := &clientApp{
sess: sess,
rend: rend,
reg: reg,
in: in,
uiR: uiR,
hud: hud,
titleScreen: titleScreen,
pauseScreen: pauseScreen,
log: log,
meshBuilder: mesh.NewBuilder(reg, uvFn),
winW: cfg.Client.WindowWidth,
winH: cfg.Client.WindowHeight,
lastTime: time.Now(),
sess: sess,
rend: rend,
reg: reg,
in: in,
uiR: uiR,
hud: hud,
titleScreen: titleScreen,
pauseScreen: pauseScreen,
log: log,
remotePlayers: make(map[uint32][3]float64),
meshBuilder: mesh.NewBuilder(reg, uvFn),
winW: cfg.Client.WindowWidth,
winH: cfg.Client.WindowHeight,
lastTime: time.Now(),
}
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)

View File

@@ -40,6 +40,13 @@ func (h *mpHandler) OnBlockChange(m netproto.BlockChange) {
h.app.sess.World.SetBlock(m.X, m.Y, m.Z, block.NewState(m.BlockID, m.Meta))
}
// OnEntityMove 其他玩家移动(多人同步.md §3:客户端存储位置,渲染插值后置)。
func (h *mpHandler) OnEntityMove(m netproto.EntityMove) {
h.app.remoteMu.Lock()
h.app.remotePlayers[m.EntityID] = [3]float64{float64(m.X), float64(m.Y), float64(m.Z)}
h.app.remoteMu.Unlock()
}
// dialServer 连接服务器(多人游戏按钮,多人同步.md §2)。
func dialServer(a *clientApp, addr string, name string) error {
h := &mpHandler{app: a}