eq2go/internal/packets/handler.go

222 lines
6.9 KiB
Go

package packets
import (
"fmt"
"sync"
)
// PacketData represents processed packet information
type PacketData struct {
Opcode InternalOpcode
ClientOpcode uint16
ClientVersion int32
Data []byte
Size int32
}
// PacketContext provides context for packet handlers
type PacketContext struct {
Client ClientInterface // Client connection interface
World WorldInterface // World server interface
Database DatabaseInterface // Database interface
}
// ClientInterface defines the interface that client connections must implement
type ClientInterface interface {
GetCharacterID() int32
GetAccountID() int32
GetCharacterName() string
GetClientVersion() int32
GetAdminLevel() int
IsInZone() bool
SendPacket(opcode InternalOpcode, data []byte) error
Disconnect() error
}
// WorldInterface defines the interface for world server operations
type WorldInterface interface {
GetClientByID(characterID int32) ClientInterface
GetAllClients() []ClientInterface
BroadcastPacket(opcode InternalOpcode, data []byte)
BroadcastToZone(zoneID int32, opcode InternalOpcode, data []byte)
}
// DatabaseInterface defines database operations needed by packet handlers
type DatabaseInterface interface {
GetCharacter(characterID int32) (map[string]interface{}, error)
SaveCharacter(characterID int32, data map[string]interface{}) error
// Add more database methods as needed
}
// PacketHandlerFunc defines the signature for packet handler functions
type PacketHandlerFunc func(ctx *PacketContext, packet *PacketData) error
// PacketHandlerRegistry manages registration and dispatch of packet handlers
type PacketHandlerRegistry struct {
handlers map[InternalOpcode]PacketHandlerFunc
mutex sync.RWMutex
}
// NewPacketHandlerRegistry creates a new packet handler registry
func NewPacketHandlerRegistry() *PacketHandlerRegistry {
return &PacketHandlerRegistry{
handlers: make(map[InternalOpcode]PacketHandlerFunc),
}
}
// RegisterHandler registers a handler for a specific opcode
func (phr *PacketHandlerRegistry) RegisterHandler(opcode InternalOpcode, handler PacketHandlerFunc) {
phr.mutex.Lock()
defer phr.mutex.Unlock()
phr.handlers[opcode] = handler
fmt.Printf("Registered handler for opcode %s (%d)\n", GetInternalOpcodeName(opcode), int(opcode))
}
// UnregisterHandler removes a handler for a specific opcode
func (phr *PacketHandlerRegistry) UnregisterHandler(opcode InternalOpcode) {
phr.mutex.Lock()
defer phr.mutex.Unlock()
delete(phr.handlers, opcode)
}
// HasHandler checks if a handler is registered for an opcode
func (phr *PacketHandlerRegistry) HasHandler(opcode InternalOpcode) bool {
phr.mutex.RLock()
defer phr.mutex.RUnlock()
_, exists := phr.handlers[opcode]
return exists
}
// HandlePacket dispatches a packet to its registered handler
func (phr *PacketHandlerRegistry) HandlePacket(ctx *PacketContext, packet *PacketData) error {
phr.mutex.RLock()
handler, exists := phr.handlers[packet.Opcode]
phr.mutex.RUnlock()
if !exists {
// No handler registered - this is not necessarily an error
fmt.Printf("No handler registered for opcode %s (%d) from client %s\n",
GetInternalOpcodeName(packet.Opcode),
int(packet.Opcode),
ctx.Client.GetCharacterName())
return nil
}
// Call the handler
return handler(ctx, packet)
}
// GetHandlerCount returns the number of registered handlers
func (phr *PacketHandlerRegistry) GetHandlerCount() int {
phr.mutex.RLock()
defer phr.mutex.RUnlock()
return len(phr.handlers)
}
// GetRegisteredOpcodes returns all opcodes with registered handlers
func (phr *PacketHandlerRegistry) GetRegisteredOpcodes() []InternalOpcode {
phr.mutex.RLock()
defer phr.mutex.RUnlock()
opcodes := make([]InternalOpcode, 0, len(phr.handlers))
for opcode := range phr.handlers {
opcodes = append(opcodes, opcode)
}
return opcodes
}
// PacketProcessor combines opcode management and handler dispatch
type PacketProcessor struct {
opcodeManager *OpcodeManager
handlerRegistry *PacketHandlerRegistry
}
// NewPacketProcessor creates a new packet processor
func NewPacketProcessor() *PacketProcessor {
return &PacketProcessor{
opcodeManager: GetOpcodeManager(),
handlerRegistry: NewPacketHandlerRegistry(),
}
}
// ProcessRawPacket processes a raw packet from the UDP layer
func (pp *PacketProcessor) ProcessRawPacket(ctx *PacketContext, rawData []byte, clientOpcode uint16) error {
if len(rawData) < 2 {
return fmt.Errorf("packet too short: %d bytes", len(rawData))
}
// Convert client opcode to internal opcode
clientVersion := ctx.Client.GetClientVersion()
internalOpcode := pp.opcodeManager.ClientOpcodeToInternal(clientVersion, clientOpcode)
if internalOpcode == OP_Unknown {
fmt.Printf("Unknown opcode 0x%04X from client version %d (client: %s)\n",
clientOpcode, clientVersion, ctx.Client.GetCharacterName())
return nil // Don't treat unknown opcodes as errors
}
// Create packet data structure
packet := &PacketData{
Opcode: internalOpcode,
ClientOpcode: clientOpcode,
ClientVersion: clientVersion,
Data: rawData,
Size: int32(len(rawData)),
}
// Dispatch to handler
return pp.handlerRegistry.HandlePacket(ctx, packet)
}
// RegisterHandler registers a packet handler
func (pp *PacketProcessor) RegisterHandler(opcode InternalOpcode, handler PacketHandlerFunc) {
pp.handlerRegistry.RegisterHandler(opcode, handler)
}
// LoadOpcodeMap loads opcode mappings for a client version
func (pp *PacketProcessor) LoadOpcodeMap(clientVersion int32, opcodeMap map[string]uint16) error {
return pp.opcodeManager.LoadOpcodeMap(clientVersion, opcodeMap)
}
// GetStats returns processor statistics
func (pp *PacketProcessor) GetStats() (int, int, []int32) {
handlerCount := pp.handlerRegistry.GetHandlerCount()
supportedVersions := pp.opcodeManager.GetSupportedVersions()
totalOpcodes := 0
for _, version := range supportedVersions {
totalOpcodes += pp.opcodeManager.GetOpcodeCount(version)
}
return handlerCount, totalOpcodes, supportedVersions
}
// Global packet processor instance
var globalPacketProcessor = NewPacketProcessor()
// GetPacketProcessor returns the global packet processor
func GetPacketProcessor() *PacketProcessor {
return globalPacketProcessor
}
// Convenience functions for global access
// RegisterGlobalHandler registers a handler with the global processor
func RegisterGlobalHandler(opcode InternalOpcode, handler PacketHandlerFunc) {
globalPacketProcessor.RegisterHandler(opcode, handler)
}
// ProcessGlobalPacket processes a packet with the global processor
func ProcessGlobalPacket(ctx *PacketContext, rawData []byte, clientOpcode uint16) error {
return globalPacketProcessor.ProcessRawPacket(ctx, rawData, clientOpcode)
}
// LoadGlobalOpcodeMappings loads opcode mappings with the global processor
func LoadGlobalOpcodeMappings(clientVersion int32, opcodeMap map[string]uint16) error {
return globalPacketProcessor.LoadOpcodeMap(clientVersion, opcodeMap)
}