mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-26 09:33:02 +01:00
fix(channelserver): correct session handler retail mismatches (#167)
Lobby search now returns only quest-bound players (QuestReserved) instead of all reserved slots, matching retail behavior. The new field is pre-collected under server lock before stage iteration to respect Server.Mutex → Stage.RWMutex lock ordering. Replaced three TODOs with RE documentation from Ghidra decompilation of mhfo-hd.dll ZZ: - Log key off-by-one: putRecord_log/putTerminal_log pass size 0 for the key field in ZZ, so the stored key is unused beyond issuance - User search padding: ZZ per-entry parser confirms 40-byte block via memcpy(dst, src+8, 0x28); G2 DLL analysis inconclusive (stripped) - Player count: field at entry offset 0x08 maps to struct param_1[0xe]
This commit is contained in:
@@ -407,8 +407,13 @@ func handleMsgSysIssueLogkey(s *Session, p mhfpacket.MHFPacket) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(Andoryuuta): In the official client, the log key index is off by one,
|
||||
// cutting off the last byte in _most uses_. Find and document these accordingly.
|
||||
// Client log key off-by-one (RE'd from mhfo-hd.dll ZZ):
|
||||
// putIssue_logkey (0x1D) requests and stores all 16 bytes correctly.
|
||||
// putRecord_log (0x1E) and putTerminal_log (0x13) do NOT embed the log key
|
||||
// in their packets — they pass size 0 to the packet builder for the key field.
|
||||
// The original off-by-one note (Andoryuuta) may apply to pre-ZZ clients where
|
||||
// these functions did use the key. In ZZ the key is stored but never sent back,
|
||||
// so the server value is effectively unused beyond issuance.
|
||||
s.Lock()
|
||||
s.logKey = logKey
|
||||
s.Unlock()
|
||||
@@ -548,7 +553,11 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint8(uint8(len(sjisName) + 1))
|
||||
resp.WriteUint16(uint16(len(snap.UserBinary3)))
|
||||
|
||||
// TODO: This case might be <=G2
|
||||
// User search response padding block (RE'd from mhfo-hd.dll ZZ):
|
||||
// ZZ per-entry parser (FUN_115868a0) reads 0x28 (40) bytes at offset +8
|
||||
// via memcpy into the result struct. G1 and earlier use 8 bytes.
|
||||
// G2 DLL analysis was inconclusive (stripped binary, no shared struct
|
||||
// sizes with ZZ) — the boundary may be <=G2 rather than <=G1.
|
||||
if s.server.erupeConfig.RealClientMode <= cfg.G1 {
|
||||
resp.WriteBytes(make([]byte, 8))
|
||||
} else {
|
||||
@@ -711,8 +720,10 @@ func handleMsgMhfTransitMessage(s *Session, p mhfpacket.MHFPacket) {
|
||||
resp.WriteUint16(0) // Unk, [0 1 2]
|
||||
resp.WriteUint16(uint16(sr.ClientCount))
|
||||
resp.WriteUint16(sr.MaxPlayers)
|
||||
// TODO: Retail returned the number of clients in quests, not workshop/my series
|
||||
resp.WriteUint16(uint16(sr.Reserved))
|
||||
// Retail returned only clients in quest stages ("Qs" prefix),
|
||||
// not workshop/my series. RE'd from FUN_11586690 in mhfo-hd.dll ZZ:
|
||||
// field at entry offset 0x08-0x09 → struct offset 0x1C (param_1[0xe]).
|
||||
resp.WriteUint16(uint16(sr.QuestReserved))
|
||||
|
||||
resp.WriteUint8(0) // Static?
|
||||
resp.WriteUint8(uint8(sr.MaxPlayers))
|
||||
|
||||
Reference in New Issue
Block a user