First real-client session (2026-10-07 01:00) showed the client walking and attacking but UI interactions stalling: ~120 CsReq dropped with no reply. - auto-empty responder: any unknown CsReq with a Cmd-enum ScRsp pair now gets an empty ScRsp, except the danger families (GridFight/ChessRogue/ EvolveBuild/ChimeraDuel/Jukebox/CycleScore) which must stay dropped (client Sync(nil) NREs on empty, per the Rust lessons) - GetUnreleasedBlockInfo: the Endgame entry waits on this - 4.6.51 wire is CsReq 4190 -> ScRsp 4112 retcode tag 14 (the Rust build answered 4130, an id this client never sends) - SetClientPaused acked (client pauses itself when opening menus/map) - explicit handlers: TakeQuestReward, GetFirstTalkNpc, QuitBattle, GetMapRotationData (Amphoreus teleport pillars), GetPamSkinData, GetAllServerPrefsData/UpdateServerPrefsData, GetHeartDialInfo, GetPetData, GetShopList - SendRaw now logs (dummy/raw replies were invisible in gameserver.log) - cmdpairs.go: req->rsp id pairs generated from the Cmd enum (865 pairs), stable across message renames - smoke test extended: 4190->4112 and SetClientPaused ack verified
80 lines
2.7 KiB
Go
80 lines
2.7 KiB
Go
package gameserver
|
|
|
|
import (
|
|
goproto "gac-hkrpg-go/protocol/proto"
|
|
)
|
|
|
|
// Handlers for cmds the real 4.6.51 client sends during normal play that were
|
|
// dropped in the first test session (2026-10-07 01:00) — several of them gate
|
|
// UI state (pause menu, Endgame entry, map rotation) on the server's reply.
|
|
|
|
func init() {
|
|
// client pauses itself when opening menus/map — must be acked
|
|
handle("SetClientPaused", func(s *Session, req *goproto.SetClientPausedCsReq, rsp *goproto.SetClientPausedScRsp) error {
|
|
rsp.Retcode = 0
|
|
rsp.Paused = req.Paused
|
|
return nil
|
|
})
|
|
|
|
// the Endgame entrance waits for this before opening its UI
|
|
// (4.6.51: CsReq 4190 -> ScRsp 4112, retcode = tag 14 — the Rust build
|
|
// answered the wrong id 4130 and the client stalled)
|
|
rawHandlers[4190] = func(s *Session, payload []byte) error {
|
|
return s.SendRaw(&NetPacket{CmdType: 4112, Body: []byte{0x70, 0x00}})
|
|
}
|
|
|
|
handle("TakeQuestReward", func(s *Session, req *goproto.TakeQuestRewardCsReq, rsp *goproto.TakeQuestRewardScRsp) error {
|
|
rsp.Retcode = 0
|
|
rsp.SuccQuestIdList = req.SuccQuestIdList
|
|
return nil
|
|
})
|
|
|
|
handle("GetFirstTalkNpc", func(s *Session, req *goproto.GetFirstTalkNpcCsReq, rsp *goproto.GetFirstTalkNpcScRsp) error {
|
|
rsp.Retcode = 0
|
|
return nil
|
|
})
|
|
|
|
handle("QuitBattle", func(s *Session, req *goproto.QuitBattleCsReq, rsp *goproto.QuitBattleScRsp) error {
|
|
rsp.Retcode = 0
|
|
return nil
|
|
})
|
|
|
|
// Amphoreus map rotation (teleport pillars) — empty but valid
|
|
handle("GetMapRotationData", func(s *Session, req *goproto.GetMapRotationDataCsReq, rsp *goproto.GetMapRotationDataScRsp) error {
|
|
rsp.Retcode = 0
|
|
return nil
|
|
})
|
|
|
|
handle("GetPamSkinData", func(s *Session, req *goproto.GetPamSkinDataCsReq, rsp *goproto.GetPamSkinDataScRsp) error {
|
|
rsp.Retcode = 0
|
|
rsp.CurSkin = 0
|
|
rsp.UnlockSkinList = []uint32{0}
|
|
return nil
|
|
})
|
|
|
|
handle("GetAllServerPrefsData", func(s *Session, req *goproto.GetAllServerPrefsDataCsReq, rsp *goproto.GetAllServerPrefsDataScRsp) error {
|
|
rsp.Retcode = 0
|
|
return nil
|
|
})
|
|
|
|
handle("UpdateServerPrefsData", func(s *Session, req *goproto.UpdateServerPrefsDataCsReq, rsp *goproto.UpdateServerPrefsDataScRsp) error {
|
|
rsp.Retcode = 0
|
|
return nil
|
|
})
|
|
|
|
// simple empty-but-valid data replies (auto-empty also covers these, but
|
|
// keeping them explicit documents that they are safe to answer)
|
|
handle("GetHeartDialInfo", func(s *Session, req *goproto.GetHeartDialInfoCsReq, rsp *goproto.GetHeartDialInfoScRsp) error {
|
|
rsp.Retcode = 0
|
|
return nil
|
|
})
|
|
handle("GetPetData", func(s *Session, req *goproto.GetPetDataCsReq, rsp *goproto.GetPetDataScRsp) error {
|
|
rsp.Retcode = 0
|
|
return nil
|
|
})
|
|
handle("GetShopList", func(s *Session, req *goproto.GetShopListCsReq, rsp *goproto.GetShopListScRsp) error {
|
|
rsp.Retcode = 0
|
|
return nil
|
|
})
|
|
}
|