using OECS; namespace Game.CardWars; /// /// A card effect that can be registered with the effect dispatcher. /// public interface ICardEffect { CardEffect Effect { get; } /// /// Called when the card is played face-up or flipped face-up. /// Return true if fully resolved. Return false if a pending component /// was set and the effect needs a player command to continue. /// bool Resolve(World world, Entity card, Entity player, Entity owner); /// /// Called when the player provides a choice to continue a pending effect. /// The effect handler is responsible for reading the correct pending /// component type from the singleton and removing it when done. /// bool ResolveChoice(World world, Entity target); } /// /// Registry of card effects, ordered by registration. /// public static class CardEffectRegistry { private static readonly List _effects = new(); private static bool _frozen; public static void Add() where TEffect : ICardEffect, new() { if (_frozen) throw new InvalidOperationException("Cannot add effects after the registry is frozen."); _effects.Add(new TEffect()); } public static void Freeze() => _frozen = true; /// /// Resolve a card effect. Returns true if fully resolved. /// public static bool Dispatch(World world, CardEffect effect, Entity card, Entity player, Entity owner) { foreach (var e in _effects) { if (e.Effect == effect) return e.Resolve(world, card, player, owner); } return true; } /// /// Look up the handler for the currently pending effect and resolve it. /// public static bool DispatchChoice(World world, Entity target) { // Find which pending component is active and dispatch to the matching handler. if (world.HasSingleton()) return DispatchByEffect(world, CardEffect.Mercenary, target); if (world.HasSingleton()) return DispatchByEffect(world, CardEffect.Dancer, target); if (world.HasSingleton()) return DispatchByEffect(world, CardEffect.Paladin, target); if (world.HasSingleton()) return DispatchByEffect(world, CardEffect.Nun, target); if (world.HasSingleton()) return DispatchByEffect(world, CardEffect.Scout, target); if (world.HasSingleton()) return DispatchByEffect(world, CardEffect.Pegasus, target); if (world.HasSingleton()) return DispatchByEffect(world, CardEffect.CurseMaster, target); return true; } private static bool DispatchByEffect(World world, CardEffect effect, Entity target) { foreach (var e in _effects) { if (e.Effect == effect) return e.ResolveChoice(world, target); } return true; } public static void ClearForTests() { _effects.Clear(); _frozen = false; } }