using System; using System.Collections.Generic; using System.Linq; using ProjectI.Combat; using UnityEngine; namespace ProjectI.Builds { [Serializable] public sealed class LocalLoadoutRecord { public int Version=1; public BuildLoadout Build=BuildLoadout.Default; public int FirstWeapon=1,SecondWeapon=2; } public static class LocalLoadoutStore { private const string Key="ProjectI.LocalLoadout.v1"; public static LocalLoadoutRecord LoadValidated(IReadOnlyDictionary catalog,AbilityUnlockState unlocks) => ValidateSerialized(PlayerPrefs.GetString(Key,""),catalog,unlocks); public static LocalLoadoutRecord ValidateSerialized(string json,IReadOnlyDictionary catalog,AbilityUnlockState unlocks) { if(catalog==null||unlocks==null)throw new ArgumentNullException(); LocalLoadoutRecord record; try{record=JsonUtility.FromJson(json);}catch{record=null;} if(record==null||record.Version!=1)record=new LocalLoadoutRecord(); var used=new HashSet(); int Repair(int selected,AbilitySlot slot) { if(catalog.TryGetValue(selected,out var definition)&&definition.Slot==slot&&unlocks.IsUnlocked(selected)&&used.Add(selected))return selected; int id=catalog.Values.Where(x=>x.Slot==slot&&unlocks.IsUnlocked(x.Id)&&!used.Contains(x.Id)).OrderBy(x=>x.Id).Select(x=>x.Id).FirstOrDefault(); if(id==0)throw new InvalidOperationException("The unlocked roster cannot fill all build slots.");used.Add(id);return id; } var b=record.Build; record.Build=new BuildLoadout(Repair(b.PassiveFirst,AbilitySlot.Passive),Repair(b.PassiveSecond,AbilitySlot.Passive),Repair(b.ActiveFirst,AbilitySlot.Active),Repair(b.ActiveSecond,AbilitySlot.Active),Repair(b.ActiveThird,AbilitySlot.Active),Repair(b.Ultimate,AbilitySlot.Ultimate),Repair(b.Melee,AbilitySlot.Melee)); var weapons=WeaponRoster.Entries.Where(x=>x!=null).Select(x=>x.weaponId).Distinct().ToArray(); if(weapons.Length<2)throw new InvalidOperationException("The weapon roster requires two distinct weapons."); if(!weapons.Contains(record.FirstWeapon))record.FirstWeapon=weapons[0]; if(!weapons.Contains(record.SecondWeapon)||record.SecondWeapon==record.FirstWeapon)record.SecondWeapon=weapons.First(x=>x!=record.FirstWeapon); return record; } public static void Save(LocalLoadoutRecord record) { if(record==null||record.Version!=1)throw new ArgumentException("Unsupported local loadout record.",nameof(record)); PlayerPrefs.SetString(Key,JsonUtility.ToJson(record));PlayerPrefs.Save(); } } }