package common import ( "crypto/sha256" "encoding/hex" "encoding/json" "fmt" ) type CurrencyWarsReferencePenalty struct { ID, ThresholdPosition, ThresholdFailPlayerHPPenalty, ThresholdPassBasicPlayerHPPenalty, ProgressPenaltyCoefficient uint32 } func LoadCurrencyWarsReferencePenalties(c *CurrencyWarsCatalog) (map[uint32]CurrencyWarsReferencePenalty, error) { b, err := ReadResourceFile("resources/CurrencyWarsReferencePenalties.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"` Reference string `json:"reference_executable_sha256"` Excel string `json:"excel_dump_sha256"` Table string `json:"source_table"` Rules []CurrencyWarsReferencePenalty `json:"penalty_rules"` } if err = json.Unmarshal(b, &r); err != nil { return nil, err } if c == nil || r.Format != 1 || r.Client != c.ClientVersion || r.Assembly != c.Provenance.GameAssemblySHA256 || r.Table != "grid_fight_penalty_rule" { return nil, fmt.Errorf("CW reference penalty compatibility differs") } for _, s := range []string{r.Reference, r.Excel} { h, e := hex.DecodeString(s) if e != nil || len(h) != sha256.Size { return nil, fmt.Errorf("CW reference penalty provenance missing") } } out := map[uint32]CurrencyWarsReferencePenalty{} for _, v := range r.Rules { if _, found := out[v.ID]; v.ID == 0 || found || v.ThresholdPosition > 100 { return nil, fmt.Errorf("CW reference penalty invalid") } out[v.ID] = v } if len(out) == 0 { return nil, fmt.Errorf("CW reference penalties empty") } return out, nil }