package packets import ( "embed" "eq2emu/internal/packets/parser" "fmt" "log" "path" "strings" "sync" ) //go:embed xml/**/*.xml var xmlFiles embed.FS var ( loadedPackets = make(map[string]*parser.PacketDef) loadedMutex sync.RWMutex loadError error ) func init() { err := loadAllPackets() if err != nil { loadError = err log.Printf("Failed to load packet definitions: %v", err) } } func loadAllPackets() error { entries, err := xmlFiles.ReadDir("xml") if err != nil { return fmt.Errorf("failed to read xml directory: %w", err) } packets := make(map[string]*parser.PacketDef) for _, entry := range entries { if !entry.IsDir() { continue } dirPath := path.Join("xml", entry.Name()) err := processDirectory(dirPath, packets) if err != nil { return fmt.Errorf("failed to process directory %s: %w", entry.Name(), err) } } loadedMutex.Lock() loadedPackets = packets loadedMutex.Unlock() log.Printf("Loaded %d packet definitions", len(packets)) return nil } func processDirectory(dirPath string, packets map[string]*parser.PacketDef) error { entries, err := xmlFiles.ReadDir(dirPath) if err != nil { return err } for _, entry := range entries { entryPath := path.Join(dirPath, entry.Name()) if entry.IsDir() { err := processDirectory(entryPath, packets) if err != nil { return err } continue } if !strings.HasSuffix(entry.Name(), ".xml") { continue } err := processXMLFile(entryPath, packets) if err != nil { log.Printf("Warning: failed to process %s: %v", entryPath, err) } } return nil } func processXMLFile(filePath string, packets map[string]*parser.PacketDef) error { content, err := xmlFiles.ReadFile(filePath) if err != nil { return fmt.Errorf("failed to read file: %w", err) } parsedPackets, err := parser.Parse(string(content)) if err != nil { return fmt.Errorf("failed to parse XML: %w", err) } for name, packet := range parsedPackets { if existing, exists := packets[name]; exists { log.Printf("Warning: packet '%s' already exists, overwriting", name) _ = existing } packets[name] = packet } return nil } func GetPacket(name string) (*parser.PacketDef, bool) { if loadError != nil { return nil, false } loadedMutex.RLock() defer loadedMutex.RUnlock() packet, exists := loadedPackets[name] return packet, exists } func GetPacketNames() []string { if loadError != nil { return nil } loadedMutex.RLock() defer loadedMutex.RUnlock() names := make([]string, 0, len(loadedPackets)) for name := range loadedPackets { names = append(names, name) } return names } func GetPacketCount() int { if loadError != nil { return 0 } loadedMutex.RLock() defer loadedMutex.RUnlock() return len(loadedPackets) }