package common import ( "crypto/sha256" "encoding/hex" "encoding/json" "fmt" ) type CurrencyWarsTrialAvatar struct { SpecialAvatarID uint32 AvatarID uint32 WorldLevel uint32 Level uint32 Promotion uint32 Rank uint32 EnhancedID uint32 ExRankIDList []uint32 EquipmentID uint32 EquipmentLevel uint32 EquipmentPromotion uint32 EquipmentRank uint32 } func (c *CurrencyWarsCatalog) TrialAvatar(specialID, avatarID, worldLevel uint32) (CurrencyWarsTrialAvatar, error) { var result CurrencyWarsTrialAvatar raw, e := ReadResourceFile("resources/CurrencyWarsTrialAvatars.json") if e != nil { return result, e } 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 []CurrencyWarsTrialAvatar `json:"entries"` } if e = json.Unmarshal(raw, &r); e != nil { return result, e } digest, e := hex.DecodeString(r.Capture) if e != nil || len(digest) != sha256.Size || r.Format != 1 || r.Client != c.ClientVersion || r.Assembly != c.Provenance.GameAssemblySHA256 { return result, fmt.Errorf("CW trial capture revision differs") } seen := map[[2]uint32]bool{} for _, v := range r.Entries { key := [2]uint32{v.SpecialAvatarID, v.WorldLevel} if seen[key] || v.SpecialAvatarID == 0 || v.AvatarID == 0 || v.Level == 0 { return result, fmt.Errorf("CW trial configuration invalid") } seen[key] = true if v.SpecialAvatarID == specialID && v.AvatarID == avatarID && v.WorldLevel <= worldLevel && (result.SpecialAvatarID == 0 || v.WorldLevel > result.WorldLevel) { result = v } } if result.SpecialAvatarID == 0 { return result, fmt.Errorf("CW special avatar %d world level %d has not been captured", specialID, worldLevel) } return result, nil }