CStack updates are also driven by events. CStack no longer observable

This commit is contained in:
Maxmtg
2013-06-01 23:58:25 +00:00
parent f137ac390f
commit 84a9732541
10 changed files with 90 additions and 71 deletions

1
.gitattributes vendored
View File

@@ -14259,6 +14259,7 @@ src/main/java/forge/game/event/GameEventPlayerPoisoned.java -text
src/main/java/forge/game/event/GameEventPlayerPriority.java -text src/main/java/forge/game/event/GameEventPlayerPriority.java -text
src/main/java/forge/game/event/GameEventShuffle.java -text src/main/java/forge/game/event/GameEventShuffle.java -text
src/main/java/forge/game/event/GameEventSpellAbilityCast.java -text src/main/java/forge/game/event/GameEventSpellAbilityCast.java -text
src/main/java/forge/game/event/GameEventSpellRemovedFromStack.java -text
src/main/java/forge/game/event/GameEventSpellResolved.java -text src/main/java/forge/game/event/GameEventSpellResolved.java -text
src/main/java/forge/game/event/GameEventTokenCreated.java -text src/main/java/forge/game/event/GameEventTokenCreated.java -text
src/main/java/forge/game/event/GameEventTurnBegan.java -text src/main/java/forge/game/event/GameEventTurnBegan.java -text

View File

