more refactor, add MultiFilterImpl

This commit is contained in:
Susucre 2025-06-01 18:31:34 +02:00
parent 6e85b2e4ab
commit 19b8a80ab5
15 changed files with 208 additions and 210 deletions

View file

@ -10,7 +10,6 @@ import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration; import mage.constants.Duration;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterSpellOrPermanent; import mage.filter.common.FilterSpellOrPermanent;
import mage.target.common.TargetCreatureOrPlaneswalker; import mage.target.common.TargetCreatureOrPlaneswalker;
import mage.target.common.TargetSpellOrPermanent; import mage.target.common.TargetSpellOrPermanent;
@ -26,7 +25,7 @@ public final class BrutalExpulsion extends CardImpl {
private static final FilterSpellOrPermanent filter = new FilterSpellOrPermanent("spell or creature"); private static final FilterSpellOrPermanent filter = new FilterSpellOrPermanent("spell or creature");
static { static {
filter.setPermanentFilter(new FilterCreaturePermanent()); filter.getPermanentFilter().add(CardType.CREATURE.getPredicate());
} }
public BrutalExpulsion(UUID ownerId, CardSetInfo setInfo) { public BrutalExpulsion(UUID ownerId, CardSetInfo setInfo) {

View file

@ -1,7 +1,6 @@
package mage.cards.c; package mage.cards.c;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.Effect; import mage.abilities.effects.Effect;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
@ -13,16 +12,17 @@ import mage.cards.SplitCard;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.constants.SpellAbilityType; import mage.constants.SpellAbilityType;
import mage.filter.common.FilterNonlandPermanent;
import mage.filter.common.FilterSpellOrPermanent; import mage.filter.common.FilterSpellOrPermanent;
import mage.filter.predicate.Predicates;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.game.stack.Spell; import mage.game.stack.Spell;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetSpellOrPermanent; import mage.target.common.TargetSpellOrPermanent;
import java.util.UUID;
/** /**
*
* @author fireshoes * @author fireshoes
*/ */
public final class CommitMemory extends SplitCard { public final class CommitMemory extends SplitCard {
@ -30,7 +30,7 @@ public final class CommitMemory extends SplitCard {
private static final FilterSpellOrPermanent filter = new FilterSpellOrPermanent("spell or nonland permanent"); private static final FilterSpellOrPermanent filter = new FilterSpellOrPermanent("spell or nonland permanent");
static { static {
filter.setPermanentFilter(new FilterNonlandPermanent()); filter.getPermanentFilter().add(Predicates.not(CardType.LAND.getPredicate()));
} }
public CommitMemory(UUID ownerId, CardSetInfo setInfo) { public CommitMemory(UUID ownerId, CardSetInfo setInfo) {

View file

@ -1,17 +1,16 @@
package mage.cards.u; package mage.cards.u;
import java.util.UUID;
import mage.abilities.effects.common.ReturnToHandTargetEffect; import mage.abilities.effects.common.ReturnToHandTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.filter.common.FilterCreaturePermanent;
import mage.filter.common.FilterSpellOrPermanent; import mage.filter.common.FilterSpellOrPermanent;
import mage.target.common.TargetSpellOrPermanent; import mage.target.common.TargetSpellOrPermanent;
import java.util.UUID;
/** /**
*
* @author fireshoes * @author fireshoes
*/ */
public final class Unsubstantiate extends CardImpl { public final class Unsubstantiate extends CardImpl {
@ -19,11 +18,11 @@ public final class Unsubstantiate extends CardImpl {
private static final FilterSpellOrPermanent filter = new FilterSpellOrPermanent("spell or creature"); private static final FilterSpellOrPermanent filter = new FilterSpellOrPermanent("spell or creature");
static { static {
filter.setPermanentFilter(new FilterCreaturePermanent()); filter.getPermanentFilter().add(CardType.CREATURE.getPredicate());
} }
public Unsubstantiate(UUID ownerId, CardSetInfo setInfo) { public Unsubstantiate(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{U}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{U}");
// Return target spell or creature to its owner's hand. // Return target spell or creature to its owner's hand.
this.getSpellAbility().addTarget(new TargetSpellOrPermanent(1, 1, filter, false)); this.getSpellAbility().addTarget(new TargetSpellOrPermanent(1, 1, filter, false));

View file

@ -28,6 +28,20 @@ public interface Filter<E> extends Serializable, Copyable<Filter<E>> {
Filter<E> add(Predicate<? super E> predicate); Filter<E> add(Predicate<? super E> predicate);
/**
* Make sure on setting a new Filter that you overwrite this method
* and call Predicates.makeSurePredicateCompatibleWithFilter
* to check that the filter is able to process objects
* of the right kind. Helps with checks the Compiler can't do
* due to ObjectSourcePlayer casting in the this.match(4 arguments).
* <p>
* (method should then call this.addExtra(predicate) after verify checks)
*/
void add(ObjectSourcePlayerPredicate predicate);
// TODO: if someone can find a way to not have to add this (overload of add made it necessary to introduce)
void addExtra(ObjectSourcePlayerPredicate predicate);
boolean checkObjectClass(Object object); boolean checkObjectClass(Object object);
String getMessage(); String getMessage();
@ -36,9 +50,9 @@ public interface Filter<E> extends Serializable, Copyable<Filter<E>> {
Filter<E> copy(); Filter<E> copy();
public boolean isLockedFilter(); boolean isLockedFilter();
public void setLockedFilter(boolean lockedFilter); void setLockedFilter(boolean lockedFilter);
List<Predicate<? super E>> getPredicates(); List<Predicate<? super E>> getPredicates();

View file

@ -4,11 +4,13 @@ package mage.filter;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.constants.AbilityType; import mage.constants.AbilityType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.filter.predicate.Predicate; import mage.filter.predicate.Predicate;
import mage.filter.predicate.Predicates;
import mage.game.Game; import mage.game.Game;
import mage.game.stack.StackObject;
/** /**
*
* @author North * @author North
*/ */
public class FilterAbility extends FilterImpl<Ability> { public class FilterAbility extends FilterImpl<Ability> {
@ -38,6 +40,18 @@ public class FilterAbility extends FilterImpl<Ability> {
return new AbilityTypePredicate(type); return new AbilityTypePredicate(type);
} }
@Override
public Filter<Ability> add(Predicate<? super Ability> predicate) {
return super.add(predicate);
}
@Override
public void add(ObjectSourcePlayerPredicate predicate) {
// Verify Checks
Predicates.makeSurePredicateCompatibleWithFilter(predicate, Ability.class, StackObject.class);
this.addExtra(predicate);
}
@Override @Override
public boolean checkObjectClass(Object object) { public boolean checkObjectClass(Object object) {
return object instanceof Ability; return object instanceof Ability;

View file

@ -63,18 +63,8 @@ public abstract class FilterImpl<E> implements Filter<E> {
return this; return this;
} }
/** @Override
* Make sure on setting a new Filter that you overwrite this method public final void addExtra(ObjectSourcePlayerPredicate predicate) {
* and call Predicates.makeSurePredicateCompatibleWithFilter
* to check that the filter is able to process objects
* of the right kind. Helps with checks the Compiler can't do
* due to ObjectSourcePlayer casting in the this.match(4 arguments).
*/
public void add(ObjectSourcePlayerPredicate predicate) {
addExtra(predicate);
}
public void addExtra(ObjectSourcePlayerPredicate predicate) {
if (isLockedFilter()) { if (isLockedFilter()) {
throw new UnsupportedOperationException("You may not modify a locked filter"); throw new UnsupportedOperationException("You may not modify a locked filter");
} }

View file

@ -1,6 +1,7 @@
package mage.filter; package mage.filter;
import mage.cards.Card;
import mage.game.stack.Spell; import mage.game.stack.Spell;
/** /**
@ -22,7 +23,8 @@ public class FilterSpell extends FilterStackObject {
@Override @Override
public boolean checkObjectClass(Object object) { public boolean checkObjectClass(Object object) {
return object instanceof Spell; return object instanceof Spell
|| object instanceof Card; // TODO: investigate. Is sometimes used for checking a spell's characteristic before cast
} }
@Override @Override

View file

@ -38,6 +38,7 @@ public class FilterStackObject extends FilterObject<StackObject> {
@Override @Override
public boolean checkObjectClass(Object object) { public boolean checkObjectClass(Object object) {
return object instanceof StackObject; return object instanceof StackObject
|| object instanceof Card; // TODO: investigate. Is sometimes used for checking a spell's characteristic before cast
} }
} }

View file

@ -0,0 +1,122 @@
package mage.filter;
import mage.abilities.Ability;
import mage.filter.predicate.ObjectSourcePlayerPredicate;
import mage.filter.predicate.Predicate;
import mage.game.Game;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* Make a Filter out of multiple inner filters.
*
* @author Susucr
*/
public abstract class MultiFilterImpl<E> implements Filter<E> {
protected List<Filter<? extends E>> innerFilters = new ArrayList<>();
private String message;
@Override
public abstract MultiFilterImpl<E> copy();
protected MultiFilterImpl(String name, Filter<? extends E>... filters) {
this.message = name;
this.innerFilters.addAll(Arrays.stream(filters).collect(Collectors.toList()));
}
protected MultiFilterImpl(final MultiFilterImpl<E> filter) {
this.message = filter.message;
for (Filter<? extends E> innerFilter : filter.innerFilters) {
this.innerFilters.add(innerFilter.copy());
}
}
@Override
public boolean match(E object, Game game) {
return innerFilters
.stream()
.anyMatch((Filter filter) -> filter.match(object, game));
}
public boolean match(E object, UUID sourceControllerId, Ability source, Game game) {
return innerFilters
.stream()
.anyMatch((Filter filter) -> filter.match(object, sourceControllerId, source, game));
}
@Override
public Filter<E> add(Predicate<? super E> predicate) {
innerFilters.forEach((Filter filter) -> filter.add(predicate));
return this;
}
@Override
public void add(ObjectSourcePlayerPredicate predicate) {
innerFilters.forEach((Filter filter) -> filter.add(predicate));
}
@Override
public void addExtra(ObjectSourcePlayerPredicate predicate) {
innerFilters.forEach((Filter filter) -> filter.addExtra(predicate));
}
@Override
public boolean checkObjectClass(Object object) {
return innerFilters
.stream()
.anyMatch((Filter filter) -> filter.checkObjectClass(object));
}
@Override
public String getMessage() {
return message;
}
@Override
public final void setMessage(String message) {
if (isLockedFilter()) {
throw new UnsupportedOperationException("You may not modify a locked filter");
}
this.message = message;
}
@Override
public String toString() {
return message;
}
@Override
public boolean isLockedFilter() {
return innerFilters.stream().anyMatch((Filter filter) -> filter.isLockedFilter());
}
@Override
public void setLockedFilter(boolean lockedFilter) {
innerFilters.forEach((Filter filter) -> filter.setLockedFilter(lockedFilter));
}
public List<Predicate<? super E>> getPredicates() {
List<Predicate<? super E>> predicates = new ArrayList<>();
for (Filter<? extends E> filter : innerFilters) {
for (Predicate predicate : filter.getPredicates()) {
predicates.add(predicate);
}
}
return predicates;
}
public List<ObjectSourcePlayerPredicate<E>> getExtraPredicates() {
List<ObjectSourcePlayerPredicate<E>> predicates = new ArrayList<>();
for (Filter<? extends E> filter : innerFilters) {
for (ObjectSourcePlayerPredicate predicate : filter.getExtraPredicates()) {
predicates.add(predicate);
}
}
return predicates;
}
}

View file

@ -14,7 +14,7 @@ public class FilterAnyTarget extends FilterPermanentOrPlayer {
public FilterAnyTarget(String name) { public FilterAnyTarget(String name) {
super(name); super(name);
this.permanentFilter.add(Predicates.or( this.getPermanentFilter().add(Predicates.or(
CardType.CREATURE.getPredicate(), CardType.CREATURE.getPredicate(),
CardType.PLANESWALKER.getPredicate(), CardType.PLANESWALKER.getPredicate(),
CardType.BATTLE.getPredicate() CardType.BATTLE.getPredicate()

View file

@ -16,7 +16,7 @@ public class FilterCreaturePlayerOrPlaneswalker extends FilterPermanentOrPlayer
public FilterCreaturePlayerOrPlaneswalker(String name) { public FilterCreaturePlayerOrPlaneswalker(String name) {
super(name); super(name);
this.permanentFilter.add(Predicates.or( this.getPermanentFilter().add(Predicates.or(
CardType.CREATURE.getPredicate(), CardType.CREATURE.getPredicate(),
CardType.PLANESWALKER.getPredicate() CardType.PLANESWALKER.getPredicate()
)); ));

View file

@ -3,7 +3,6 @@ package mage.filter.common;
import mage.constants.CardType; import mage.constants.CardType;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.filter.predicate.other.PlayerIdPredicate; import mage.filter.predicate.other.PlayerIdPredicate;
import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.filter.predicate.permanent.PermanentIdPredicate; import mage.filter.predicate.permanent.PermanentIdPredicate;
import java.util.Set; import java.util.Set;
@ -17,17 +16,17 @@ public class FilterDefender extends FilterPermanentOrPlayer {
public FilterDefender(Set<UUID> defenders) { public FilterDefender(Set<UUID> defenders) {
super("player, planeswalker, or battle to attack"); super("player, planeswalker, or battle to attack");
this.permanentFilter.add(Predicates.or( this.getPermanentFilter().add(Predicates.or(
CardType.PLANESWALKER.getPredicate(), CardType.PLANESWALKER.getPredicate(),
CardType.BATTLE.getPredicate() CardType.BATTLE.getPredicate()
)); ));
this.permanentFilter.add(Predicates.or( this.getPermanentFilter().add(Predicates.or(
defenders defenders
.stream() .stream()
.map(PermanentIdPredicate::new) .map(PermanentIdPredicate::new)
.collect(Collectors.toList()) .collect(Collectors.toList())
)); ));
this.playerFilter.add(Predicates.or( this.getPlayerFilter().add(Predicates.or(
defenders defenders
.stream() .stream()
.map(PlayerIdPredicate::new) .map(PlayerIdPredicate::new)

View file

@ -1,23 +1,14 @@
package mage.filter.common; package mage.filter.common;
import mage.MageItem; import mage.MageItem;
import mage.abilities.Ability;
import mage.filter.FilterImpl;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.FilterPlayer; import mage.filter.FilterPlayer;
import mage.game.Game; import mage.filter.MultiFilterImpl;
import mage.game.permanent.Permanent;
import mage.players.Player;
import java.util.UUID;
/** /**
* @author nantuko * @author nantuko
*/ */
public class FilterPermanentOrPlayer extends FilterImpl<MageItem> { public class FilterPermanentOrPlayer extends MultiFilterImpl<MageItem> {
protected final FilterPermanent permanentFilter;
protected final FilterPlayer playerFilter;
public FilterPermanentOrPlayer() { public FilterPermanentOrPlayer() {
this("player or permanent"); this("player or permanent");
@ -28,52 +19,11 @@ public class FilterPermanentOrPlayer extends FilterImpl<MageItem> {
} }
public FilterPermanentOrPlayer(String name, FilterPermanent permanentFilter, FilterPlayer playerFilter) { public FilterPermanentOrPlayer(String name, FilterPermanent permanentFilter, FilterPlayer playerFilter) {
super(name); super(name, permanentFilter, playerFilter);
this.permanentFilter = permanentFilter;
this.playerFilter = playerFilter;
} }
protected FilterPermanentOrPlayer(final FilterPermanentOrPlayer filter) { protected FilterPermanentOrPlayer(final FilterPermanentOrPlayer filter) {
super(filter); super(filter);
this.permanentFilter = filter.permanentFilter.copy();
this.playerFilter = filter.playerFilter.copy();
}
@Override
public boolean checkObjectClass(Object object) {
return true;
}
@Override
public boolean match(MageItem o, Game game) {
if (super.match(o, game)) {
if (o instanceof Player) {
return playerFilter.match((Player) o, game);
} else if (o instanceof Permanent) {
return permanentFilter.match((Permanent) o, game);
}
}
return false;
}
@Override
public boolean match(MageItem o, UUID playerId, Ability source, Game game) {
if (super.match(o, game)) { // process predicates
if (o instanceof Player) {
return playerFilter.match((Player) o, playerId, source, game);
} else if (o instanceof Permanent) {
return permanentFilter.match((Permanent) o, playerId, source, game);
}
}
return false;
}
public FilterPermanent getPermanentFilter() {
return this.permanentFilter;
}
public FilterPlayer getPlayerFilter() {
return this.playerFilter;
} }
@Override @Override
@ -81,4 +31,12 @@ public class FilterPermanentOrPlayer extends FilterImpl<MageItem> {
return new FilterPermanentOrPlayer(this); return new FilterPermanentOrPlayer(this);
} }
public FilterPermanent getPermanentFilter() {
return (FilterPermanent) this.innerFilters.get(0);
}
public FilterPlayer getPlayerFilter() {
return (FilterPlayer) this.innerFilters.get(1);
}
} }

View file

@ -1,88 +1,42 @@
package mage.filter.common; package mage.filter.common;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.keyword.SuspendAbility; import mage.abilities.keyword.SuspendAbility;
import mage.cards.Card;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.FilterCard; import mage.filter.FilterCard;
import mage.filter.FilterImpl;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.MultiFilterImpl;
import mage.filter.predicate.mageobject.AbilityPredicate; import mage.filter.predicate.mageobject.AbilityPredicate;
import mage.game.Game;
import mage.game.permanent.Permanent;
import java.util.UUID;
/** /**
* @author emerald000 * @author emerald000
*/ */
public class FilterPermanentOrSuspendedCard extends FilterImpl<MageObject> { public class FilterPermanentOrSuspendedCard extends MultiFilterImpl<MageObject> {
protected FilterCard cardFilter;
protected FilterPermanent permanentFilter;
public FilterPermanentOrSuspendedCard() { public FilterPermanentOrSuspendedCard() {
this("permanent or suspended card"); this("permanent or suspended card");
} }
public FilterPermanentOrSuspendedCard(String name) { public FilterPermanentOrSuspendedCard(String name) {
super(name); super(name, new FilterPermanent(), new FilterCard());
permanentFilter = new FilterPermanent(); this.getCardFilter().add(new AbilityPredicate(SuspendAbility.class));
cardFilter = new FilterCard(); this.getCardFilter().add(CounterType.TIME.getPredicate());
cardFilter.add(new AbilityPredicate(SuspendAbility.class));
cardFilter.add(CounterType.TIME.getPredicate());
} }
protected FilterPermanentOrSuspendedCard(final FilterPermanentOrSuspendedCard filter) { protected FilterPermanentOrSuspendedCard(final FilterPermanentOrSuspendedCard filter) {
super(filter); super(filter);
this.permanentFilter = filter.permanentFilter.copy();
this.cardFilter = filter.cardFilter.copy();
}
@Override
public boolean checkObjectClass(Object object) {
return object instanceof MageObject;
}
@Override
public boolean match(MageObject o, Game game) {
if (o instanceof Permanent) {
return permanentFilter.match((Permanent) o, game);
} else if (o instanceof Card) {
return cardFilter.match((Card) o, game);
}
return false;
}
@Override
public boolean match(MageObject o, UUID playerId, Ability source, Game game) {
if (o instanceof Permanent) {
return permanentFilter.match((Permanent) o, playerId, source, game);
} else if (o instanceof Card) {
return cardFilter.match((Card) o, playerId, source, game);
}
return false;
}
public FilterPermanent getPermanentFilter() {
return this.permanentFilter;
}
public FilterCard getCardFilter() {
return this.cardFilter;
}
public void setPermanentFilter(FilterPermanent permanentFilter) {
this.permanentFilter = permanentFilter;
}
public void setCardFilter(FilterCard cardFilter) {
this.cardFilter = cardFilter;
} }
@Override @Override
public FilterPermanentOrSuspendedCard copy() { public FilterPermanentOrSuspendedCard copy() {
return new FilterPermanentOrSuspendedCard(this); return new FilterPermanentOrSuspendedCard(this);
} }
public FilterPermanent getPermanentFilter() {
return (FilterPermanent) this.innerFilters.get(0);
}
public FilterCard getCardFilter() {
return (FilterCard) this.innerFilters.get(1);
}
} }

View file

@ -1,86 +1,25 @@
package mage.filter.common; package mage.filter.common;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.filter.FilterImpl;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
import mage.filter.FilterSpell; import mage.filter.FilterSpell;
import mage.game.Game; import mage.filter.MultiFilterImpl;
import mage.game.permanent.Permanent;
import mage.game.stack.Spell;
import java.util.UUID;
/** /**
* @author LevelX * @author LevelX
*/ */
public class FilterSpellOrPermanent extends FilterImpl<MageObject> { public class FilterSpellOrPermanent extends MultiFilterImpl<MageObject> {
protected FilterPermanent permanentFilter;
protected FilterSpell spellFilter;
public FilterSpellOrPermanent() { public FilterSpellOrPermanent() {
this("spell or permanent"); this("spell or permanent");
} }
public FilterSpellOrPermanent(String name) { public FilterSpellOrPermanent(String name) {
super(name); super(name, new FilterPermanent(), new FilterSpell());
permanentFilter = new FilterPermanent();
spellFilter = new FilterSpell();
} }
protected FilterSpellOrPermanent(final FilterSpellOrPermanent filter) { protected FilterSpellOrPermanent(final FilterSpellOrPermanent filter) {
super(filter); super(filter);
this.permanentFilter = filter.permanentFilter.copy();
this.spellFilter = filter.spellFilter.copy();
}
@Override
public boolean checkObjectClass(Object object) {
return object instanceof MageObject;
}
@Override
public boolean match(MageObject o, Game game) {
if (o instanceof Spell) {
return spellFilter.match((Spell) o, game);
} else if (o instanceof Permanent) {
return permanentFilter.match((Permanent) o, game);
}
return false;
}
@Override
public boolean match(MageObject o, UUID playerId, Ability source, Game game) {
if (o instanceof Spell) {
return spellFilter.match((Spell) o, playerId, source, game);
} else if (o instanceof Permanent) {
return permanentFilter.match((Permanent) o, playerId, source, game);
}
return false;
}
@Override
public void setLockedFilter(boolean lockedFilter) {
super.setLockedFilter(lockedFilter);
spellFilter.setLockedFilter(lockedFilter);
permanentFilter.setLockedFilter(lockedFilter);
}
public FilterPermanent getPermanentFilter() {
return this.permanentFilter;
}
public FilterSpell getSpellFilter() {
return this.spellFilter;
}
public void setPermanentFilter(FilterPermanent permanentFilter) {
this.permanentFilter = permanentFilter;
}
public void setSpellFilter(FilterSpell spellFilter) {
this.spellFilter = spellFilter;
} }
@Override @Override
@ -88,4 +27,11 @@ public class FilterSpellOrPermanent extends FilterImpl<MageObject> {
return new FilterSpellOrPermanent(this); return new FilterSpellOrPermanent(this);
} }
public FilterPermanent getPermanentFilter() {
return (FilterPermanent) this.innerFilters.get(0);
}
public FilterSpell getSpellFilter() {
return (FilterSpell) this.innerFilters.get(1);
}
} }