package catalogs import ( "encoding/json" "errors" "fmt" "os" "path/filepath" "sync" ) type ItemCatalogEntry4229938 struct { Id uint32 `json:"id"` Name string `json:"name"` Quality uint32 `json:"quality"` SubType uint32 `json:"subType"` } var itemCatalogState = struct { sync.RWMutex byPath map[string][]ItemCatalogEntry4229938 current []ItemCatalogEntry4229938 }{byPath: make(map[string][]ItemCatalogEntry4229938)} // LoadItemCatalog4229938 accepts the legacy slim ItemCatalog table or the // ConsumableConfig projection shipped in this Go repository. Cache keys include // the source path, so loading another configuration cannot reuse the first table. func LoadItemCatalog4229938(configDir string) ([]any, error) { path, err := filepath.Abs(filepath.Join(configDir, "ItemCatalog.json")) if err != nil { return nil, err } itemCatalogState.Lock() defer itemCatalogState.Unlock() entries, ok := itemCatalogState.byPath[path] if !ok { data, err := os.ReadFile(path) if errors.Is(err, os.ErrNotExist) { data, err = os.ReadFile(filepath.Join(configDir, "ConsumableConfig.json")) } if err != nil { return nil, err } var raw struct { Records []ItemCatalogEntry4229938 `json:"records"` } if err = json.Unmarshal(data, &raw); err != nil { return nil, err } if raw.Records == nil { return nil, fmt.Errorf("item catalog missing records array") } entries = make([]ItemCatalogEntry4229938, 0, len(raw.Records)) for _, entry := range raw.Records { if entry.Id != 0 { entries = append(entries, entry) } } itemCatalogState.byPath[path] = entries } itemCatalogState.current = entries result := make([]any, len(entries)) for i, entry := range entries { result[i] = entry } return result, nil } func ItemCatalog4229938_Find(id uint32) *ItemCatalogEntry4229938 { itemCatalogState.RLock() defer itemCatalogState.RUnlock() for _, entry := range itemCatalogState.current { if entry.Id == id { copy := entry return © } } return nil }