1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-13 01:01:11 -09:00

Fixed some possible null pointer exceptions.

This commit is contained in:
LevelX2 2015-07-28 00:04:57 +02:00
parent b23d987fe7
commit 1ef74f3293
6 changed files with 164 additions and 79 deletions
Mage.Server.Plugins/Mage.Player.Human/src/mage/player/human
Mage/src/mage

View file

@ -251,7 +251,7 @@ public class HumanPlayer extends PlayerImpl {
@Override @Override
public boolean choose(Outcome outcome, Choice choice, Game game) { public boolean choose(Outcome outcome, Choice choice, Game game) {
if (outcome.equals(Outcome.PutManaInPool)) { if (Outcome.PutManaInPool.equals(outcome)) {
if (currentlyUnpaidMana != null if (currentlyUnpaidMana != null
&& ManaUtil.tryToAutoSelectAManaColor(choice, currentlyUnpaidMana)) { && ManaUtil.tryToAutoSelectAManaColor(choice, currentlyUnpaidMana)) {
return true; return true;

View file

@ -51,13 +51,15 @@ import mage.target.common.TargetCardInGraveyard;
/** /**
* Cards with the Aura subtype don't change the zone they are in, if there is no * Cards with the Aura subtype don't change the zone they are in, if there is no
* valid target on the battlefield. Also, when entering the battlefield and it * valid target on the battlefield. Also, when entering the battlefield and it
* was not cast (so from Zone != Hand), this effect gets the target to whitch to attach it * was not cast (so from Zone != Hand), this effect gets the target to whitch to
* and adds the Aura the the battlefield and attachs it to the target. * attach it and adds the Aura the the battlefield and attachs it to the target.
* The "attachTo:" value in game state has to be set therefore. * The "attachTo:" value in game state has to be set therefore.
* *
* If no "attachTo:" value is defined, the controlling player has to chose the aura target. * If no "attachTo:" value is defined, the controlling player has to chose the
* aura target.
* *
* This effect is automatically added to ContinuousEffects at the start of a game * This effect is automatically added to ContinuousEffects at the start of a
* game
* *
* @author North * @author North
*/ */
@ -122,7 +124,8 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
} }
Player player = game.getPlayer(card.getOwnerId()); Player player = game.getPlayer(card.getOwnerId());
Outcome auraOutcome = Outcome.BoostCreature; Outcome auraOutcome = Outcome.BoostCreature;
Ability: for (Ability ability:card.getAbilities()) { Ability:
for (Ability ability : card.getAbilities()) {
if (ability instanceof SpellAbility) { if (ability instanceof SpellAbility) {
for (Effect effect : ability.getEffects()) { for (Effect effect : ability.getEffects()) {
if (effect instanceof AttachEffect) { if (effect instanceof AttachEffect) {
@ -167,8 +170,11 @@ public class AuraReplacementEffect extends ReplacementEffectImpl {
game.getBattlefield().addPermanent(permanent); game.getBattlefield().addPermanent(permanent);
card.setZone(Zone.BATTLEFIELD, game); card.setZone(Zone.BATTLEFIELD, game);
game.applyEffects(); game.applyEffects();
permanent.entersBattlefield(event.getSourceId(), game, fromZone, true); boolean entered = permanent.entersBattlefield(event.getSourceId(), game, fromZone, true);
game.applyEffects(); game.applyEffects();
if (!entered) {
return false;
}
game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD)); game.fireEvent(new ZoneChangeEvent(permanent, controllerId, fromZone, Zone.BATTLEFIELD));
if (targetCard != null) { if (targetCard != null) {

View file

@ -421,13 +421,17 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
game.setZone(objectId, Zone.BATTLEFIELD); game.setZone(objectId, Zone.BATTLEFIELD);
game.setScopeRelevant(true); game.setScopeRelevant(true);
game.applyEffects(); game.applyEffects();
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true); boolean entered = permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
game.setScopeRelevant(false); game.setScopeRelevant(false);
game.applyEffects(); game.applyEffects();
if (entered) {
if (flag) { if (flag) {
permanent.setTapped(true); permanent.setTapped(true);
} }
event.setTarget(permanent); event.setTarget(permanent);
} else {
return false;
}
break; break;
default: default:
Card sourceCard = game.getCard(sourceId); Card sourceCard = game.getCard(sourceId);
@ -603,12 +607,14 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
game.setScopeRelevant(true); game.setScopeRelevant(true);
permanent.setTapped(tapped); permanent.setTapped(tapped);
permanent.setFaceDown(facedown, game); permanent.setFaceDown(facedown, game);
permanent.entersBattlefield(sourceId, game, event.getFromZone(), true); boolean entered = permanent.entersBattlefield(sourceId, game, event.getFromZone(), true);
game.setScopeRelevant(false); game.setScopeRelevant(false);
game.applyEffects(); game.applyEffects();
if (entered) {
game.addSimultaneousEvent(new ZoneChangeEvent(permanent, event.getPlayerId(), fromZone, Zone.BATTLEFIELD)); game.addSimultaneousEvent(new ZoneChangeEvent(permanent, event.getPlayerId(), fromZone, Zone.BATTLEFIELD));
return true; return true;
} }
}
if (facedown) { if (facedown) {
this.setFaceDown(false, game); this.setFaceDown(false, game);
} }

View file

@ -810,6 +810,7 @@ public class Combat implements Serializable, Copyable<Combat> {
// check now, if it already blocks a creature that mustBeBlockedByAtLeastOne // check now, if it already blocks a creature that mustBeBlockedByAtLeastOne
if (possibleBlocker.getBlocking() > 0) { if (possibleBlocker.getBlocking() > 0) {
CombatGroup combatGroupOfPossibleBlocker = findGroupOfBlocker(possibleBlockerId); CombatGroup combatGroupOfPossibleBlocker = findGroupOfBlocker(possibleBlockerId);
if (combatGroupOfPossibleBlocker != null) {
for (UUID blockedAttackerId : combatGroupOfPossibleBlocker.getAttackers()) { for (UUID blockedAttackerId : combatGroupOfPossibleBlocker.getAttackers()) {
if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) { if (mustBeBlockedByAtLeastOne.containsKey(blockedAttackerId)) {
// blocks a creature that has to be blocked by at least one // blocks a creature that has to be blocked by at least one
@ -828,6 +829,7 @@ public class Combat implements Serializable, Copyable<Combat> {
} }
} }
} }
}
return null; return null;
} }
@ -947,9 +949,12 @@ public class Combat implements Serializable, Copyable<Combat> {
if (!canDefenderBeAttacked(attackerId, defenderId, game)) { if (!canDefenderBeAttacked(attackerId, defenderId, game)) {
return false; return false;
} }
Permanent attacker = game.getPermanent(attackerId);
if (attacker == null) {
return false;
}
CombatGroup newGroup = new CombatGroup(defenderId, defender != null, defender != null ? defender.getControllerId() : defenderId); CombatGroup newGroup = new CombatGroup(defenderId, defender != null, defender != null ? defender.getControllerId() : defenderId);
newGroup.attackers.add(attackerId); newGroup.attackers.add(attackerId);
Permanent attacker = game.getPermanent(attackerId);
attacker.setAttacking(true); attacker.setAttacking(true);
groups.add(newGroup); groups.add(newGroup);
return true; return true;

View file

@ -25,7 +25,6 @@
* authors and should not be interpreted as representing official policies, either expressed * authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com. * or implied, of BetaSteward_at_googlemail.com.
*/ */
package mage.game.permanent; package mage.game.permanent;
import java.util.ArrayList; import java.util.ArrayList;
@ -45,60 +44,89 @@ import mage.game.Game;
public interface Permanent extends Card, Controllable { public interface Permanent extends Card, Controllable {
void setControllerId(UUID controllerId); void setControllerId(UUID controllerId);
boolean isTapped(); boolean isTapped();
boolean untap(Game game); boolean untap(Game game);
boolean tap(Game game); boolean tap(Game game);
/** /**
* use tap(game) * use tap(game)
* <p>setTapped doesn't trigger TAPPED event and should be used * <p>
* only if you want permanent to enter battlefield tapped</p> * setTapped doesn't trigger TAPPED event and should be used only if you
* want permanent to enter battlefield tapped</p>
* *
* @param tapped * @param tapped
* @deprecated * @deprecated
*/ */
@Deprecated @Deprecated
void setTapped(boolean tapped); void setTapped(boolean tapped);
boolean canTap(); boolean canTap();
boolean isFlipped(); boolean isFlipped();
boolean unflip(Game game); boolean unflip(Game game);
boolean flip(Game game); boolean flip(Game game);
boolean transform(Game game); boolean transform(Game game);
boolean isTransformed(); boolean isTransformed();
void setTransformed(boolean value); void setTransformed(boolean value);
boolean isPhasedIn(); boolean isPhasedIn();
boolean phaseIn(Game game); boolean phaseIn(Game game);
boolean phaseOut(Game game); boolean phaseOut(Game game);
boolean isMonstrous(); boolean isMonstrous();
void setMonstrous(boolean value); void setMonstrous(boolean value);
boolean isRenowned(); boolean isRenowned();
void setRenowned(boolean value); void setRenowned(boolean value);
void setCardNumber(int cid); void setCardNumber(int cid);
void setExpansionSetCode(String expansionSetCode); void setExpansionSetCode(String expansionSetCode);
void setRarity(Rarity rarity); void setRarity(Rarity rarity);
void setFlipCard(boolean flipCard); void setFlipCard(boolean flipCard);
void setFlipCardName(String flipCardName); void setFlipCardName(String flipCardName);
void setSecondCardFace(Card card); void setSecondCardFace(Card card);
Counters getCounters(); Counters getCounters();
List<UUID> getAttachments(); List<UUID> getAttachments();
UUID getAttachedTo(); UUID getAttachedTo();
void attachTo(UUID permanentId, Game game); void attachTo(UUID permanentId, Game game);
boolean addAttachment(UUID permanentId, Game game); boolean addAttachment(UUID permanentId, Game game);
boolean removeAttachment(UUID permanentId, Game game); boolean removeAttachment(UUID permanentId, Game game);
boolean canBeTargetedBy(MageObject source, UUID controllerId, Game game); boolean canBeTargetedBy(MageObject source, UUID controllerId, Game game);
boolean hasProtectionFrom(MageObject source, Game game); boolean hasProtectionFrom(MageObject source, Game game);
boolean cantBeEnchantedBy(MageObject source, Game game); boolean cantBeEnchantedBy(MageObject source, Game game);
boolean wasControlledFromStartOfControllerTurn(); boolean wasControlledFromStartOfControllerTurn();
boolean hasSummoningSickness(); boolean hasSummoningSickness();
int getDamage(); int getDamage();
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable); int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable);
int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, ArrayList<UUID> appliedEffects); int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, ArrayList<UUID> appliedEffects);
@ -114,58 +142,83 @@ public interface Permanent extends Card, Controllable {
* @return * @return
*/ */
int markDamage(int damage, UUID sourceId, Game game, boolean preventable, boolean combat); int markDamage(int damage, UUID sourceId, Game game, boolean preventable, boolean combat);
int applyDamage(Game game); int applyDamage(Game game);
void removeAllDamage(Game game); void removeAllDamage(Game game);
void reset(Game game); void reset(Game game);
boolean destroy(UUID sourceId, Game game, boolean noRegen); boolean destroy(UUID sourceId, Game game, boolean noRegen);
boolean sacrifice(UUID sourceId, Game game); boolean sacrifice(UUID sourceId, Game game);
boolean regenerate(UUID sourceId, Game game); boolean regenerate(UUID sourceId, Game game);
boolean fight(Permanent fightTarget, Ability source, Game game); boolean fight(Permanent fightTarget, Ability source, Game game);
void entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent); boolean entersBattlefield(UUID sourceId, Game game, Zone fromZone, boolean fireEvent);
String getValue(); String getValue();
@Deprecated @Deprecated
void addAbility(Ability ability); void addAbility(Ability ability);
@Deprecated @Deprecated
void addAbility(Ability ability, Game game); void addAbility(Ability ability, Game game);
void addAbility(Ability ability, UUID sourceId, Game game); void addAbility(Ability ability, UUID sourceId, Game game);
void addAbility(Ability ability, UUID sourceId, Game game, boolean createNewId); void addAbility(Ability ability, UUID sourceId, Game game, boolean createNewId);
void removeAllAbilities(UUID sourceId, Game game); void removeAllAbilities(UUID sourceId, Game game);
void addLoyaltyUsed(); void addLoyaltyUsed();
boolean canLoyaltyBeUsed(Game game); boolean canLoyaltyBeUsed(Game game);
public void resetControl(); public void resetControl();
boolean changeControllerId(UUID controllerId, Game game); boolean changeControllerId(UUID controllerId, Game game);
boolean checkControlChanged(Game game); boolean checkControlChanged(Game game);
void beginningOfTurn(Game game); void beginningOfTurn(Game game);
void endOfTurn(Game game); void endOfTurn(Game game);
int getTurnsOnBattlefield(); int getTurnsOnBattlefield();
void addPower(int power); void addPower(int power);
void addToughness(int toughness); void addToughness(int toughness);
boolean isAttacking(); boolean isAttacking();
int getBlocking(); int getBlocking();
void setAttacking(boolean attacking); void setAttacking(boolean attacking);
void setBlocking(int blocking); void setBlocking(int blocking);
int getMaxBlocks(); int getMaxBlocks();
void setMaxBlocks(int maxBlocks); void setMaxBlocks(int maxBlocks);
int getMinBlockedBy(); int getMinBlockedBy();
void setMinBlockedBy(int minBlockedBy); void setMinBlockedBy(int minBlockedBy);
int getMaxBlockedBy(); int getMaxBlockedBy();
boolean isRemovedFromCombat(); boolean isRemovedFromCombat();
void setRemovedFromCombat(boolean removedFromCombat); void setRemovedFromCombat(boolean removedFromCombat);
/** /**
* Sets the maximum number of blockers the creature can be blocked by. * Sets the maximum number of blockers the creature can be blocked by.
* Default = 0 which means there is no restriction in the number of blockers. * Default = 0 which means there is no restriction in the number of
* blockers.
* *
* @param maxBlockedBy maximum number of blockers * @param maxBlockedBy maximum number of blockers
*/ */
@ -180,11 +233,14 @@ public interface Permanent extends Card, Controllable {
* @return * @return
*/ */
boolean canAttack(UUID defenderId, Game game); boolean canAttack(UUID defenderId, Game game);
boolean canBlock(UUID attackerId, Game game); boolean canBlock(UUID attackerId, Game game);
boolean canBlockAny(Game game); boolean canBlockAny(Game game);
/** /**
* Checks by restriction effects if the permanent can use activated abilities * Checks by restriction effects if the permanent can use activated
* abilities
* *
* @param game * @param game
* @return true - permanent can use activated abilities * @return true - permanent can use activated abilities
@ -192,11 +248,15 @@ public interface Permanent extends Card, Controllable {
boolean canUseActivatedAbilities(Game game); boolean canUseActivatedAbilities(Game game);
boolean removeFromCombat(Game game); boolean removeFromCombat(Game game);
boolean removeFromCombat(Game game, boolean withInfo); boolean removeFromCombat(Game game, boolean withInfo);
boolean isDeathtouched(); boolean isDeathtouched();
/** /**
* Returns a list of object refrences that dealt damage this turn to this permanent * Returns a list of object refrences that dealt damage this turn to this
* permanent
*
* @return * @return
*/ */
HashSet<MageObjectReference> getDealtDamageByThisTurn(); HashSet<MageObjectReference> getDealtDamageByThisTurn();
@ -222,13 +282,14 @@ public interface Permanent extends Card, Controllable {
* Get card that was imprinted on this one. * Get card that was imprinted on this one.
* *
* Can be null if no card was imprinted. * Can be null if no card was imprinted.
*
* @return Imprinted card UUID. * @return Imprinted card UUID.
*/ */
List<UUID> getImprinted(); List<UUID> getImprinted();
/** /**
* Allows to connect any card to permanent. * Allows to connect any card to permanent. Very similar to Imprint except
* Very similar to Imprint except that it is for internal use only. * that it is for internal use only.
* *
* @param key * @param key
* @param connectedCard * @param connectedCard
@ -236,8 +297,9 @@ public interface Permanent extends Card, Controllable {
void addConnectedCard(String key, UUID connectedCard); void addConnectedCard(String key, UUID connectedCard);
/** /**
* Returns connected cards. * Returns connected cards. Very similar to Imprint except that it is for
* Very similar to Imprint except that it is for internal use only. * internal use only.
*
* @param key * @param key
* @return * @return
*/ */
@ -245,6 +307,7 @@ public interface Permanent extends Card, Controllable {
/** /**
* Clear all connected cards. * Clear all connected cards.
*
* @param key * @param key
*/ */
void clearConnectedCards(String key); void clearConnectedCards(String key);
@ -269,9 +332,11 @@ public interface Permanent extends Card, Controllable {
void clearPairedCard(); void clearPairedCard();
void setMorphed(boolean value); void setMorphed(boolean value);
boolean isMorphed(); boolean isMorphed();
void setManifested(boolean value); void setManifested(boolean value);
boolean isManifested(); boolean isManifested();
@Override @Override
@ -280,5 +345,6 @@ public interface Permanent extends Card, Controllable {
// Simple int counter to set a timewise create order , the lower the number the earlier the object was created // Simple int counter to set a timewise create order , the lower the number the earlier the object was created
// if objects enter the battlefield at the same time they can get (and should) get the same number. // if objects enter the battlefield at the same time they can get (and should) get the same number.
int getCreateOrder(); int getCreateOrder();
void setCreateOrder(int createOrder); void setCreateOrder(int createOrder);
} }

View file

@ -159,9 +159,10 @@ public class Token extends MageObjectImpl {
this.lastAddedTokenId = newToken.getId(); this.lastAddedTokenId = newToken.getId();
game.setScopeRelevant(true); game.setScopeRelevant(true);
game.applyEffects(); game.applyEffects();
newToken.entersBattlefield(sourceId, game, Zone.OUTSIDE, true); boolean entered = newToken.entersBattlefield(sourceId, game, Zone.OUTSIDE, true);
game.setScopeRelevant(false); game.setScopeRelevant(false);
game.applyEffects(); game.applyEffects();
if (entered) {
game.fireEvent(new ZoneChangeEvent(newToken, event.getPlayerId(), Zone.OUTSIDE, Zone.BATTLEFIELD)); game.fireEvent(new ZoneChangeEvent(newToken, event.getPlayerId(), Zone.OUTSIDE, Zone.BATTLEFIELD));
if (attacking && game.getCombat() != null) { if (attacking && game.getCombat() != null) {
game.getCombat().addAttackingCreature(newToken.getId(), game); game.getCombat().addAttackingCreature(newToken.getId(), game);
@ -170,6 +171,7 @@ public class Token extends MageObjectImpl {
game.informPlayers(controller.getLogName() + " puts a " + newToken.getLogName() + " token onto the battlefield"); game.informPlayers(controller.getLogName() + " puts a " + newToken.getLogName() + " token onto the battlefield");
} }
} }
}
return true; return true;
} }