mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 23:54:33 +01:00
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]
60 lines
2.0 KiB
Go
60 lines
2.0 KiB
Go
package channelserver
|
|
|
|
import (
|
|
"erupe-ce/network/mhfpacket"
|
|
"net"
|
|
)
|
|
|
|
// ChannelRegistry abstracts cross-channel operations behind an interface.
|
|
// The default LocalChannelRegistry wraps the in-process []*Server slice.
|
|
// Future implementations may use DB/Redis/NATS for multi-process deployments.
|
|
type ChannelRegistry interface {
|
|
// Worldcast broadcasts a packet to all sessions across all channels.
|
|
Worldcast(pkt mhfpacket.MHFPacket, ignoredSession *Session, ignoredChannel *Server)
|
|
|
|
// FindSessionByCharID looks up a session by character ID across all channels.
|
|
FindSessionByCharID(charID uint32) *Session
|
|
|
|
// DisconnectUser disconnects all sessions belonging to the given character IDs.
|
|
DisconnectUser(cids []uint32)
|
|
|
|
// FindChannelForStage searches all channels for a stage whose ID has the
|
|
// given suffix and returns the owning channel's GlobalID, or "" if not found.
|
|
FindChannelForStage(stageSuffix string) string
|
|
|
|
// SearchSessions searches sessions across all channels using a predicate,
|
|
// returning up to max snapshot results.
|
|
SearchSessions(predicate func(SessionSnapshot) bool, max int) []SessionSnapshot
|
|
|
|
// SearchStages searches stages across all channels with a prefix filter,
|
|
// returning up to max snapshot results.
|
|
SearchStages(stagePrefix string, max int) []StageSnapshot
|
|
|
|
// NotifyMailToCharID finds the session for charID and sends a mail notification.
|
|
NotifyMailToCharID(charID uint32, sender *Session, mail *Mail)
|
|
}
|
|
|
|
// SessionSnapshot is an immutable copy of session data taken under lock.
|
|
type SessionSnapshot struct {
|
|
CharID uint32
|
|
Name string
|
|
StageID string
|
|
ServerIP net.IP
|
|
ServerPort uint16
|
|
UserBinary3 []byte // Copy of userBinaryParts index 3
|
|
}
|
|
|
|
// StageSnapshot is an immutable copy of stage data taken under lock.
|
|
type StageSnapshot struct {
|
|
ServerIP net.IP
|
|
ServerPort uint16
|
|
StageID string
|
|
ClientCount int
|
|
Reserved int
|
|
QuestReserved int // Players who left to enter quest stages ("Qs" prefix)
|
|
MaxPlayers uint16
|
|
RawBinData0 []byte
|
|
RawBinData1 []byte
|
|
RawBinData3 []byte
|
|
}
|