diff --git a/internal/packets/loader.go b/internal/packets/loader.go new file mode 100644 index 0000000..b7a7101 --- /dev/null +++ b/internal/packets/loader.go @@ -0,0 +1,146 @@ +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) +}