using System.Collections.Generic; using Cthangover.Core.Characters; namespace Cthangover.Core.Battle.Actions { /// /// Central action-execution dispatcher. Resolves an action ID to an /// IActionExecutor in two tiers: first the active provider (set by /// the current IBattleCore, allowing per-battle-engine overrides), /// then a global fallback registry. This two-level lookup lets mods /// supply custom executors for specific battle cores without replacing /// the global ones. Execute returns ChangedAttributes to allow the /// caller to inspect the result (success/failure, stat deltas). /// public class ActionExecutorHub { /// /// Singleton hub instance. There is one global dispatcher shared /// across all battle cores; cores swap providers via /// when they activate. /// public static readonly ActionExecutorHub Instance = new(); private IActionExecutorProvider _activeProvider; private readonly Dictionary _globalExecutors = new(); /// /// Installs a per-core executor provider. The active provider is /// consulted before the global registry, allowing the current /// battle core to override specific action handlers. /// public void SetActiveProvider(IActionExecutorProvider provider) { _activeProvider = provider; } /// /// Registers a fallback executor in the global pool, keyed by /// . Global executors are /// used when no active provider supplies a match. /// public void RegisterGlobal(IActionExecutor executor) { if (executor != null && !string.IsNullOrEmpty(executor.ActionId)) _globalExecutors[executor.ActionId] = executor; } /// /// Dispatches an action to the appropriate executor. Resolution /// order: active provider first, then global registry. Returns /// Result = false if no executor is found or if /// is null. /// public ChangedAttributes Execute(ActionCharacter action, Character user, Character target) { if (action == null) return new ChangedAttributes { Result = false }; var executor = Resolve(action.ID); if (executor == null) return new ChangedAttributes { Result = false }; return executor.Execute(action, user, target); } private IActionExecutor Resolve(string actionId) { if (_activeProvider != null) { var executor = _activeProvider.GetExecutor(actionId); if (executor != null) return executor; } _globalExecutors.TryGetValue(actionId, out var fallback); return fallback; } } }