using System; using System.Collections.Generic; using BriarQueen.Data.Identifiers; using BriarQueen.Data.IO.Saves; using BriarQueen.Framework.Events.Progression; using BriarQueen.Framework.Events.UI; using BriarQueen.Framework.Managers.Hints.Data; using BriarQueen.Framework.Managers.Levels.Data; using BriarQueen.Framework.Managers.Player.Data; using BriarQueen.Framework.Services.Puzzles.Base; using Cysharp.Threading.Tasks; using MemoryPack; using UnityEngine; namespace BriarQueen.Game.Puzzles.ChapterOne.Fountain { [Serializable] [MemoryPackable] public partial struct FountainGemPuzzleState { public bool IsCompleted; public string[] InputtedGemIDs; } public class FountainGemBasePuzzle : BasePuzzle, IPuzzleStateful { [SerializeField] private FountainGemSlot _fountainGemSlot; public override string PuzzleID => PuzzleIdentifiers.AllPuzzles[PuzzleKey.FountainGemPuzzle]; public override string LevelName => "Hole in the side of a Fountain"; public override Dictionary Hints { get; } = new(); private readonly List _inputtedGems = new(); private readonly List _inputtedGemIDs = new(); private readonly string[] _correctSequence = { ItemIDs.Get(ItemKey.Sapphire), ItemIDs.Get(ItemKey.Emerald), ItemIDs.Get(ItemKey.Ruby) }; private bool _isCompleted; public bool IsCompleted => _isCompleted; protected override UniTask PostActivateInternal() { TutorialService.DisplayTutorial(TutorialPopupID.ResetPuzzles); return UniTask.CompletedTask; } protected void Start() { if (_fountainGemSlot != null) _fountainGemSlot.Initialize(this); } internal bool TryInsertGem(ItemDataSo item) { if (_isCompleted || item == null) return false; var itemID = item.UniqueID; if (string.IsNullOrWhiteSpace(itemID)) return false; _inputtedGems.Add(item); _inputtedGemIDs.Add(itemID); ConsumePlayerGem(item); if (_inputtedGemIDs.Count < _correctSequence.Length) return true; if (IsCorrectSequence()) { CompletePuzzle().Forget(); return true; } AudioManager.Play(AudioNameIdentifiers.Get(SFXKey.PuzzleIncorrect)); ResetPuzzleState(); return false; } public override UniTask CompletePuzzle() { if (_isCompleted) return UniTask.CompletedTask; _isCompleted = true; SaveManager.SetLevelFlag(LevelFlag.VillageStreetGateOpen, true); SaveManager.SetPuzzleCompleted(PuzzleKey.FountainGemPuzzle, true); AudioManager.Play(AudioNameIdentifiers.Get(SFXKey.GateOpening)); EventCoordinator.Publish(new UnlockAchievementEvent(AchievementID.FountainGemPuzzleSolved)); return UniTask.CompletedTask; } public UniTask CaptureState() { var state = new FountainGemPuzzleState { IsCompleted = _isCompleted, InputtedGemIDs = _inputtedGemIDs.ToArray() }; return UniTask.FromResult(MemoryPackSerializer.Serialize(state)); } public UniTask RestoreState(byte[] state) { _inputtedGems.Clear(); _inputtedGemIDs.Clear(); _isCompleted = false; if (state == null || state.Length == 0) { _isCompleted = SaveManager.GetLevelFlag(LevelFlag.VillageStreetGateOpen); return UniTask.CompletedTask; } var restoredState = MemoryPackSerializer.Deserialize(state); _isCompleted = restoredState.IsCompleted; if (restoredState.InputtedGemIDs != null) _inputtedGemIDs.AddRange(restoredState.InputtedGemIDs); if (_isCompleted) { SaveManager.SetLevelFlag(LevelFlag.VillageStreetGateOpen, true, false); SaveManager.SetPuzzleCompleted(PuzzleKey.FountainGemPuzzle, true, false); } return UniTask.CompletedTask; } public void ResetPuzzleState() { if (_isCompleted) return; for (int i = 0; i < _inputtedGems.Count; i++) { var gem = _inputtedGems[i]; if (gem != null) PlayerManager.CollectItem(gem); } _inputtedGems.Clear(); _inputtedGemIDs.Clear(); } public void OnResetButtonPressed() { AudioManager.Play(AudioNameIdentifiers.Get(SFXKey.ResetPuzzle)); ResetPuzzleState(); } private bool IsCorrectSequence() { if (_inputtedGemIDs.Count != _correctSequence.Length) return false; for (int i = 0; i < _correctSequence.Length; i++) { if (_inputtedGemIDs[i] != _correctSequence[i]) return false; } return true; } private void ConsumePlayerGem(ItemDataSo item) { if (item == null) return; PlayerManager.RemoveItem(item); } } }