using BriarQueen.Data.Identifiers; using BriarQueen.Framework.Coordinators.Events; using BriarQueen.Framework.Events.Save; using BriarQueen.Framework.Events.UI; using BriarQueen.Framework.Managers.Input; using BriarQueen.Framework.Managers.IO; using BriarQueen.Framework.Services.Settings; using System.Text.RegularExpressions; using UnityEngine.InputSystem; using VContainer; namespace BriarQueen.Framework.Services.Tutorials { public class TutorialService { private readonly EventCoordinator _eventCoordinator; private readonly SettingsService _settingsService; private readonly SaveManager _saveManager; private readonly InputManager _inputManager; [Inject] public TutorialService( EventCoordinator eventCoordinator, SettingsService settingsService, SaveManager saveManager, InputManager inputManager) { _eventCoordinator = eventCoordinator; _settingsService = settingsService; _saveManager = saveManager; _inputManager = inputManager; } public void DisplayTutorial(TutorialPopupID tutorialPopupID) { var save = _saveManager.CurrentSave; var tutorialVars = save?.PersistentVariables?.TutorialPopupVariables; if (tutorialVars == null) return; if (tutorialVars.HasBeenDisplayed(tutorialPopupID)) return; tutorialVars.MarkDisplayed(tutorialPopupID); if (_settingsService.AreTutorialsEnabled()) { var resolvedText = ResolveText(tutorialPopupID); _eventCoordinator.Publish(new DisplayTutorialPopupEvent(tutorialPopupID, resolvedText)); } _eventCoordinator.PublishImmediate(new RequestGameSaveEvent()); } // ── Text resolution ─────────────────────────────────────────── /// /// Resolves {ActionName} tokens in the tutorial text for the given ID /// to the current binding display string for that action. /// Hotswap-safe — reads the current control scheme at call time. /// public string ResolveText(TutorialPopupID id) { if (!TutorialPopupTexts.TryGet(id, out var template)) return string.Empty; return ResolveText(template); } /// /// Resolves {ActionName} tokens in an arbitrary string to the current /// binding display string for that action. /// public string ResolveText(string template) { if (string.IsNullOrWhiteSpace(template)) return template; return Regex.Replace(template, @"\{(\w+)\}", match => { var actionName = match.Groups[1].Value; var binding = GetBindingDisplayString(actionName); return string.IsNullOrWhiteSpace(binding) ? match.Value : binding; }); } /// /// Returns the display string for a named action's current binding, /// matched to the active control scheme. /// public string GetBindingDisplayString(string actionName) { if (_inputManager == null) return string.Empty; var action = _inputManager.GetAction(actionName); if (action == null) return string.Empty; var displayString = action.GetBindingDisplayString(group: _inputManager.CurrentControlScheme); return string.IsNullOrWhiteSpace(displayString) ? string.Empty : displayString; } } }