using game.PlayerDataStorage; using Newtonsoft.Json; static partial class Tests { static async Task RunPlayerSchemaTests() { await Run("M01-player-additional-fields-and-ownership",() => { var raw=ModernRaw(); raw["NewRodList"]="[7,8]"; raw["SeasonId"]="9"; raw["IsOpenAppraise"]=""; raw["InfiniteBuildingData"]="raw"; var modern=new Dictionary { ["newData"]=string.Join(",",CompleteCore),["vipL"]="-1,5|0,6|1,7" }; var a=PlayerKVSaveSchema.DecodePlayer(raw,modern,SchemaSnapshot(),new()); Check(a!=null && a.VipScores[-1]==5 && a.VipScores[0]==6 && a.VipScores[1]==7 && a.NewRods.SequenceEqual(new[] { 7,8 }) && a.Season==9 && a.Appraise && a.Building=="raw","all extra fields"); modern["vipL"]=""; Check(a.Modern["vipL"]=="-1,5|0,6|1,7","modern copied"); var b=PlayerKVSaveSchema.DecodePlayer(ModernRaw(),modern,SchemaSnapshot(),new()); Check(b.NewRods.Count==0 && b.VipScores.Count==0 && b.Season==0 && !b.Appraise && b.Building=="0","missing building restores original zero default"); foreach(var text in new[]{"", "0", "23,7"}) { var existing=ModernRaw(); existing["InfiniteBuildingData"]=text; Check(PlayerKVSaveSchema.DecodePlayer(existing,modern,SchemaSnapshot(),new()).Building==text,"existing building string unchanged"); } foreach(var vip in new[] { "0,1|00,2","0,1|","1,2,3","null",null }) { modern["vipL"]=vip; Check(PlayerKVSaveSchema.DecodePlayer(raw,modern,SchemaSnapshot(),new())==null,"bad vip map rejects"); } modern["vipL"]=""; foreach(var key in new[] { "NewRodList","SeasonId","IsOpenAppraise","InfiniteBuildingData" }) { var bad=new Dictionary(raw) { [key]=null }; Check(PlayerKVSaveSchema.DecodePlayer(bad,modern,SchemaSnapshot(),new())==null,"present null extra fails"); } var missingCore=new Dictionary(); Check(PlayerKVSaveSchema.DecodePlayer(missingCore,new Dictionary(),SchemaSnapshot(),new())==null,"no default account creation"); return Task.CompletedTask; }); } }