package common import ( "crypto/sha256" "encoding/hex" "encoding/json" "fmt" ) type CurrencyWarsOrb struct { ID uint32 `json:"OrbID"` Bonus uint32 `json:"BonusID"` Type uint32 `json:"Type"` } type CurrencyWarsConsumable struct { ID uint32 IfStack, IfConsume bool ConsumableRule uint32 ConsumableParamList []uint32 } type CurrencyWarsForge struct { ID, FuncType, EquipNum, EquipCategory uint32 ParamList []uint32 } type CurrencyWarsCombination struct { ID uint32 `json:"BonusID"` Pools []uint32 `json:"CombinationBonusList"` Counts []uint32 `json:"BonusNumberList"` } type CurrencyWarsRewards struct { Orbs map[uint32]CurrencyWarsOrb Consumables map[uint32]CurrencyWarsConsumable Forges map[uint32]CurrencyWarsForge Combinations map[uint32]CurrencyWarsCombination } // Tables are complete flat-table captures for the recorded Client revision. // Bonus-pool resolution and item-effect execution are separate prerequisites. func LoadCurrencyWarsRewards(c *CurrencyWarsCatalog) (*CurrencyWarsRewards, error) { raw, err := ReadResourceFile("resources/CurrencyWarsRewards.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"` Tables struct { Orbs []CurrencyWarsOrb `json:"orb"` Consumables []CurrencyWarsConsumable `json:"consumable"` Forges []CurrencyWarsForge `json:"forge"` Combinations []CurrencyWarsCombination `json:"combination"` } `json:"tables"` } if err = json.Unmarshal(raw, &r); err != nil { return nil, err } if c == nil || r.Format != 1 || r.Client != c.ClientVersion || r.Assembly != c.Provenance.GameAssemblySHA256 { return nil, fmt.Errorf("CW reward table revision differs") } hash, e := hex.DecodeString(r.Capture) if e != nil || len(hash) != sha256.Size { return nil, fmt.Errorf("CW reward capture provenance missing") } out := &CurrencyWarsRewards{Orbs: map[uint32]CurrencyWarsOrb{}, Consumables: map[uint32]CurrencyWarsConsumable{}, Forges: map[uint32]CurrencyWarsForge{}, Combinations: map[uint32]CurrencyWarsCombination{}} for _, v := range r.Tables.Orbs { if _, ok := out.Orbs[v.ID]; v.ID == 0 || v.Bonus == 0 || ok { return nil, fmt.Errorf("CW Orb identity invalid") } out.Orbs[v.ID] = v } for _, v := range r.Tables.Consumables { if _, ok := out.Consumables[v.ID]; v.ID == 0 || ok { return nil, fmt.Errorf("CW consumable identity invalid") } out.Consumables[v.ID] = v } for _, v := range r.Tables.Forges { if _, ok := out.Forges[v.ID]; v.ID == 0 || v.EquipNum == 0 || ok { return nil, fmt.Errorf("CW forge identity invalid") } out.Forges[v.ID] = v } for _, v := range r.Tables.Combinations { if _, ok := out.Combinations[v.ID]; v.ID == 0 || len(v.Pools) != len(v.Counts) || ok { return nil, fmt.Errorf("CW combination identity invalid") } out.Combinations[v.ID] = v } if len(out.Orbs) == 0 || len(out.Consumables) == 0 || len(out.Forges) == 0 || len(out.Combinations) == 0 { return nil, fmt.Errorf("CW reward tables incomplete") } return out, nil }