fixing NPE in CCombat.getCombatDescription. CCombat is given its own copy of combat that cannot be taken away by a different thread.

This commit is contained in:
Maxmtg
2013-06-27 08:39:13 +00:00
parent 67ee42dcda
commit 82bb17ebf9
7 changed files with 20 additions and 19 deletions

View File

@@ -56,7 +56,6 @@ import forge.gui.home.CHomeUI;
import forge.gui.home.VHomeUI; import forge.gui.home.VHomeUI;
import forge.gui.match.CMatchUI; import forge.gui.match.CMatchUI;
import forge.gui.match.VMatchUI; import forge.gui.match.VMatchUI;
import forge.gui.match.controllers.CCombat;
import forge.gui.match.controllers.CDock; import forge.gui.match.controllers.CDock;
import forge.gui.match.controllers.CLog; import forge.gui.match.controllers.CLog;
import forge.gui.match.controllers.CMessage; import forge.gui.match.controllers.CMessage;
@@ -415,7 +414,6 @@ public enum FControl {
CDock.SINGLETON_INSTANCE.setModel(game, humanLobbyPlayer); CDock.SINGLETON_INSTANCE.setModel(game, humanLobbyPlayer);
CStack.SINGLETON_INSTANCE.setModel(game.getStack(), humanLobbyPlayer); CStack.SINGLETON_INSTANCE.setModel(game.getStack(), humanLobbyPlayer);
CLog.SINGLETON_INSTANCE.setModel(game.getGameLog()); CLog.SINGLETON_INSTANCE.setModel(game.getGameLog());
CCombat.SINGLETON_INSTANCE.setModel(game);
CMessage.SINGLETON_INSTANCE.setModel(game); CMessage.SINGLETON_INSTANCE.setModel(game);

View File

@@ -74,7 +74,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
if ( combatUpdPlanned.getAndSet(true) ) return null; if ( combatUpdPlanned.getAndSet(true) ) return null;
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() {
combatUpdPlanned.set(false); combatUpdPlanned.set(false);
CMatchUI.SINGLETON_INSTANCE.showCombat(); CMatchUI.SINGLETON_INSTANCE.showCombat(fc.getObservedGame().getCombat());
} }); } });
return null; return null;
} }

View File

