Lots of code cleanup, including removing some useless null checks,

preventing some NPE's before they ever occur, and clean up some
of the inheritance hierarchy.
This commit is contained in:
elcnesh
2015-04-13 14:29:01 +00:00
parent 19ccab3d00
commit 6dacb83c37
19 changed files with 322 additions and 262 deletions

View File

@@ -0,0 +1,20 @@
package forge.game.ability;
import forge.game.spellability.SpellAbility;
public class IllegalAbilityException extends RuntimeException {
private static final long serialVersionUID = -8638474348184716635L;
public IllegalAbilityException(final SpellAbility sa) {
this(sa.toString());
}
public IllegalAbilityException(final SpellAbility sa, final SpellAbilityEffect effect) {
this(String.format("%s (effect %s)", sa, effect.getClass().getName()));
}
private IllegalAbilityException(final String message) {
super(message);
}
}

View File

@@ -1,62 +0,0 @@
package forge.game.ability;
import com.google.common.collect.Lists;
import forge.game.GameObject;
import forge.game.card.CardCollection;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.util.FCollection;
import java.util.List;
// Class contains all that methods that are used by both effects and AI to fetch their targets.
// {SA}Effect and {SA}Ai now inherit from this class to use these routines, though they should not.
public class SaTargetRoutines {
// Cards
protected CardCollection getTargetCards(SpellAbility sa) { return getCards(false, "Defined", sa); }
protected CardCollection getTargetCards(SpellAbility sa, String definedParam) { return getCards(false, definedParam, sa); }
protected CardCollection getDefinedCardsOrTargeted(SpellAbility sa) { return getCards(true, "Defined", sa); }
protected CardCollection getDefinedCardsOrTargeted(SpellAbility sa, String definedParam) { return getCards(true, definedParam, sa); }
private static CardCollection getCards(boolean definedFirst, String definedParam, SpellAbility sa) {
boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam))
&& sa.getTargets() != null && (sa.getTargets().isTargetingAnyCard() || sa.getTargets().getTargets().isEmpty());
return useTargets ? new CardCollection(sa.getTargets().getTargetCards())
: AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Players
protected FCollection<Player> getTargetPlayers(SpellAbility sa) { return getPlayers(false, "Defined", sa); }
protected FCollection<Player> getTargetPlayers(SpellAbility sa, String definedParam) { return getPlayers(false, definedParam, sa); }
protected FCollection<Player> getDefinedPlayersOrTargeted(SpellAbility sa ) { return getPlayers(true, "Defined", sa); }
protected FCollection<Player> getDefinedPlayersOrTargeted(SpellAbility sa, String definedParam) { return getPlayers(true, definedParam, sa); }
private static FCollection<Player> getPlayers(boolean definedFirst, String definedParam, SpellAbility sa) {
boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? new FCollection<Player>(sa.getTargets().getTargetPlayers())
: AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Spells
protected List<SpellAbility> getTargetSpells(SpellAbility sa) { return getSpells(false, "Defined", sa); }
protected List<SpellAbility> getTargetSpells(SpellAbility sa, String definedParam) { return getSpells(false, definedParam, sa); }
protected List<SpellAbility> getDefinedSpellsOrTargeted(SpellAbility sa, String definedParam) { return getSpells(true, definedParam, sa); }
private static List<SpellAbility> getSpells(boolean definedFirst, String definedParam, SpellAbility sa) {
boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? Lists.newArrayList(sa.getTargets().getTargetSpells())
: AbilityUtils.getDefinedSpellAbilities(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Targets of unspecified type
protected List<GameObject> getTargets(SpellAbility sa) { return getTargetables(false, "Defined", sa); }
protected List<GameObject> getTargets(SpellAbility sa, String definedParam) { return getTargetables(false, definedParam, sa); }
protected List<GameObject> getDefinedOrTargeted(SpellAbility sa, String definedParam) { return getTargetables(true, definedParam, sa); }
private static List<GameObject> getTargetables(boolean definedFirst, String definedParam, SpellAbility sa) {
boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? Lists.newArrayList(sa.getTargets().getTargets())
: AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam(definedParam), sa);
}
}

View File

@@ -1,16 +1,22 @@
package forge.game.ability;
import forge.game.GameObject;
import forge.game.card.CardFactoryUtil;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import org.apache.commons.lang3.StringUtils;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Lists;
import forge.game.GameObject;
import forge.game.card.Card;
import forge.game.card.CardCollection;
import forge.game.card.CardFactoryUtil;
import forge.game.player.Player;
import forge.game.spellability.AbilitySub;
import forge.game.spellability.SpellAbility;
import forge.util.FCollection;
/**
* <p>
* AbilityFactory_AlterLife class.
@@ -20,7 +26,7 @@ import java.util.StringTokenizer;
* @version $Id: AbilityFactoryAlterLife.java 17656 2012-10-22 19:32:56Z Max mtg $
*/
public abstract class SpellAbilityEffect extends SaTargetRoutines {
public abstract class SpellAbilityEffect {
public abstract void resolve(SpellAbility sa);
@@ -129,4 +135,52 @@ public abstract class SpellAbilityEffect extends SaTargetRoutines {
}
}
}
// Target/defined methods
// Cards
protected final static CardCollection getTargetCards(final SpellAbility sa) { return getCards(false, "Defined", sa); }
protected final static CardCollection getTargetCards(final SpellAbility sa, final String definedParam) { return getCards(false, definedParam, sa); }
protected final static CardCollection getDefinedCardsOrTargeted(final SpellAbility sa) { return getCards(true, "Defined", sa); }
protected final static CardCollection getDefinedCardsOrTargeted(final SpellAbility sa, final String definedParam) { return getCards(true, definedParam, sa); }
private static CardCollection getCards(final boolean definedFirst, final String definedParam, final SpellAbility sa) {
final boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam))
&& sa.getTargets() != null && (sa.getTargets().isTargetingAnyCard() || sa.getTargets().getTargets().isEmpty());
return useTargets ? new CardCollection(sa.getTargets().getTargetCards())
: AbilityUtils.getDefinedCards(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Players
protected final static FCollection<Player> getTargetPlayers(final SpellAbility sa) { return getPlayers(false, "Defined", sa); }
protected final static FCollection<Player> getTargetPlayers(final SpellAbility sa, final String definedParam) { return getPlayers(false, definedParam, sa); }
protected final static FCollection<Player> getDefinedPlayersOrTargeted(final SpellAbility sa ) { return getPlayers(true, "Defined", sa); }
protected final static FCollection<Player> getDefinedPlayersOrTargeted(final SpellAbility sa, final String definedParam) { return getPlayers(true, definedParam, sa); }
private static FCollection<Player> getPlayers(final boolean definedFirst, final String definedParam, final SpellAbility sa) {
final boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? new FCollection<Player>(sa.getTargets().getTargetPlayers())
: AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Spells
protected final static List<SpellAbility> getTargetSpells(final SpellAbility sa) { return getSpells(false, "Defined", sa); }
protected final static List<SpellAbility> getTargetSpells(final SpellAbility sa, final String definedParam) { return getSpells(false, definedParam, sa); }
protected final static List<SpellAbility> getDefinedSpellsOrTargeted(final SpellAbility sa, final String definedParam) { return getSpells(true, definedParam, sa); }
private static List<SpellAbility> getSpells(final boolean definedFirst, final String definedParam, final SpellAbility sa) {
final boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? Lists.newArrayList(sa.getTargets().getTargetSpells())
: AbilityUtils.getDefinedSpellAbilities(sa.getHostCard(), sa.getParam(definedParam), sa);
}
// Targets of unspecified type
protected final static List<GameObject> getTargets(final SpellAbility sa) { return getTargetables(false, "Defined", sa); }
protected final static List<GameObject> getTargets(final SpellAbility sa, final String definedParam) { return getTargetables(false, definedParam, sa); }
protected final static List<GameObject> getDefinedOrTargeted(SpellAbility sa, final String definedParam) { return getTargetables(true, definedParam, sa); }
private static List<GameObject> getTargetables(final boolean definedFirst, final String definedParam, final SpellAbility sa) {
final boolean useTargets = sa.usesTargeting() && (!definedFirst || !sa.hasParam(definedParam));
return useTargets ? Lists.newArrayList(sa.getTargets().getTargets())
: AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam(definedParam), sa);
}
}

