From a5d7ca83d7ac5e13805bff58f2838384a97beed6 Mon Sep 17 00:00:00 2001 From: LevelX2 Date: Sat, 31 Oct 2015 11:55:20 +0100 Subject: [PATCH] Checked objects possible to cause null pointer exceptions. Added some logging. --- Mage.Common/src/mage/view/SeatView.java | 7 ++- .../java/mage/server/game/GamesRoomImpl.java | 16 ++--- .../sets/battleforzendikar/BringToLight.java | 11 +++- .../mage/sets/lorwyn/RingsOfBrighthearth.java | 2 +- .../mage/sets/mirrodin/IsochronScepter.java | 25 +++++--- .../QuicksilverGargantuan.java | 63 ++++++++++--------- .../mage/sets/tenthedition/DoublingCube.java | 12 ++-- Mage/src/mage/Mana.java | 2 +- ...tureEntersBattlefieldTriggeredAbility.java | 7 ++- .../predicate/mageobject/ColorPredicate.java | 2 +- Mage/src/mage/game/GameCommanderImpl.java | 8 ++- Mage/src/mage/players/net/UserData.java | 5 +- 12 files changed, 94 insertions(+), 66 deletions(-) diff --git a/Mage.Common/src/mage/view/SeatView.java b/Mage.Common/src/mage/view/SeatView.java index f8f79a397e..d812dadebd 100644 --- a/Mage.Common/src/mage/view/SeatView.java +++ b/Mage.Common/src/mage/view/SeatView.java @@ -30,6 +30,7 @@ package mage.view; import java.io.Serializable; import java.util.UUID; import mage.game.Seat; +import mage.players.net.UserData; /** * @@ -48,7 +49,11 @@ public class SeatView implements Serializable { if (seat.getPlayer() != null) { this.playerId = seat.getPlayer().getId(); this.playerName = seat.getPlayer().getName(); - this.flagName = seat.getPlayer().getUserData().getFlagName(); + if (seat.getPlayer().getUserData() == null) { + this.flagName = UserData.getDefaultFlagName(); + } else { + this.flagName = seat.getPlayer().getUserData().getFlagName(); + } } else { // Empty seat this.playerName = ""; diff --git a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java index 63edac1348..9afcea7846 100644 --- a/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java +++ b/Mage.Server/src/main/java/mage/server/game/GamesRoomImpl.java @@ -228,13 +228,15 @@ class TableListSorter implements Comparator { @Override public int compare(Table one, Table two) { - if (!one.getState().equals(TableState.SIDEBOARDING) && !one.getState().equals(TableState.DUELING)) { - if (one.getState().compareTo(two.getState()) != 0) { - return one.getState().compareTo(two.getState()); - } - } else if (!two.getState().equals(TableState.SIDEBOARDING) && !two.getState().equals(TableState.DUELING)) { - if (one.getState().compareTo(two.getState()) != 0) { - return one.getState().compareTo(two.getState()); + if (one.getState() != null && two.getState() != null) { + if (!TableState.SIDEBOARDING.equals(one.getState()) && !TableState.DUELING.equals(one.getState())) { + if (one.getState().compareTo(two.getState()) != 0) { + return one.getState().compareTo(two.getState()); + } + } else if (!TableState.SIDEBOARDING.equals(two.getState()) && !TableState.DUELING.equals(two.getState())) { + if (one.getState().compareTo(two.getState()) != 0) { + return one.getState().compareTo(two.getState()); + } } } if (two.getEndTime() != null) { diff --git a/Mage.Sets/src/mage/sets/battleforzendikar/BringToLight.java b/Mage.Sets/src/mage/sets/battleforzendikar/BringToLight.java index 21f64d21c7..5419dc8264 100644 --- a/Mage.Sets/src/mage/sets/battleforzendikar/BringToLight.java +++ b/Mage.Sets/src/mage/sets/battleforzendikar/BringToLight.java @@ -45,6 +45,7 @@ import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.players.Player; import mage.target.common.TargetCardInLibrary; +import org.apache.log4j.Logger; /** * @@ -77,7 +78,7 @@ class BringToLightEffect extends OneShotEffect { public BringToLightEffect() { super(Outcome.PlayForFree); this.staticText = "Converge — Search your library for a creature, instant, or sorcery card with converted mana " - + "cost less than or equal to the number of colors of mana spent to cast Bring to Light, exile that card, " + + "cost less than or equal to the number of colors of mana spent to cast {this}, exile that card, " + "then shuffle your library. You may cast that card without paying its mana cost"; } @@ -102,12 +103,16 @@ class BringToLightEffect extends OneShotEffect { controller.searchLibrary(target, game); Card card = controller.getLibrary().getCard(target.getFirstTarget(), game); if (card != null) { - controller.moveCards(card, null, Zone.EXILED, source, game); + controller.moveCards(card, Zone.EXILED, source, game); } controller.shuffleLibrary(game); if (card != null) { if (controller.chooseUse(outcome, "Cast " + card.getName() + " without paying its mana cost?", source, game)) { - controller.cast(card.getSpellAbility(), game, true); + if (card.getSpellAbility() != null) { + controller.cast(card.getSpellAbility(), game, true); + } else { + Logger.getLogger(BringToLightEffect.class).error("Bring to Light: spellAbility == null " + card.getName()); + } } } return true; diff --git a/Mage.Sets/src/mage/sets/lorwyn/RingsOfBrighthearth.java b/Mage.Sets/src/mage/sets/lorwyn/RingsOfBrighthearth.java index 4bf012e1bb..8793c91e92 100644 --- a/Mage.Sets/src/mage/sets/lorwyn/RingsOfBrighthearth.java +++ b/Mage.Sets/src/mage/sets/lorwyn/RingsOfBrighthearth.java @@ -94,7 +94,7 @@ class RingsOfBrighthearthTriggeredAbility extends TriggeredAbilityImpl { public boolean checkTrigger(GameEvent event, Game game) { if (event.getPlayerId().equals(getControllerId())) { StackAbility stackAbility = (StackAbility) game.getStack().getStackObject(event.getSourceId()); - if (!(stackAbility.getStackAbility() instanceof ManaAbility)) { + if (stackAbility != null && !(stackAbility.getStackAbility() instanceof ManaAbility)) { Effect effect = this.getEffects().get(0); effect.setValue("stackAbility", stackAbility.getStackAbility()); return true; diff --git a/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java b/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java index 182669babf..e4eb8d3083 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java +++ b/Mage.Sets/src/mage/sets/mirrodin/IsochronScepter.java @@ -28,11 +28,6 @@ package mage.sets.mirrodin; import java.util.UUID; - -import mage.constants.CardType; -import mage.constants.Outcome; -import mage.constants.Rarity; -import mage.constants.Zone; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldTriggeredAbility; import mage.abilities.common.SimpleActivatedAbility; @@ -41,6 +36,10 @@ import mage.abilities.costs.mana.GenericManaCost; import mage.abilities.effects.OneShotEffect; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; +import mage.constants.Outcome; +import mage.constants.Rarity; +import mage.constants.Zone; import mage.filter.Filter; import mage.filter.FilterCard; import mage.filter.predicate.mageobject.CardTypePredicate; @@ -50,6 +49,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.TargetCard; import mage.util.CardUtil; +import org.apache.log4j.Logger; /** * @@ -84,7 +84,8 @@ public class IsochronScepter extends CardImpl { class IsochronScepterImprintEffect extends OneShotEffect { private static final FilterCard filter = new FilterCard("instant card with converted mana cost 2 or less from your hand"); - static { + + static { filter.add(new CardTypePredicate(CardType.INSTANT)); filter.add(new ConvertedManaCostPredicate(Filter.ComparisonType.LessThan, 3)); } @@ -109,7 +110,7 @@ class IsochronScepterImprintEffect extends OneShotEffect { && controller.choose(Outcome.Benefit, controller.getHand(), target, game)) { Card card = controller.getHand().get(target.getFirstTarget(), game); if (card != null) { - controller.moveCardToExileWithInfo(card, source.getSourceId(), sourcePermanent.getIdName() +" (Imprint)", source.getSourceId(), game, Zone.HAND, true); + controller.moveCardToExileWithInfo(card, source.getSourceId(), sourcePermanent.getIdName() + " (Imprint)", source.getSourceId(), game, Zone.HAND, true); Permanent permanent = game.getPermanent(source.getSourceId()); if (permanent != null) { permanent.imprint(card.getId(), game); @@ -121,7 +122,7 @@ class IsochronScepterImprintEffect extends OneShotEffect { return true; } return false; - + } @java.lang.Override @@ -158,10 +159,14 @@ class IsochronScepterCopyEffect extends OneShotEffect { if (controller.chooseUse(outcome, new StringBuilder("Create a copy of ").append(imprintedInstant.getName()).append("?").toString(), source, game)) { Card copiedCard = game.copyCard(imprintedInstant, source, source.getControllerId()); if (copiedCard != null) { - game.getExile().add(source.getSourceId(), "",copiedCard); + game.getExile().add(source.getSourceId(), "", copiedCard); game.getState().setZone(copiedCard.getId(), Zone.EXILED); if (controller.chooseUse(outcome, "Cast the copied card without paying mana cost?", source, game)) { - controller.cast(copiedCard.getSpellAbility(), game, true); + if (copiedCard.getSpellAbility() != null) { + controller.cast(copiedCard.getSpellAbility(), game, true); + } else { + Logger.getLogger(IsochronScepterCopyEffect.class).error("Isochron Scepter: spell ability == null " + copiedCard.getName()); + } } } } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/QuicksilverGargantuan.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/QuicksilverGargantuan.java index a02bb9ccda..2b9c6fb19c 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/QuicksilverGargantuan.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/QuicksilverGargantuan.java @@ -25,27 +25,25 @@ * authors and should not be interpreted as representing official policies, either expressed * or implied, of BetaSteward_at_googlemail.com. */ - package mage.sets.scarsofmirrodin; -import mage.constants.CardType; -import mage.constants.Rarity; +import java.util.UUID; import mage.MageInt; import mage.abilities.Ability; import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.effects.ContinuousEffectImpl; import mage.cards.Card; import mage.cards.CardImpl; +import mage.constants.CardType; import mage.constants.Duration; import mage.constants.Layer; import mage.constants.Outcome; +import mage.constants.Rarity; import mage.constants.SubLayer; import mage.game.Game; import mage.game.permanent.Permanent; -import mage.target.common.TargetCreaturePermanent; - -import java.util.UUID; import mage.target.Target; +import mage.target.common.TargetCreaturePermanent; /** * @author ayratn @@ -60,7 +58,7 @@ public class QuicksilverGargantuan extends CardImpl { this.power = new MageInt(7); this.toughness = new MageInt(7); - Ability ability = new EntersBattlefieldAbility(new QuicksilverGargantuanCopyEffect(), + Ability ability = new EntersBattlefieldAbility(new QuicksilverGargantuanCopyEffect(), "You may have {this} enter the battlefield as a copy of any creature on the battlefield, except it's still 7/7"); Target target = new TargetCreaturePermanent(); target.setNotTarget(true); @@ -81,7 +79,7 @@ public class QuicksilverGargantuan extends CardImpl { public QuicksilverGargantuanCopyEffect() { super(Duration.WhileOnBattlefield, Layer.CopyEffects_1, SubLayer.NA, Outcome.BecomeCreature); - staticText = "You may have {this} enter the battlefield as a copy of any creature on the battlefield, except it's still 7/7"; + staticText = "You may have {this} enter the battlefield as a copy of any creature on the battlefield, except it's still 7/7"; } public QuicksilverGargantuanCopyEffect(final QuicksilverGargantuanCopyEffect effect) { @@ -91,30 +89,35 @@ public class QuicksilverGargantuan extends CardImpl { @Override public boolean apply(Game game, Ability source) { Card card = game.getCard(source.getFirstTarget()); - Permanent permanent = game.getPermanent(source.getSourceId()); - permanent.setName(card.getName()); - permanent.getColor(game).setColor(card.getColor(game)); - permanent.getManaCost().clear(); - permanent.getManaCost().add(card.getManaCost()); - permanent.getCardType().clear(); - for (CardType type : card.getCardType()) { - permanent.getCardType().add(type); + Permanent permanent = game.getPermanentEntering(source.getSourceId()); + if (permanent == null) { + permanent = game.getPermanent(source.getSourceId()); } - permanent.getSubtype().clear(); - for (String type : card.getSubtype()) { - permanent.getSubtype().add(type); + if (permanent != null) { + permanent.setName(card.getName()); + permanent.getColor(game).setColor(card.getColor(game)); + permanent.getManaCost().clear(); + permanent.getManaCost().add(card.getManaCost()); + permanent.getCardType().clear(); + for (CardType type : card.getCardType()) { + permanent.getCardType().add(type); + } + permanent.getSubtype().clear(); + for (String type : card.getSubtype()) { + permanent.getSubtype().add(type); + } + permanent.getSupertype().clear(); + for (String type : card.getSupertype()) { + permanent.getSupertype().add(type); + } + permanent.setExpansionSetCode(card.getExpansionSetCode()); + permanent.getAbilities().clear(); + for (Ability ability : card.getAbilities()) { + permanent.addAbility(ability, game); + } + return true; } - permanent.getSupertype().clear(); - for (String type : card.getSupertype()) { - permanent.getSupertype().add(type); - } - permanent.setExpansionSetCode(card.getExpansionSetCode()); - permanent.getAbilities().clear(); - for (Ability ability : card.getAbilities()) { - permanent.addAbility(ability, game); - } - - return true; + return false; } @Override diff --git a/Mage.Sets/src/mage/sets/tenthedition/DoublingCube.java b/Mage.Sets/src/mage/sets/tenthedition/DoublingCube.java index 86c0ba07ee..99ea557b4e 100644 --- a/Mage.Sets/src/mage/sets/tenthedition/DoublingCube.java +++ b/Mage.Sets/src/mage/sets/tenthedition/DoublingCube.java @@ -36,7 +36,6 @@ import mage.abilities.effects.common.ManaEffect; import mage.abilities.mana.SimpleManaAbility; import mage.cards.CardImpl; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; import mage.game.Game; @@ -57,7 +56,7 @@ public class DoublingCube extends CardImpl { Ability ability = new SimpleManaAbility(Zone.BATTLEFIELD, new DoublingCubeEffect(), new ManaCostsImpl("{3}")); ability.addCost(new TapSourceCost()); this.addAbility(ability); - + } public DoublingCube(final DoublingCube card) { @@ -83,11 +82,11 @@ class DoublingCubeEffect extends ManaEffect { @Override public boolean apply(Game game, Ability source) { - Player you = game.getPlayer(source.getControllerId()); - if (you == null) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { return false; } - ManaPool pool = you.getManaPool(); + ManaPool pool = controller.getManaPool(); int blackMana = pool.getBlack(); int whiteMana = pool.getWhite(); int blueMana = pool.getBlue(); @@ -105,10 +104,9 @@ class DoublingCubeEffect extends ManaEffect { return null; } - @Override public DoublingCubeEffect copy() { return new DoublingCubeEffect(this); } - } +} diff --git a/Mage/src/mage/Mana.java b/Mage/src/mage/Mana.java index b9b3e04c8f..e5dace32df 100644 --- a/Mage/src/mage/Mana.java +++ b/Mage/src/mage/Mana.java @@ -259,7 +259,7 @@ public class Mana implements Comparable, Serializable, Copyable { @Override public String toString() { - StringBuilder sbMana = threadLocalBuilder.get(); + StringBuilder sbMana = new StringBuilder(); if (colorless > 0) { sbMana.append("{").append(Integer.toString(colorless)).append("}"); } diff --git a/Mage/src/mage/abilities/common/AnotherCreatureEntersBattlefieldTriggeredAbility.java b/Mage/src/mage/abilities/common/AnotherCreatureEntersBattlefieldTriggeredAbility.java index cb67ac5ca1..accd6b2205 100644 --- a/Mage/src/mage/abilities/common/AnotherCreatureEntersBattlefieldTriggeredAbility.java +++ b/Mage/src/mage/abilities/common/AnotherCreatureEntersBattlefieldTriggeredAbility.java @@ -30,8 +30,11 @@ public class AnotherCreatureEntersBattlefieldTriggeredAbility extends TriggeredA @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getTargetId() != this.getSourceId()) { - Permanent permanent = game.getPermanent(event.getTargetId()); - if (permanent.getCardType().contains(CardType.CREATURE)) { + Permanent permanent = game.getPermanentEntering(event.getTargetId()); + if (permanent == null) { + permanent = game.getPermanent(event.getTargetId()); + } + if (permanent != null && permanent.getCardType().contains(CardType.CREATURE)) { return true; } } diff --git a/Mage/src/mage/filter/predicate/mageobject/ColorPredicate.java b/Mage/src/mage/filter/predicate/mageobject/ColorPredicate.java index 74e5164049..d6f3ad0a97 100644 --- a/Mage/src/mage/filter/predicate/mageobject/ColorPredicate.java +++ b/Mage/src/mage/filter/predicate/mageobject/ColorPredicate.java @@ -46,7 +46,7 @@ public class ColorPredicate implements Predicate { @Override public boolean apply(MageObject input, Game game) { - return input.getColor(game).contains(color); + return color != null && input.getColor(game).contains(color); } @Override diff --git a/Mage/src/mage/game/GameCommanderImpl.java b/Mage/src/mage/game/GameCommanderImpl.java index 4181efc3e4..2d9602d02a 100644 --- a/Mage/src/mage/game/GameCommanderImpl.java +++ b/Mage/src/mage/game/GameCommanderImpl.java @@ -129,7 +129,9 @@ public abstract class GameCommanderImpl extends GameImpl { if (!mulliganedCards.containsKey(playerId)) { mulliganedCards.put(playerId, new CardsImpl()); } - card.moveToExile(null, "", null, this); + player.getHand().remove(card); + getExile().add(card); + getState().setZone(card.getId(), Zone.EXILED); card.setFaceDown(true, this); mulliganedCards.get(playerId).add(card); } @@ -168,7 +170,9 @@ public abstract class GameCommanderImpl extends GameImpl { if (player != null && mulliganedCards.containsKey(playerId)) { for (Card card : mulliganedCards.get(playerId).getCards(this)) { if (card != null) { - card.moveToZone(Zone.LIBRARY, null, this, false); + getExile().removeCard(card, this); + player.getLibrary().putOnTop(card, this); + getState().setZone(card.getId(), Zone.LIBRARY); card.setFaceDown(false, this); } } diff --git a/Mage/src/mage/players/net/UserData.java b/Mage/src/mage/players/net/UserData.java index 0e6e401733..c2c3b2a3bb 100644 --- a/Mage/src/mage/players/net/UserData.java +++ b/Mage/src/mage/players/net/UserData.java @@ -59,7 +59,7 @@ public class UserData implements Serializable { } public static UserData getDefaultUserDataView() { - return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, "world.png", false, true, true, false, false, false); + return new UserData(UserGroup.DEFAULT, 0, false, false, true, null, getDefaultFlagName(), false, true, true, false, false, false); } public void setGroupId(int groupId) { @@ -166,4 +166,7 @@ public class UserData implements Serializable { this.autoOrderTrigger = autoOrderTrigger; } + public static String getDefaultFlagName() { + return "world.png"; + } }