@@ -280,11 +280,11 @@ public class Combat {
} }
/** If there are multiple blockers, the Attacker declares the Assignment Order */ /** If there are multiple blockers, the Attacker declares the Assignment Order */
public void orderBlockersForDamageAssignment() { public void orderBlockersForDamageAssignment() { // this method performs controller's role
for(Collection<AttackingBand> abs : attackedEntities.values()) for(Collection<AttackingBand> abs : attackedEntities.values())
for (final AttackingBand band : abs) { for (final AttackingBand band : abs) {
if (band.isEmpty()) continue; // there should not be empty bands if (band.isEmpty()) continue;
Collection<Card> blockers = blockedBands.get(band); Collection<Card> blockers = blockedBands.get(band);
if ( blockers == null || blockers.isEmpty() ) if ( blockers == null || blockers.isEmpty() )
@@ -300,7 +300,7 @@ public class Combat {
} }
} }
public void orderAttackersForDamageAssignment() { public void orderAttackersForDamageAssignment() { // this method performs controller's role
// If there are multiple blockers, the Attacker declares the Assignment Order // If there are multiple blockers, the Attacker declares the Assignment Order
for (final Card blocker : getAllBlockers()) { for (final Card blocker : getAllBlockers()) {
List<Card> attackers = getAttackersBlockedBy(blocker); List<Card> attackers = getAttackersBlockedBy(blocker);

View File

@@ -93,7 +93,7 @@ public class InputAttack extends InputSyncronizedBase {
private void showCombat() { private void showCombat() {
playerAttacks.getZone(ZoneType.Battlefield).updateObservers(); // redraw sword icons playerAttacks.getZone(ZoneType.Battlefield).updateObservers(); // redraw sword icons
CMatchUI.SINGLETON_INSTANCE.showCombat(); CMatchUI.SINGLETON_INSTANCE.showCombat(combat);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */

View File

@@ -79,7 +79,7 @@ public class InputBlock extends InputSyncronizedBase {
showMessage(sb.toString()); showMessage(sb.toString());
} }
CMatchUI.SINGLETON_INSTANCE.showCombat(); CMatchUI.SINGLETON_INSTANCE.showCombat(combat);
} }
/** {@inheritDoc} */ /** {@inheritDoc} */
@@ -102,7 +102,7 @@ public class InputBlock extends InputSyncronizedBase {
if (isMetaDown && card.getController() == defender) { if (isMetaDown && card.getController() == defender) {
combat.removeFromCombat(card); combat.removeFromCombat(card);
CMatchUI.SINGLETON_INSTANCE.showCombat(); CMatchUI.SINGLETON_INSTANCE.showCombat(combat);
return; return;
} }

View File

@@ -31,6 +31,7 @@ import forge.FThreads;
import forge.GameEntity; import forge.GameEntity;
import forge.ImageCache; import forge.ImageCache;
import forge.Singletons; import forge.Singletons;
import forge.game.combat.Combat;
import forge.game.phase.PhaseType; import forge.game.phase.PhaseType;
import forge.game.player.LobbyPlayer; import forge.game.player.LobbyPlayer;
import forge.game.player.Player; import forge.game.player.Player;
@@ -260,10 +261,11 @@ public enum CMatchUI {
} }
public void showCombat() { public void showCombat(Combat combat) {
if (Singletons.getControl().getObservedGame().getPhaseHandler().inCombat()) { if (combat != null) {
SDisplayUtil.showTab(EDocID.REPORT_COMBAT.getDoc()); SDisplayUtil.showTab(EDocID.REPORT_COMBAT.getDoc());
} }
CCombat.SINGLETON_INSTANCE.setModel(combat);
CCombat.SINGLETON_INSTANCE.update(); CCombat.SINGLETON_INSTANCE.update();
} // showBlockers() } // showBlockers()

View File

@@ -5,10 +5,8 @@ import java.util.List;
import forge.Card; import forge.Card;
import forge.Command; import forge.Command;
import forge.GameEntity; import forge.GameEntity;
import forge.game.Game;
import forge.game.combat.AttackingBand; import forge.game.combat.AttackingBand;
import forge.game.combat.Combat; import forge.game.combat.Combat;
import forge.game.phase.PhaseHandler;
import forge.game.player.Player; import forge.game.player.Player;
import forge.gui.framework.ICDoc; import forge.gui.framework.ICDoc;
import forge.gui.match.views.VCombat; import forge.gui.match.views.VCombat;
@@ -24,7 +22,7 @@ public enum CCombat implements ICDoc {
/** */ /** */
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
private Game game; private Combat combat;
/* (non-Javadoc) /* (non-Javadoc)
* @see forge.gui.framework.ICDoc#getCommandOnSelect() * @see forge.gui.framework.ICDoc#getCommandOnSelect()
@@ -46,16 +44,16 @@ public enum CCombat implements ICDoc {
*/ */
@Override @Override
public void update() { public void update() {
PhaseHandler pH = game.getPhaseHandler(); Combat localCombat = this.combat; // noone will re-assign this from other thread.
if (pH.inCombat()) // display combat if (localCombat != null )
VCombat.SINGLETON_INSTANCE.updateCombat(pH.getCombat().getAttackers().size(), getCombatDescription(pH.getCombat())); VCombat.SINGLETON_INSTANCE.updateCombat(localCombat.getAttackers().size(), getCombatDescription(localCombat));
else else
VCombat.SINGLETON_INSTANCE.updateCombat(0, ""); VCombat.SINGLETON_INSTANCE.updateCombat(0, "");
} }
public void setModel(Game game) public void setModel(Combat combat)
{ {
this.game = game; this.combat = combat;
} }
@@ -83,6 +81,9 @@ public enum CCombat implements ICDoc {
// Associate Bands, Attackers Blockers // Associate Bands, Attackers Blockers
boolean previousBand = false; boolean previousBand = false;
for(AttackingBand band : bands) { for(AttackingBand band : bands) {
if (band.isEmpty())
continue;
// Space out band blocks from non-band blocks // Space out band blocks from non-band blocks
if (previousBand) { if (previousBand) {
display.append("\n"); display.append("\n");