using game.PlayerDataStorage; using Newtonsoft.Json.Linq; static partial class Tests { const string CubeJson="{\"TicketCount\":1,\"FirstOpen\":true,\"IsFinished\":true,\"EventId\":2,\"IsInGuide\":true,\"StartTime\":\"2026-09-22T00:00:00.0000000Z\",\"EndTime\":\"2026-09-24T00:00:00.0000000Z\",\"CurrentStagetId\":3,\"CollectItems\":[{\"ItemId\":4,\"Count\":5,\"MaxCount\":6,\"ItemTrueId\":7}],\"BoardData\":[8,9],\"BoardViewSize\":{\"x\":10,\"y\":11},\"CollectRewardsId\":[12,13],\"IsFinalRewardGet\":true,\"PieceDatas\":[[14,15],[16,17]],\"Cycle\":18,\"InflationRate\":1.5}"; static async Task RunCubeSchemaTests() { await Run("M19-cube-all-fields-nested-collections",() => { var obj=JObject.Parse(CubeJson); Dictionary Raw(JObject value)=>new() { ["EventCubeMeltData"]=value.ToString() }; var state=PlayerKVSaveSchema.DecodeCube(Raw(obj),SchemaSnapshot(),new()); Check(state.IsPresent && state.TicketCount==1 && state.FirstOpen && state.IsFinished && state.EventId==2 && state.IsInGuide && state.StartTime.Day==22 && state.EndTime.Day==24 && state.CurrentStagetId==3,"base fields"); Check(state.CollectItems[0].ItemId==4 && state.CollectItems[0].Count==5 && state.CollectItems[0].MaxCount==6 && state.CollectItems[0].ItemTrueId==7 && state.BoardData.SequenceEqual(new[] { 8,9 }),"items and board"); Check(state.Width==10 && state.Height==11 && state.CollectRewardsId.SequenceEqual(new[] { 12,13 }) && state.IsFinalRewardGet && state.Cycle==18 && state.InflationRate==1.5f,"dimensions and progress"); Check(state.PieceDatas[0].SequenceEqual(new[] { 14,15 }) && state.PieceDatas[1].SequenceEqual(new[] { 16,17 }),"nested pieces"); foreach(var path in obj.Properties().Select(p=>p.Name).Concat(new[] { "CollectItems[0]","CollectItems[0].Count","BoardViewSize.x","BoardViewSize.y","PieceDatas[0]","PieceDatas[0][0]" })) { var bad=(JObject)obj.DeepClone(); bad.SelectToken(path).Replace(JValue.CreateNull()); Check(PlayerKVSaveSchema.DecodeCube(Raw(bad),SchemaSnapshot(),new())==null,"all nested nulls reject"); } Check(!PlayerKVSaveSchema.DecodeCube(new Dictionary(),SchemaSnapshot(),new()).IsPresent,"missing explicit"); Check(PlayerKVSaveSchema.DecodeCube(new Dictionary { ["EventCubeMeltData"]="null" },SchemaSnapshot(),new())==null,"null not missing"); return Task.CompletedTask; }); } }