Added syncPoint between a moment when Game thread adds input to stack and EDT->showMessage, to ensure Game thread's changes happen-before whatever EDT will read

input/InputAttack.java is initialized with combat instead of game (cosmtic change though)
CMatchUI stopAtPhase will use an existing method to get the needed checkBox
This commit is contained in:
Maxmtg
2013-05-29 18:41:04 +00:00
parent f939aa13a5
commit 0a33b93903
5 changed files with 29 additions and 35 deletions

View File

@@ -88,11 +88,19 @@ public class InputQueue extends MyObservable implements java.io.Serializable {
public void setInputAndWait(InputSynchronized input) { public void setInputAndWait(InputSynchronized input) {
this.inputStack.push(input); this.inputStack.push(input);
syncPoint();
this.updateObservers(); this.updateObservers();
input.awaitLatchRelease(); input.awaitLatchRelease();
} }
public void syncPoint() {
synchronized (inputLock) {
// acquire and release lock, so that actions from Game thread happen before EDT reads their results
}
}
/** /**
* TODO: Write javadoc for this method. * TODO: Write javadoc for this method.
*/ */

View File

@@ -493,7 +493,7 @@ public class PlayerControllerHuman extends PlayerController {
case COMBAT_DECLARE_ATTACKERS: case COMBAT_DECLARE_ATTACKERS:
game.getCombat().initiatePossibleDefenders(player.getOpponents()); game.getCombat().initiatePossibleDefenders(player.getOpponents());
InputSynchronized inpAttack = new InputAttack(player); InputSynchronized inpAttack = new InputAttack(player, game.getCombat());
Singletons.getControl().getInputQueue().setInputAndWait(inpAttack); Singletons.getControl().getInputQueue().setInputAndWait(inpAttack);
return; return;

View File

@@ -62,6 +62,7 @@ public class InputProxy implements Observer {
Runnable showMessage = new Runnable() { Runnable showMessage = new Runnable() {
@Override public void run() { @Override public void run() {
Input current = getInput(); Input current = getInput();
Singletons.getControl().getInputQueue().syncPoint();
//System.out.printf("\t%s > showMessage @ %s/%s during %s%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), current.getClass().getSimpleName(), game.getPhaseHandler().debugPrintState()); //System.out.printf("\t%s > showMessage @ %s/%s during %s%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), current.getClass().getSimpleName(), game.getPhaseHandler().debugPrintState());
current.showMessageInitial(); current.showMessageInitial();
} }

View File

@@ -26,10 +26,9 @@ import com.google.common.collect.Iterables;
import forge.Card; import forge.Card;
import forge.CardPredicates; import forge.CardPredicates;
import forge.GameEntity; import forge.GameEntity;
import forge.game.Game; import forge.game.phase.Combat;
import forge.game.phase.CombatUtil; import forge.game.phase.CombatUtil;
import forge.game.player.Player; import forge.game.player.Player;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType; import forge.game.zone.ZoneType;
import forge.util.MyObservable; import forge.util.MyObservable;
import forge.view.ButtonUtil; import forge.view.ButtonUtil;
@@ -47,14 +46,15 @@ public class InputAttack extends InputSyncronizedBase {
private static final long serialVersionUID = 7849903731842214245L; private static final long serialVersionUID = 7849903731842214245L;
private final Game game; private final Combat combat;
private List<GameEntity> defenders; private final List<GameEntity> defenders;
private GameEntity currentDefender; private GameEntity currentDefender;
private final Player player; private final Player player;
public InputAttack(Player human) { public InputAttack(Player human, Combat combat) {
player = human; this.player = human;
game = human.getGame(); this.combat = combat;
this.defenders = combat.getDefenders();
} }
@@ -64,7 +64,7 @@ public class InputAttack extends InputSyncronizedBase {
// TODO still seems to have some issues with multiple planeswalkers // TODO still seems to have some issues with multiple planeswalkers
ButtonUtil.enableOnlyOk(); ButtonUtil.enableOnlyOk();
defenders = game.getCombat().getDefenders();
setCurrentDefender(defenders.isEmpty() ? null : defenders.get(0)); setCurrentDefender(defenders.isEmpty() ? null : defenders.get(0));
if ( null == currentDefender ) { if ( null == currentDefender ) {
@@ -78,8 +78,8 @@ public class InputAttack extends InputSyncronizedBase {
continue; // do not force continue; // do not force
for(GameEntity def : defenders ) { for(GameEntity def : defenders ) {
if( CombatUtil.canAttack(c, def, game.getCombat()) ) { if( CombatUtil.canAttack(c, def, combat) ) {
game.getCombat().addAttacker(c, currentDefender); combat.addAttacker(c, currentDefender);
break; break;
} }
} }
@@ -110,9 +110,9 @@ public class InputAttack extends InputSyncronizedBase {
/** {@inheritDoc} */ /** {@inheritDoc} */
@Override @Override
protected final void onCardSelected(final Card card, boolean isMetaDown) { protected final void onCardSelected(final Card card, boolean isMetaDown) {
final List<Card> att = game.getCombat().getAttackers(); final List<Card> att = combat.getAttackers();
if (isMetaDown && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")) { if (isMetaDown && att.contains(card) && !card.hasKeyword("CARDNAME attacks each turn if able.")) {
game.getCombat().removeFromCombat(card); combat.removeFromCombat(card);
showCombat(); showCombat();
return; return;
} }
@@ -128,12 +128,11 @@ public class InputAttack extends InputSyncronizedBase {
} }
} }
Zone zone = game.getZoneOf(card); if (player.getZone(ZoneType.Battlefield).contains(card) && CombatUtil.canAttack(card, currentDefender, combat)) {
if (zone.is(ZoneType.Battlefield, player) && CombatUtil.canAttack(card, currentDefender, game.getCombat())) { if( combat.isAttacking(card)) {
if( game.getCombat().isAttacking(card)) { combat.removeFromCombat(card);
game.getCombat().removeFromCombat(card);
} }
game.getCombat().addAttacker(card, currentDefender); combat.addAttacker(card, currentDefender);
showCombat(); showCombat();
} }
else { else {

View File

@@ -42,6 +42,7 @@ import forge.gui.match.controllers.CMessage;
import forge.gui.match.controllers.CPicture; import forge.gui.match.controllers.CPicture;
import forge.gui.match.nonsingleton.VCommand; import forge.gui.match.nonsingleton.VCommand;
import forge.gui.match.nonsingleton.VField; import forge.gui.match.nonsingleton.VField;
import forge.gui.match.nonsingleton.VField.PhaseLabel;
import forge.gui.match.nonsingleton.VHand; import forge.gui.match.nonsingleton.VHand;
import forge.gui.match.views.VPlayers; import forge.gui.match.views.VPlayers;
import forge.gui.toolbox.FSkin; import forge.gui.toolbox.FSkin;
@@ -233,23 +234,8 @@ public enum CMatchUI {
*/ */
public final boolean stopAtPhase(final Player turn, final PhaseType phase) { public final boolean stopAtPhase(final Player turn, final PhaseType phase) {
VField vf = getFieldViewFor(turn); VField vf = getFieldViewFor(turn);
PhaseLabel label = vf.getLabelFor(phase);
switch (phase) { return label == null || label.isTurnedOn();
case UPKEEP: return vf.getLblUpkeep().getEnabled();
case DRAW: return vf.getLblDraw().getEnabled();
case MAIN1: return vf.getLblMain1().getEnabled();
case COMBAT_BEGIN: return vf.getLblBeginCombat().getEnabled();
case COMBAT_DECLARE_ATTACKERS: return vf.getLblDeclareAttackers().getEnabled();
case COMBAT_DECLARE_BLOCKERS: return vf.getLblDeclareBlockers().getEnabled();
case COMBAT_FIRST_STRIKE_DAMAGE: return vf.getLblFirstStrike().getEnabled();
case COMBAT_DAMAGE: return vf.getLblCombatDamage().getEnabled();
case COMBAT_END: return vf.getLblEndCombat().getEnabled();
case MAIN2: return vf.getLblMain2().getEnabled();
case END_OF_TURN: return vf.getLblEndTurn().getEnabled();
default:
}
return true;
} }
public void setCard(final Card c) { public void setCard(final Card c) {