View File

@@ -1,10 +1,19 @@
package forge.game.ability.effects;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import com.google.common.collect.Lists;
import forge.game.Game;
import forge.game.ability.AbilityFactory;
import forge.game.ability.AbilityUtils;
import forge.game.ability.IllegalAbilityException;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.Card;
import forge.game.card.CardCollection;
@@ -17,8 +26,6 @@ import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.util.Aggregates;
import forge.util.FCollection;
import java.util.*;
import java.util.Map.Entry;
public class RepeatEachEffect extends SpellAbilityEffect {
@@ -63,6 +70,9 @@ public class RepeatEachEffect extends SpellAbilityEffect {
loopOverCards = true;
}
}
else {
throw new IllegalAbilityException(sa, this);
}
if (sa.hasParam("ClearRemembered")) {
source.clearRemembered();

View File

@@ -8,6 +8,7 @@ import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;
import com.google.common.base.Objects;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -23,6 +24,7 @@ import forge.game.zone.ZoneType;
import forge.trackable.TrackableCollection;
import forge.trackable.TrackableProperty;
import forge.trackable.Tracker;
import forge.util.FCollection;
import forge.util.FCollectionView;
import forge.util.Lang;
@@ -82,7 +84,7 @@ public class PlayerView extends GameEntityView {
}
public FCollectionView<PlayerView> getOpponents() {
return get(TrackableProperty.Opponents);
return Objects.firstNonNull(this.<FCollectionView<PlayerView>>get(TrackableProperty.Opponents), new FCollection<PlayerView>());
}
void updateOpponents(Player p) {
set(TrackableProperty.Opponents, PlayerView.getCollection(p.getOpponents()));
@@ -123,7 +125,7 @@ public class PlayerView extends GameEntityView {
final FCollectionView<PlayerView> opponents = getOpponents();
final List<String> info = Lists.newArrayListWithExpectedSize(opponents.size());
info.add(String.format("Commander: %s", commander));
for (final PlayerView p : Iterables.concat(Collections.singleton(this), opponents == null ? Collections.<PlayerView>emptySet() : opponents)) {
for (final PlayerView p : Iterables.concat(Collections.singleton(this), opponents)) {
final int damage = this.getCommanderDamage(p.getCommander());
if (damage > 0) {
final String text;

View File

@@ -103,7 +103,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
private int totalManaSpent = 0;
/** The pay costs. */
private Cost payCosts = null;
private Cost payCosts;
private SpellAbilityRestriction restrictions = new SpellAbilityRestriction();
private SpellAbilityCondition conditions = new SpellAbilityCondition();
private AbilitySub subAbility = null;