using System; using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace BaseGames.Core.Save { // ─── 顶层 ───────────────────────────────────────────────────────────────── [Serializable] public class SaveData { [JsonExtensionData] public Dictionary ExtensionData = new(); public SaveMeta Meta = new(); public PlayerSaveData Player = new(); public EquipmentSaveData Equipment = new(); public WorldSaveData World = new(); public MapSaveData Map = new(); public QuestSaveData Quests = new(); public AchievementSaveData Achievements = new(); public ToolsSaveData Tools = new(); public ChallengeRoomsSaveData ChallengeRooms = new(); public EventChainsSaveData EventChains = new(); public ShopsSaveData Shops = new(); public StatsSaveData Stats = new(); public NGPlusSaveData NGPlus = null; // null = 非 NG+ 模式 public TutorialSaveData Tutorial = new(); public SettingsSaveData Settings = new(); public Dictionary DLC = new(); } // ─── Meta ───────────────────────────────────────────────────────────────── [Serializable] public class SaveMeta { public string Version = "2.1"; public int SlotIndex; public string LastSaved; // ISO 8601 public float Playtime; public string SavePointId; public int NGPlusCount; public int SaveCount; public string Checksum; // HMAC-SHA256 /// 此存档是否以钢铁之魂(一命)模式开始;加载后 DifficultyManager 会锁定到 SteelSoul。 public bool IsSteelSoul; } // ─── Player ─────────────────────────────────────────────────────────────── [Serializable] public class PlayerSaveData { public float PosX, PosY; public string Scene; public int CurrentHP, MaxHP; public int CurrentGeo, LifetimeGeo; // 能力解锁位掩码(AbilityType [Flags] uint bitmask) public uint AbilityFlags = 0; public string ActiveFormId; public List UnlockedFormIds = new(); public DeathShadeSaveData DeathShade; // 护盾:-1 = 满护盾(默认),>= 0 = 当前耐久值 public int ShieldHP = -1; public bool ShieldIsBroken = false; } [Serializable] public class DeathShadeSaveData { public float PosX, PosY; public string SceneId; public int GeoAmount; } // ─── Equipment ──────────────────────────────────────────────────────────── [Serializable] public class EquipmentSaveData { public List EquippedCharmIds = new(); public int NotchesUsed; public int MaxNotches; public List OwnedCharmIds = new(); public List UpgradedCharmIds = new(); } // ─── World ──────────────────────────────────────────────────────────────── [Serializable] public class WorldSaveData { public List VisitedScenes = new(); public List ActivatedSavePoints = new(); public List OpenedDoors = new(); public List DefeatedBossIds = new(); public List CollectedIds = new(); public List DestroyedObjectIds = new(); public Dictionary Switches = new(); public Dictionary NpcRelations = new(); public HashSet ChallengeFirstClears = new(); } // ─── Map ────────────────────────────────────────────────────────────────── [Serializable] public class MapSaveData { public List ExploredRooms = new(); // 踏入过的房间 ID public List MappedRooms = new(); // 完整地图信息(购买/存档点揭示) public List Pins = new(); // 玩家自定义地图标记 } /// 玩家在地图上放置的自定义标记(架构 15_MapShopModule §1.5)。 [Serializable] public class MapPin { public string RoomId; public float NormalizedPosX; public float NormalizedPosY; public int PinTypeInt; // PinType 枚举整数值,避免 SaveData 依赖 Map 程序集 public string Note; // 玩家备注(最多 64 字符) } public enum PinType { Marker = 0, Chest = 1, Enemy = 2, Path = 3, Note = 4, } // ─── Quests ─────────────────────────────────────────────────────────────── [Serializable] public class QuestSaveData { public Dictionary QuestStates = new(); public List AvailableQuestIds = new(); } [Serializable] public class QuestState { public string Status; // "NotStarted"|"Active"|"Completed"|"Failed" public int ObjectiveIndex; public List ProgressCounts = new(); public string GiverNpcId; } // ─── Achievements ───────────────────────────────────────────────────────── [Serializable] public class AchievementSaveData { public List Unlocked = new(); public Dictionary Progress = new(); } [Serializable] public class AchievementProgress { public int Count; public float Percent; } // ─── Stats ──────────────────────────────────────────────────────────────── [Serializable] public class StatsSaveData { public int EnemyKills, Deaths, ParrySuccess, ParryFail; public int GeoEarned, GeoLost; public float DistanceTraveled; public float SpeedrunTime; public int SaveCount; public Dictionary SkillUseCounts = new(); public Dictionary DeathsByBoss = new(); } // ─── Tools ──────────────────────────────────────────────────────────────── [Serializable] public class ToolsSaveData { public string ToolSlot0; public string ToolSlot1; public List OwnedToolIds = new(); public Dictionary ToolStates = new(); } // ─── ChallengeRooms ─────────────────────────────────────────────────────── [Serializable] public class ChallengeRoomsSaveData { public Dictionary Records = new(); } [Serializable] public class ChallengeRoomRecord { public int BestScore; public float BestTime; public string BestRank; // "S"/"A"/"B"/"C" public int CompletionCount; } // ─── EventChains ────────────────────────────────────────────────────────── [Serializable] public class EventChainsSaveData { public Dictionary ChainStates = new(); public Dictionary WorldFlags = new(); } // ─── Shops ──────────────────────────────────────────────────────────────── [Serializable] public class ShopsSaveData { public Dictionary ShopRecords = new(); } [Serializable] public class ShopRecord { public List SoldUniqueItems = new(); public Dictionary PurchaseCounts = new(); } // ─── NGPlus ─────────────────────────────────────────────────────────────── [Serializable] public class NGPlusSaveData { public int NGPlusCount; public bool SteelSoulMode; public Dictionary NGPlusFlags = new(); } // ─── SlotSummary(主菜单 UI 用)──────────────────────────────────────────── public class SlotSummary { public int SlotIndex; public float Playtime; public string LastSaved; public string SceneName; public string ActiveFormId; } // ─── Tutorial ───────────────────────────────────────────────────────────── [Serializable] public class TutorialSaveData { /// 已完成(不再弹出)的提示 ID 列表。 public List CompletedHintIds = new(); } // ─── Settings ───────────────────────────────────────────────────────────── [Serializable] public class SettingsSaveData { /// 玩家选择的语言。空字符串 = 使用系统默认。 public string Language = string.Empty; } }