package common import ( "crypto/sha256" "encoding/hex" "encoding/json" "fmt" ) // Only initialized handbook equipment is captured, not consumables or a claim // of the complete hidden item table. Native fixed-point values remain text. type CurrencyWarsEquipment struct { ItemID uint32 `json:"ItemID"` BaseItemID uint32 `json:"BaseItemID"` NeedEquipSlot bool `json:"NeedEquipSlot"` EquipType uint32 `json:"EquipType"` EquipCategory uint32 `json:"EquipCategory"` EquipFunc uint32 `json:"EquipFunc"` DressRule uint32 `json:"DressRule"` AbilityName string `json:"AbilityName"` GeneralPropertyList []CurrencyWarsNativePropertyValue `json:"GeneralPropertyList"` AbilityParamList []string `json:"AbilityParamList"` EquipFuncParamList []uint32 `json:"EquipFuncParamList"` DressRuleParamList []uint32 `json:"DressRuleParamList"` } func LoadCurrencyWarsEquipment(catalog *CurrencyWarsCatalog) (map[uint32]CurrencyWarsEquipment, error) { raw, err := ReadResourceFile("resources/CurrencyWarsEquipment.json") if err != nil { return nil, err } var r struct { Format uint32 `json:"format_version"` Client string `json:"target_client_version"` Assembly string `json:"target_assembly_sha256"` Capture string `json:"source_capture_sha256"` Entries []CurrencyWarsEquipment `json:"entries"` } if err = json.Unmarshal(raw, &r); err != nil { return nil, err } if catalog == nil || r.Format != 1 || r.Client != catalog.ClientVersion || r.Assembly != catalog.Provenance.GameAssemblySHA256 { return nil, fmt.Errorf("CW equipment revision differs") } digest, err := hex.DecodeString(r.Capture) if err != nil || len(digest) != sha256.Size || len(r.Entries) == 0 { return nil, fmt.Errorf("CW equipment capture missing") } values := make(map[uint32]CurrencyWarsEquipment, len(r.Entries)) for _, row := range r.Entries { if _, duplicate := values[row.ItemID]; row.ItemID == 0 || row.BaseItemID == 0 || duplicate { return nil, fmt.Errorf("CW equipment identity invalid/duplicated") } for _, property := range row.GeneralPropertyList { if property.PropertyType == 0 || !currencyWarsDecimal.MatchString(property.Value) { return nil, fmt.Errorf("CW equipment property value invalid") } } for _, parameter := range row.AbilityParamList { if !currencyWarsDecimal.MatchString(parameter) { return nil, fmt.Errorf("CW equipment ability parameter invalid") } } values[row.ItemID] = row } return values, nil }