Use caching for CombatView (plus some random NPE and concurrency fixes).

This commit is contained in:
elcnesh
2014-09-26 07:38:47 +00:00
parent 3c411f3a3c
commit 3f1f199537
18 changed files with 119 additions and 44 deletions

View File

@@ -440,7 +440,7 @@ public class Game implements IGameStateObject {
return card.getZone();
}
public List<Card> getCardsIn(final ZoneType zone) {
public synchronized List<Card> getCardsIn(final ZoneType zone) {
if (zone == ZoneType.Stack) {
return getStackZone().getCards();
}

View File

@@ -4,9 +4,11 @@ import forge.game.Game;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardFactoryUtil;
import forge.game.event.GameEventCombatChanged;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
import forge.game.trigger.TriggerType;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
@@ -29,13 +31,14 @@ public class BecomesBlockedEffect extends SpellAbilityEffect {
@Override
public void resolve(SpellAbility sa) {
boolean isCombatChanged = false;
final Game game = sa.getActivatingPlayer().getGame();
final TargetRestrictions tgt = sa.getTargetRestrictions();
for (final Card c : getTargetCards(sa)) {
if ((tgt == null) || c.canBeTargetedBy(sa)) {
game.getCombat().setBlocked(c, true);
if (!c.getDamageHistory().getCreatureGotBlockedThisCombat()) {
isCombatChanged = true;
final HashMap<String, Object> runParams = new HashMap<String, Object>();
runParams.put("Attacker", c);
runParams.put("Blockers", new ArrayList<Card>());
@@ -50,5 +53,8 @@ public class BecomesBlockedEffect extends SpellAbilityEffect {
}
}
if (isCombatChanged) {
game.fireEvent(new GameEventCombatChanged());
}
}
}

View File

@@ -11,6 +11,7 @@ import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.*;
import forge.game.combat.Combat;
import forge.game.event.GameEventCombatChanged;
import forge.game.player.Player;
import forge.game.player.PlayerActionConfirmMode;
import forge.game.spellability.AbilitySub;
@@ -511,6 +512,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
// Blockeres are already declared, set this to unblocked
game.getCombat().addAttacker(tgtC, defenders.get(0));
game.getCombat().getBandOfAttacker(tgtC).setBlocked(false);
game.fireEvent(new GameEventCombatChanged());
}
}
if (sa.hasParam("Tapped") || sa.hasParam("Ninjutsu")) {
@@ -880,6 +882,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
final List<GameEntity> e = combat.getDefenders();
final GameEntity defender = player.getController().chooseSingleEntityForEffect(e, sa, "Declare " + c);
combat.addAttacker(c, defender);
game.fireEvent(new GameEventCombatChanged());
}
}
if (sa.hasParam("Blocking")) {
@@ -891,6 +894,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
if (combat.isAttacking(attacker)) {
combat.addBlocker(attacker, c);
combat.orderAttackersForDamageAssignment(c);
game.fireEvent(new GameEventCombatChanged());
}
}
}

View File

@@ -15,6 +15,7 @@ import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardFactory;
import forge.game.card.CardLists;
import forge.game.event.GameEventCombatChanged;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
@@ -189,6 +190,7 @@ public class CopyPermanentEffect extends SpellAbilityEffect {
if (sa.hasParam("CopyAttacking") && game.getPhaseHandler().inCombat()) {
final GameEntity defender = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("CopyAttacking"), sa).get(0);
game.getCombat().addAttacker(copyInPlay, defender);
game.fireEvent(new GameEventCombatChanged());
}
if (sa.hasParam("AttachedTo")) {

View File

@@ -27,6 +27,7 @@ import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardFactory;
import forge.game.combat.Combat;
import forge.game.event.GameEventCombatChanged;
import forge.game.event.GameEventTokenCreated;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
@@ -297,6 +298,7 @@ public class TokenEffect extends SpellAbilityEffect {
}
}
boolean combatChanged = false;
final Game game = controller.getGame();
for (final Card c : tokens) {
if (this.tokenAttacking && game.getPhaseHandler().inCombat()) {
@@ -304,6 +306,7 @@ public class TokenEffect extends SpellAbilityEffect {
final List<GameEntity> defs = combat.getDefenders();
final GameEntity defender = c.getController().getController().chooseSingleEntityForEffect(defs, sa, "Choose which defender to attack with " + c, false);
combat.addAttacker(c, defender);
combatChanged = true;
}
if (this.tokenBlocking != null && game.getPhaseHandler().inCombat()) {
Combat combat = game.getPhaseHandler().getCombat();
@@ -315,6 +318,7 @@ public class TokenEffect extends SpellAbilityEffect {
} else {
// TODO Flash Foliage: set blocked; attackerBlocked trigger; damage
}
combatChanged = true;
}
}
if (remember) {
@@ -336,6 +340,10 @@ public class TokenEffect extends SpellAbilityEffect {
}
}
}
if (combatChanged) {
game.fireEvent(new GameEventCombatChanged());
}
}
}
}

View File

@@ -0,0 +1,13 @@
package forge.game.event;
public class GameEventCombatChanged extends GameEvent {
public GameEventCombatChanged() {
}
@Override
public <T> T visit(IGameEventVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@@ -18,6 +18,7 @@ public interface IGameEventVisitor<T> {
T visit(GameEventCardTapped event);
T visit(GameEventCardStatsChanged event);
T visit(GameEventCardCounters event);
T visit(GameEventCombatChanged event);
T visit(GameEventCombatEnded event);
T visit(GameEventGameFinished event);
T visit(GameEventGameOutcome event);
@@ -60,6 +61,8 @@ public interface IGameEventVisitor<T> {
public T visit(GameEventCardStatsChanged event) { return null; }
public T visit(GameEventCardCounters event) { return null; }
public T visit(GameEventCardPhased event) { return null; }
public T visit(GameEventCombatChanged event) { return null; }
public T visit(GameEventCombatEnded event) { return null; }
public T visit(GameEventGameFinished event) { return null; }
public T visit(GameEventGameOutcome event) { return null; }
public T visit(GameEventFlipCoin event) { return null; }
@@ -84,7 +87,6 @@ public interface IGameEventVisitor<T> {
public T visit(GameEventTurnPhase event) { return null; }
public T visit(GameEventPlayerDamaged event) { return null; }
public T visit(GameEventZone event) { return null; }
public T visit(GameEventCombatEnded event) { return null; }
}
}

View File

@@ -473,7 +473,7 @@ public class PhaseHandler implements java.io.Serializable, IGameStateObject {
}
}
private Combat declareAttackersTurnBasedAction() {
private void declareAttackersTurnBasedAction() {
Player whoDeclares = playerDeclaresAttackers == null || playerDeclaresAttackers.hasLost() ? playerTurn : playerDeclaresAttackers;
if (CombatUtil.canAttack(playerTurn)) {
@@ -481,7 +481,7 @@ public class PhaseHandler implements java.io.Serializable, IGameStateObject {
}
if (game.isGameOver()) { // they just like to close window at any moment
return null;
return;
}
combat.removeAbsentCombatants();
@@ -544,7 +544,8 @@ public class PhaseHandler implements java.io.Serializable, IGameStateObject {
for (final Card c : combat.getAttackers()) {
CombatUtil.checkDeclaredAttacker(game, c, combat);
}
return combat;
game.fireEvent(new GameEventCombatChanged());
}
@@ -686,6 +687,8 @@ public class PhaseHandler implements java.io.Serializable, IGameStateObject {
a.getDamageHistory().setCreatureGotBlockedThisCombat(true);
}
game.fireEvent(new GameEventCombatChanged());
}