// ============================== // SaveGame.cs (refactored) // ============================== using System; using System.Collections.Generic; using BriarQueen.Data.Identifiers; using MemoryPack; namespace BriarQueen.Data.IO.Saves { [Serializable] [MemoryPackable] public partial class SaveGame { public string SaveVersion = "0.0.2-alpha"; public string SaveFileName; // Inventory & item tracking public List InventoryData = new(); public List CollectedItems = new(); public List RemovedItems = new(); public Dictionary Tools = new(); // Codex public List DiscoveredCodexEntries = new(); // Current location public string CurrentSceneID; public string CurrentLevelID; // Per-puzzle persisted state (resume progress when revisiting) public List PuzzleStates = new(); public bool OpeningCinematicPlayed; // Centralized game variables public PersistentGameVariables PersistentVariables = new(); // Level-specific hints public Dictionary LevelHintStages = new(); } [Serializable] [MemoryPackable] public partial class ItemSaveData { public string UniqueIdentifier; } [Serializable] [MemoryPackable] public partial class CodexSaveData { public string UniqueIdentifier; } [Serializable] [MemoryPackable] public partial class PuzzleStateSaveData { public string PuzzleID; public byte[] State; public bool Completed; } [Serializable] [MemoryPackable] public partial class PersistentGameVariables { public GameVariables Game = new(); public TutorialPopupVariables TutorialPopupVariables = new(); } [Serializable] [MemoryPackable] public partial class TutorialPopupVariables { // Tracks which popups have been shown public HashSet DisplayedPopups = new(); public bool HasBeenDisplayed(TutorialPopupID id) { return DisplayedPopups.Contains(id); } public void MarkDisplayed(TutorialPopupID id) { DisplayedPopups.Add(id); } } [Serializable] public enum LevelFlag { None = 0, FountainVinesCut, PumpHouseOpened, PumpHousePipesFixed, PumpWaterRestored, WorkshopBagHoleDug, WorkshopSafeUnlocked, WorkshopDownstairsDoorOpen, WorkshopDownstairsLightOn, WorkshopGrindstoneRepaired, VillageStreetGateOpen, VillageStreetVinesCut, LaxleyFireplaceExtinguished, LaxleyLockboxOpened, } [Serializable] [MemoryPackable] public partial class GameVariables { // Type-safe level flags using enum public Dictionary LevelFlags = new(); // Tracks completed puzzles public Dictionary PuzzleCompleted = new(); // Candle slots public Dictionary WorkshopCandleSlotsFilled = new() { { 0, ItemIDs.Pickups[ItemKey.BlueCandle] }, { 3, ItemIDs.Pickups[ItemKey.OrangeCandle] }, { 5, ItemIDs.Pickups[ItemKey.RedCandle] } }; // -------- Helper Methods -------- public bool IsPuzzleCompleted(PuzzleKey puzzle) { return PuzzleCompleted.TryGetValue(PuzzleIdentifiers.AllPuzzles[puzzle], out var completed) && completed; } public void SetPuzzleCompleted(PuzzleKey puzzle, bool completed = true) { PuzzleCompleted[PuzzleIdentifiers.AllPuzzles[puzzle]] = completed; } public bool GetLevelFlag(LevelFlag flag) { return LevelFlags.TryGetValue(flag, out var value) && value; } public void SetLevelFlag(LevelFlag flag, bool value = true) { LevelFlags[flag] = value; } } }