package net.demilich.metastone.game.spells.trigger; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import net.demilich.metastone.game.events.GameEvent; import net.demilich.metastone.game.events.GameEventType; import net.demilich.metastone.game.spells.aura.Aura; import net.demilich.metastone.game.targeting.EntityReference; import net.demilich.metastone.utils.IDisposable; public class TriggerManager implements Cloneable, IDisposable { public static Logger logger = LoggerFactory.getLogger(TriggerManager.class); private final List<IGameEventListener> triggers = new ArrayList<IGameEventListener>(); public TriggerManager() { } private TriggerManager(TriggerManager otherTriggerManager) { for (IGameEventListener gameEventListener : otherTriggerManager.triggers) { triggers.add(gameEventListener.clone()); } } public void addTrigger(IGameEventListener trigger) { triggers.add(trigger); if (triggers.size() > 100) { logger.warn("Warning, many triggers: " + triggers.size() + " adding one of type: " + trigger); } } @Override public TriggerManager clone() { return new TriggerManager(this); } @Override public void dispose() { triggers.clear(); } public void fireGameEvent(GameEvent event) { List<IGameEventListener> eventTriggers = new ArrayList<IGameEventListener>(); List<IGameEventListener> removeTriggers = new ArrayList<IGameEventListener>(); for (IGameEventListener trigger : triggers) { // In order to stop premature expiration, check // for a oneTurnOnly tag and that it isn't delayed. if (event.getEventType() == GameEventType.TURN_END) { if(trigger.oneTurnOnly() && !trigger.isDelayed() && !trigger.interestedIn(GameEventType.TURN_START) && !trigger.interestedIn(GameEventType.TURN_END)) { trigger.expire(); } trigger.delayTimeDown(); } if (trigger.isExpired()) { removeTriggers.add(trigger); } if (!trigger.interestedIn(event.getEventType())) { continue; } if (triggers.contains(trigger) && trigger.canFire(event)) { eventTriggers.add(trigger); } } for (IGameEventListener trigger : eventTriggers) { if (trigger.canFireCondition(event) && triggers.contains(trigger)) { trigger.countDown(); if (!trigger.hasCounter()) { trigger.onGameEvent(event); } } // we need to double check here if the trigger still exists; // after all, a previous trigger may have removed it (i.e. double // corruption) if (trigger.isExpired()) { removeTriggers.add(trigger); } } for (IGameEventListener trigger : removeTriggers) { triggers.remove(trigger); } } private List<IGameEventListener> getListSnapshot(List<IGameEventListener> triggerList) { return new ArrayList<IGameEventListener>(triggerList); } public List<IGameEventListener> getTriggersAssociatedWith(EntityReference entityReference) { List<IGameEventListener> relevantTriggers = new ArrayList<>(); for (IGameEventListener trigger : triggers) { if (trigger.getHostReference().equals(entityReference)) { relevantTriggers.add(trigger); } } return relevantTriggers; } public void printCurrentTriggers() { for (IGameEventListener trigger : triggers) { System.out.println(); System.out.println(trigger.toString()); System.out.println(); } } public void removeTrigger(IGameEventListener trigger) { if (!triggers.remove(trigger)) { System.out.println("Failed to remove trigger " + trigger); } } public void removeTriggersAssociatedWith(EntityReference entityReference, boolean removeAuras) { for (IGameEventListener trigger : getListSnapshot(triggers)) { if (trigger.getHostReference().equals(entityReference)) { if (!removeAuras && trigger instanceof Aura) { continue; } triggers.remove(trigger); } } } }