package mage.game.turn; import mage.abilities.Ability; import mage.constants.PhaseStep; import mage.constants.TurnPhase; import mage.game.Game; import mage.util.CardUtil; import mage.util.Copyable; import java.io.Serializable; import java.util.UUID; /** * Creates a signle turn modification for turn, phase or step *

* For one time usage only * For current turn only *

* If you need it in continuous effect then use ContinuousRuleModifyingEffectImpl * with game events like UNTAP_STEP (example: Sands of Time) *

* Supports: * - new turn controller * - turn: extra and skip * - phase: extra and skip * - step: extra and skip * * @author JayDi85 */ public class TurnMod implements Serializable, Copyable { private final UUID id; private final UUID playerId; private UUID newControllerId; private boolean extraTurn; private boolean skipTurn; private TurnPhase extraPhase; private TurnPhase skipPhase; private Step extraStep; private PhaseStep skipStep; private PhaseStep skipAllButExtraStep; // for extra phase skipping all but a specific step. private TurnPhase afterPhase; private PhaseStep afterStep; private boolean locked = false; // locked for modification, used for wrong code usage protection private String tag; // for inner usage like enable/disable mod in effects private String info; // for GUI usage like additional info in logs // Turn mod that should be applied after current turn mod // Implemented only for new controller turn mod private TurnMod subsequentTurnMod; private TurnMod(final TurnMod mod) { this.id = mod.id; this.playerId = mod.playerId; this.newControllerId = mod.newControllerId; this.extraTurn = mod.extraTurn; this.skipTurn = mod.skipTurn; this.extraPhase = mod.extraPhase; this.skipPhase = mod.skipPhase; if (mod.extraStep != null) { this.extraStep = mod.extraStep.copy(); } this.skipStep = mod.skipStep; this.skipAllButExtraStep = mod.skipAllButExtraStep; this.afterPhase = mod.afterPhase; this.afterStep = mod.afterStep; if (mod.subsequentTurnMod != null) { this.subsequentTurnMod = mod.subsequentTurnMod.copy(); } this.tag = mod.tag; this.info = mod.info; this.locked = mod.locked; } public TurnMod copy() { return new TurnMod(this); } public TurnMod(UUID playerId) { // TODO: delete this.id = UUID.randomUUID(); this.playerId = playerId; } private void lock() { if (this.locked) { throw new IllegalStateException("Wrong code usage: you must use only one type of turn modification"); } this.locked = true; } public TurnMod withSkipTurn() { this.skipTurn = true; lock(); return this; } public TurnMod withExtraTurn() { this.extraTurn = true; lock(); return this; } public TurnMod withNewController(UUID newControllerId) { return withNewController(newControllerId, null); } public TurnMod withNewController(UUID newControllerId, TurnMod nextSubsequentTurnMod) { this.newControllerId = newControllerId; this.subsequentTurnMod = nextSubsequentTurnMod; lock(); return this; } public TurnMod withSkipPhase(TurnPhase skipPhase) { this.skipPhase = skipPhase; lock(); return this; } public TurnMod withExtraPhase(TurnPhase extraPhase) { return withExtraPhase(extraPhase, null); } /** * Adds an extra step in a new extra phase after this one. * All steps that are not the right one are skipped in the extra phase. * e.g. [[Obeka, Splitter of Seconds]] */ public TurnMod withExtraStepInExtraPhase(PhaseStep extraStep, TurnPhase extraPhase) { this.extraPhase = extraPhase; this.skipAllButExtraStep = extraStep; lock(); return this; } public TurnMod withExtraPhase(TurnPhase extraPhase, TurnPhase addAfterPhase) { this.extraPhase = extraPhase; this.afterPhase = addAfterPhase; lock(); return this; } public TurnMod withSkipStep(PhaseStep skipStep) { this.skipStep = skipStep; lock(); return this; } public TurnMod withExtraStep(Step extraStep) { return withExtraStep(extraStep, null); } public TurnMod withExtraStep(Step extraStep, PhaseStep addAfterStep) { this.extraStep = extraStep; this.afterStep = addAfterStep; lock(); return this; } public TurnMod withTag(String tag) { this.tag = tag; return this; } public String getTag() { return tag; } public TurnMod withInfo(String info) { this.info = info; return this; } public String getInfo() { return info == null ? "" : info; } public UUID getPlayerId() { return playerId; } public boolean isExtraTurn() { return extraTurn; } public boolean isSkipTurn() { return skipTurn; } public TurnPhase getExtraPhase() { return extraPhase; } public Step getExtraStep() { return extraStep; } public TurnPhase getSkipPhase() { return skipPhase; } public PhaseStep getSkipAllButExtraStep() { return skipAllButExtraStep; } public PhaseStep getSkipStep() { return skipStep; } public TurnPhase getAfterPhase() { return afterPhase; } public PhaseStep getAfterStep() { return afterStep; } public UUID getNewControllerId() { return newControllerId; } public UUID getId() { return id; } public TurnMod getSubsequentTurnMod() { return subsequentTurnMod; } public boolean isLocked() { return locked; } private void addSourceAsInfo(Game game, Ability source) { this.info = CardUtil.getSourceLogName(game, source); } }