@@ -3918,8 +3918,8 @@ public class Card extends GameEntity implements Comparable<Card> {
* @param n * @param n
* a int. * a int.
*/ */
public final void setReplicateMagnitude(final int n) { public final void resetReplicateMagnitude() {
this.replicateMagnitude = n; this.replicateMagnitude = 0;
} }
/** /**

View File

@@ -41,7 +41,6 @@ public class EndTurnEffect extends SpellAbilityEffect {
game.getPhaseHandler().endTurnByEffect(); game.getPhaseHandler().endTurnByEffect();
// Update observers // Update observers
game.getStack().updateObservers();
for (Player p : game.getPlayers()) { for (Player p : game.getPlayers()) {
p.updateObservers(); p.updateObservers();
p.updateLabelObservers(); p.updateLabelObservers();

View File

@@ -13,6 +13,9 @@ import forge.game.event.GameEventAnteCardsSelected;
import forge.game.event.GameEventGameFinished; import forge.game.event.GameEventGameFinished;
import forge.game.event.GameEventGameOutcome; import forge.game.event.GameEventGameOutcome;
import forge.game.event.GameEventPlayerControl; import forge.game.event.GameEventPlayerControl;
import forge.game.event.GameEventSpellAbilityCast;
import forge.game.event.GameEventSpellRemovedFromStack;
import forge.game.event.GameEventSpellResolved;
import forge.game.event.GameEventTurnBegan; import forge.game.event.GameEventTurnBegan;
import forge.game.event.GameEventTurnPhase; import forge.game.event.GameEventTurnPhase;
import forge.game.event.IGameEventVisitor; import forge.game.event.IGameEventVisitor;
@@ -24,6 +27,7 @@ import forge.gui.match.CMatchUI;
import forge.gui.match.VMatchUI; import forge.gui.match.VMatchUI;
import forge.gui.match.ViewWinLose; import forge.gui.match.ViewWinLose;
import forge.gui.match.controllers.CMessage; import forge.gui.match.controllers.CMessage;
import forge.gui.match.controllers.CStack;
import forge.gui.match.nonsingleton.VHand; import forge.gui.match.nonsingleton.VHand;
import forge.gui.match.nonsingleton.VField.PhaseLabel; import forge.gui.match.nonsingleton.VField.PhaseLabel;
@@ -113,4 +117,30 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
} }); } });
return null; return null;
} }
private final AtomicBoolean stackUpdPlanned = new AtomicBoolean(false);
private final Runnable updStack = new Runnable() { @Override public void run() {
stackUpdPlanned.set(false);
CStack.SINGLETON_INSTANCE.update();
}
};
@Override
public Void visit(GameEventSpellAbilityCast event) {
if ( !stackUpdPlanned.getAndSet(true) )
FThreads.invokeInEdtNowOrLater(updStack);
return null;
}
@Override
public Void visit(GameEventSpellResolved event) {
if ( !stackUpdPlanned.getAndSet(true) )
FThreads.invokeInEdtNowOrLater(updStack);
return null;
}
@Override
public Void visit(GameEventSpellRemovedFromStack event) {
if ( !stackUpdPlanned.getAndSet(true) )
FThreads.invokeInEdtNowOrLater(updStack);
return null;
}
} }

View File

@@ -74,7 +74,7 @@ import forge.util.TextUtil;
*/ */
public final class GameActionUtil { public final class GameActionUtil {
private static final class CascadeAbility extends Ability { public static final class CascadeAbility extends Ability {
private final Player controller; private final Player controller;
private final Card cascCard; private final Card cascCard;
@@ -132,7 +132,7 @@ public final class GameActionUtil {
} }
} }
private static final class CascadeExecutor implements Command { public static final class CascadeExecutor implements Command {
private final Card c; private final Card c;
private final Game game; private final Game game;
private final Player controller; private final Player controller;
@@ -144,7 +144,7 @@ public final class GameActionUtil {
* @param controller * @param controller
* @param c * @param c
*/ */
private CascadeExecutor(Player controller, Card c, final Game game) { public CascadeExecutor(Player controller, Card c, final Game game) {
this.controller = controller; this.controller = controller;
this.c = c; this.c = c;
this.game = game; this.game = game;
@@ -187,7 +187,7 @@ public final class GameActionUtil {
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
* *
*/ */
private static final class RippleAbility extends Ability { public static final class RippleAbility extends Ability {
private final Player controller; private final Player controller;
private final int rippleCount; private final int rippleCount;
private final Card rippleCard; private final Card rippleCard;
@@ -263,7 +263,7 @@ public final class GameActionUtil {
* TODO: Write javadoc for this type. * TODO: Write javadoc for this type.
* *
*/ */
private static final class RippleExecutor implements Command { public static final class RippleExecutor implements Command {
private final Player controller; private final Player controller;
private final Card c; private final Card c;
private static final long serialVersionUID = -845154812215847505L; private static final long serialVersionUID = -845154812215847505L;
@@ -273,7 +273,7 @@ public final class GameActionUtil {
* @param controller * @param controller
* @param c * @param c
*/ */
private RippleExecutor(Player controller, Card c) { public RippleExecutor(Player controller, Card c) {
this.controller = controller; this.controller = controller;
this.c = c; this.c = c;
} }
@@ -316,24 +316,6 @@ public final class GameActionUtil {
throw new AssertionError(); throw new AssertionError();
} }
/**
* <p>
* executePlayCardEffects.
* </p>
*
* @param sa
* a {@link forge.card.spellability.SpellAbility} object.
*/
public static void executePlayCardEffects(final SpellAbility sa) {
// (called from MagicStack.java)
final Game game = sa.getActivatingPlayer().getGame();
final Command cascade = new CascadeExecutor(sa.getActivatingPlayer(), sa.getSourceCard(), game);
cascade.run();
final Command ripple = new RippleExecutor(sa.getActivatingPlayer(), sa.getSourceCard());
ripple.run();
}
// this is for cards like Sengir Vampire // this is for cards like Sengir Vampire
/** /**
* <p> * <p>

View File

@@ -9,9 +9,11 @@ import forge.card.spellability.SpellAbility;
public class GameEventSpellAbilityCast extends GameEvent { public class GameEventSpellAbilityCast extends GameEvent {
public final SpellAbility sa; public final SpellAbility sa;
public final boolean replicate;
public GameEventSpellAbilityCast(SpellAbility sp) { public GameEventSpellAbilityCast(SpellAbility sp, boolean replicate) {
sa = sp; sa = sp;
this.replicate = replicate;
} }
/* (non-Javadoc) /* (non-Javadoc)

View File

@@ -0,0 +1,22 @@
package forge.game.event;
import forge.card.spellability.SpellAbility;
/**
* TODO: Write javadoc for this type.
*
*/
public class GameEventSpellRemovedFromStack extends GameEvent {
public final SpellAbility sa;
public GameEventSpellRemovedFromStack(SpellAbility spellAbility) {
sa = spellAbility;
}
@Override
public <T> T visit(IGameEventVisitor<T> visitor) {
// TODO Auto-generated method stub
return visitor.visit(this);
}
}

View File

@@ -33,6 +33,7 @@ public interface IGameEventVisitor<T> {
T visit(GameEventShuffle event); T visit(GameEventShuffle event);
T visit(GameEventSpellAbilityCast gameEventSpellAbilityCast); T visit(GameEventSpellAbilityCast gameEventSpellAbilityCast);
T visit(GameEventSpellResolved event); T visit(GameEventSpellResolved event);
T visit(GameEventSpellRemovedFromStack event);
T visit(GameEventTokenCreated event); T visit(GameEventTokenCreated event);
T visit(GameEventTurnBegan gameEventTurnBegan); T visit(GameEventTurnBegan gameEventTurnBegan);
T visit(GameEventTurnEnded event); T visit(GameEventTurnEnded event);
@@ -68,6 +69,7 @@ public interface IGameEventVisitor<T> {
public T visit(GameEventShuffle event) { return null; } public T visit(GameEventShuffle event) { return null; }
public T visit(GameEventSpellResolved event) { return null; } public T visit(GameEventSpellResolved event) { return null; }
public T visit(GameEventSpellAbilityCast event) { return null; } public T visit(GameEventSpellAbilityCast event) { return null; }
public T visit(GameEventSpellRemovedFromStack event) { return null; }
public T visit(GameEventTokenCreated event) { return null; } public T visit(GameEventTokenCreated event) { return null; }
public T visit(GameEventTurnBegan event) { return null; } public T visit(GameEventTurnBegan event) { return null; }
public T visit(GameEventTurnEnded event) { return null; } public T visit(GameEventTurnEnded event) { return null; }

View File

@@ -31,6 +31,7 @@ import com.esotericsoftware.minlog.Log;
import forge.Card; import forge.Card;
import forge.CardLists; import forge.CardLists;
import forge.Command;
import forge.FThreads; import forge.FThreads;
import forge.Singletons; import forge.Singletons;
import forge.CardPredicates.Presets; import forge.CardPredicates.Presets;
@@ -51,11 +52,13 @@ import forge.card.spellability.Target;
import forge.card.spellability.TargetChoices; import forge.card.spellability.TargetChoices;
import forge.card.trigger.Trigger; import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerType; import forge.card.trigger.TriggerType;
import forge.game.GameActionUtil;
import forge.game.Game; import forge.game.Game;
import forge.game.GameActionUtil.CascadeExecutor;
import forge.game.GameActionUtil.RippleExecutor;
import forge.game.ai.ComputerUtil; import forge.game.ai.ComputerUtil;
import forge.game.ai.ComputerUtilCard; import forge.game.ai.ComputerUtilCard;
import forge.game.event.GameEventSpellAbilityCast; import forge.game.event.GameEventSpellAbilityCast;
import forge.game.event.GameEventSpellRemovedFromStack;
import forge.game.event.GameEventSpellResolved; import forge.game.event.GameEventSpellResolved;
import forge.game.player.HumanPlay; import forge.game.player.HumanPlay;
import forge.game.player.Player; import forge.game.player.Player;
@@ -63,7 +66,6 @@ import forge.game.player.PlayerController.ManaPaymentPurpose;
import forge.gui.GuiChoose; import forge.gui.GuiChoose;
import forge.gui.input.InputSelectCards; import forge.gui.input.InputSelectCards;
import forge.gui.input.InputSelectCardsFromList; import forge.gui.input.InputSelectCardsFromList;
import forge.util.MyObservable;
/** /**
* <p> * <p>
@@ -73,7 +75,7 @@ import forge.util.MyObservable;
* @author Forge * @author Forge
* @version $Id$ * @version $Id$
*/ */
public class MagicStack extends MyObservable implements Iterable<SpellAbilityStackInstance> { public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbilityStackInstance> {
private final List<SpellAbility> simultaneousStackEntryList = new ArrayList<SpellAbility>(); private final List<SpellAbility> simultaneousStackEntryList = new ArrayList<SpellAbility>();
// They don't provide a LIFO queue, so had to use a deque // They don't provide a LIFO queue, so had to use a deque
@@ -133,7 +135,6 @@ public class MagicStack extends MyObservable implements Iterable<SpellAbilitySta
this.thisTurnCast.clear(); this.thisTurnCast.clear();
this.curResolvingCard = null; this.curResolvingCard = null;
this.frozenStack.clear(); this.frozenStack.clear();
this.updateObservers();
} }
/** /**
@@ -299,7 +300,6 @@ public class MagicStack extends MyObservable implements Iterable<SpellAbilitySta
return; return;
} }
game.fireEvent(new GameEventSpellAbilityCast(sp));
// if activating player slips through the cracks, assign activating // if activating player slips through the cracks, assign activating
// Player to the controller here // Player to the controller here
@@ -341,12 +341,12 @@ public class MagicStack extends MyObservable implements Iterable<SpellAbilitySta
if (sp.isReplicate()) { if (sp.isReplicate()) {
// TODO: convert multikicker/replicate support in abCost so this // TODO: convert multikicker/replicate support in abCost so this
// doesn't happen here // doesn't happen here
// X and multi and replicate are not supported yet
final Player activating = sp.getActivatingPlayer(); final Player activating = sp.getActivatingPlayer();
final Cost costMultikicker = new Cost(sp.getMultiKickerManaCost(), false); final Cost costMultikicker = new Cost(sp.getReplicateManaCost(), false);
sp.getSourceCard().resetReplicateMagnitude();
boolean hasPaid = false; boolean hasPaid = false;
do { do {
int rMagnitude = sp.getSourceCard().getReplicateMagnitude(); int rMagnitude = sp.getSourceCard().getReplicateMagnitude();
String prompt = String.format("Replicate for %s\r\nTimes Replicated: %d\r\n", sp.getSourceCard(), rMagnitude); String prompt = String.format("Replicate for %s\r\nTimes Replicated: %d\r\n", sp.getSourceCard(), rMagnitude);
@@ -464,6 +464,7 @@ public class MagicStack extends MyObservable implements Iterable<SpellAbilitySta
final SpellAbilityStackInstance si = new SpellAbilityStackInstance(sp); final SpellAbilityStackInstance si = new SpellAbilityStackInstance(sp);
this.stack.addFirst(si); this.stack.addFirst(si);
game.fireEvent(new GameEventSpellAbilityCast(sp, false));
// 2012-07-21 the following comparison needs to move below the pushes but somehow screws up priority // 2012-07-21 the following comparison needs to move below the pushes but somehow screws up priority
// When it's down there. That makes absolutely no sense to me, so i'm putting it back for now // When it's down there. That makes absolutely no sense to me, so i'm putting it back for now
@@ -472,12 +473,14 @@ public class MagicStack extends MyObservable implements Iterable<SpellAbilitySta
game.getPhaseHandler().setPriority(sp.getActivatingPlayer()); game.getPhaseHandler().setPriority(sp.getActivatingPlayer());
} }
this.updateObservers();
if (sp.isSpell() && !sp.getSourceCard().isCopiedSpell()) { if (sp.isSpell() && !sp.getSourceCard().isCopiedSpell()) {
this.thisTurnCast.add(sp.getSourceCard()); this.thisTurnCast.add(sp.getSourceCard());
GameActionUtil.executePlayCardEffects(sp); final Game game = sp.getActivatingPlayer().getGame();
final Command cascade = new CascadeExecutor(sp.getActivatingPlayer(), sp.getSourceCard(), game);
cascade.run();
final Command ripple = new RippleExecutor(sp.getActivatingPlayer(), sp.getSourceCard());
ripple.run();
} }
} }
@@ -516,6 +519,7 @@ public class MagicStack extends MyObservable implements Iterable<SpellAbilitySta
sa.resolve(); sa.resolve();
// do creatures ETB from here? // do creatures ETB from here?
} }
this.finishResolving(sa, thisHasFizzled); this.finishResolving(sa, thisHasFizzled);
game.fireEvent(new GameEventSpellResolved(sa, thisHasFizzled)); game.fireEvent(new GameEventSpellResolved(sa, thisHasFizzled));
@@ -579,13 +583,10 @@ public class MagicStack extends MyObservable implements Iterable<SpellAbilitySta
sa.resetOnceResolved(); sa.resetOnceResolved();
game.getAction().checkStateEffects(); game.getAction().checkStateEffects();
game.getPhaseHandler().onStackResolved(); game.getPhaseHandler().onStackResolved();
this.curResolvingCard = null; this.curResolvingCard = null;
this.updateObservers();
// TODO: this is a huge hack. Why is this necessary? // TODO: this is a huge hack. Why is this necessary?
// hostCard in AF is not the same object that's on the battlefield // hostCard in AF is not the same object that's on the battlefield
// verified by System.identityHashCode(card); // verified by System.identityHashCode(card);
@@ -728,7 +729,7 @@ public class MagicStack extends MyObservable implements Iterable<SpellAbilitySta
public final void remove(final SpellAbilityStackInstance si) { public final void remove(final SpellAbilityStackInstance si) {
this.stack.remove(si); this.stack.remove(si);
this.frozenStack.remove(si); this.frozenStack.remove(si);
this.updateObservers(); game.fireEvent(new GameEventSpellRemovedFromStack(si.getSpellAbility()));
} }
public final SpellAbilityStackInstance getInstanceFromSpellAbility(final SpellAbility sa) { public final SpellAbilityStackInstance getInstanceFromSpellAbility(final SpellAbility sa) {
@@ -901,6 +902,7 @@ public class MagicStack extends MyObservable implements Iterable<SpellAbilitySta
*/ */
public void clear() { public void clear() {
stack.clear(); stack.clear();
game.fireEvent(new GameEventSpellRemovedFromStack(null));
} }
@Override @Override

View File

@@ -1,10 +1,6 @@
package forge.gui.match.controllers; package forge.gui.match.controllers;
import java.util.Observable;
import java.util.Observer;
import forge.Command; import forge.Command;
import forge.FThreads;
import forge.game.player.LobbyPlayer; import forge.game.player.LobbyPlayer;
import forge.game.zone.MagicStack; import forge.game.zone.MagicStack;
import forge.gui.framework.EDocID; import forge.gui.framework.EDocID;
@@ -18,7 +14,7 @@ import forge.gui.match.views.VStack;
* <br><br><i>(C at beginning of class name denotes a control class.)</i> * <br><br><i>(C at beginning of class name denotes a control class.)</i>
* *
*/ */
public enum CStack implements ICDoc, Observer { public enum CStack implements ICDoc {
/** */ /** */
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
@@ -40,32 +36,15 @@ public enum CStack implements ICDoc, Observer {
public void initialize() { public void initialize() {
} }
private final Runnable upd = new Runnable() { @Override public void run() {
SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc());
VStack.SINGLETON_INSTANCE.updateStack(model, viewer);
} };
/* (non-Javadoc)
* @see java.util.Observer#update(java.util.Observable, java.lang.Object)
*/
@Override
public void update(final Observable arg0, Object arg1) {
update();
}
/* (non-Javadoc)
* @see forge.gui.framework.ICDoc#update()
*/
@Override @Override
public void update() { public void update() {
FThreads.invokeInEdtNowOrLater(upd); SDisplayUtil.showTab(EDocID.REPORT_STACK.getDoc());
VStack.SINGLETON_INSTANCE.updateStack(model, viewer);
} }
public void setModel(MagicStack model, LobbyPlayer guiPlayer) { public void setModel(MagicStack model, LobbyPlayer guiPlayer) {
this.model = model; this.model = model;
this.viewer = guiPlayer; this.viewer = guiPlayer;
model.addObserver(this);
} }
} }