package common import ( "encoding/json" "fmt" "sync" ) type PlayerCosmetics struct { ClientVersion string `json:"client_version"` OutfitItems []struct { ItemID uint32 `json:"item_id"` PileLimit uint32 `json:"pile_limit"` OwnedCount uint32 `json:"owned_count"` } `json:"outfit_items"` Skins []struct { ID uint32 `json:"id"` AvatarID uint32 `json:"avatar_id"` } `json:"skins"` } var cosmeticsOnce sync.Once var cosmeticsData PlayerCosmetics var cosmeticsError error func LoadPlayerCosmetics() (*PlayerCosmetics, error) { cosmeticsOnce.Do(func() { raw, err := ReadResourceFile("resources/PlayerCosmetics.json") if err != nil { cosmeticsError = err return } if err = json.Unmarshal(raw, &cosmeticsData); err != nil { cosmeticsError = err return } cfg, err := LoadRuntimeConfig() if err != nil { cosmeticsError = err return } if cfg.ClientVersion != cosmeticsData.ClientVersion || len(cosmeticsData.OutfitItems) == 0 { cosmeticsError = fmt.Errorf("missing or mismatched PlayerCosmetics resource") return } seen := map[uint32]bool{} for _, item := range cosmeticsData.OutfitItems { if item.ItemID == 0 || item.OwnedCount == 0 || item.OwnedCount > item.PileLimit || seen[item.ItemID] { cosmeticsError = fmt.Errorf("invalid outfit item %d", item.ItemID) return } seen[item.ItemID] = true } }) return &cosmeticsData, cosmeticsError }