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]any, error) SaveCharacter(characterID int32, data map[string]any) 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) }