package common import ( "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "slices" ) type CurrencyWarsCraft struct { CraftID uint32 `json:"CraftID"` CraftEquipID uint32 `json:"CraftEquipID"` CostEquipList []uint32 `json:"CostEquipList"` } func LoadCurrencyWarsCrafts(catalog *CurrencyWarsCatalog) ([]CurrencyWarsCraft, error) { raw, err := ReadResourceFile("resources/CurrencyWarsCrafts.json") if err != nil { return nil, err } var data struct { Format uint32 `json:"format_version"` Client string `json:"target_client_version"` Assembly string `json:"target_assembly_sha256"` Hash string `json:"source_capture_sha256"` Entries []CurrencyWarsCraft `json:"entries"` } if err = json.Unmarshal(raw, &data); err != nil { return nil, err } if catalog == nil || data.Format != 1 || data.Client != catalog.ClientVersion || data.Assembly != catalog.Provenance.GameAssemblySHA256 { return nil, fmt.Errorf("CW crafting resource revision differs") } digest, err := hex.DecodeString(data.Hash) if err != nil || len(digest) != sha256.Size || len(data.Entries) == 0 { return nil, fmt.Errorf("CW crafting provenance is missing") } seen := map[uint32]bool{} for _, r := range data.Entries { if r.CraftID == 0 || r.CraftEquipID == 0 || seen[r.CraftID] || len(r.CostEquipList) != 2 || slices.Contains(r.CostEquipList, uint32(0)) { return nil, fmt.Errorf("CW craft identity/material schema differs") } seen[r.CraftID] = true } return data.Entries, nil }