-
Notifications
You must be signed in to change notification settings - Fork 834
Refactor: clean filter logic #13713
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Refactor: clean filter logic #13713
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,11 +4,13 @@ | |
import mage.abilities.Ability; | ||
import mage.constants.AbilityType; | ||
import mage.constants.Zone; | ||
import mage.filter.predicate.ObjectSourcePlayerPredicate; | ||
import mage.filter.predicate.Predicate; | ||
import mage.filter.predicate.Predicates; | ||
import mage.game.Game; | ||
import mage.game.stack.StackObject; | ||
|
||
/** | ||
* | ||
* @author North | ||
*/ | ||
public class FilterAbility extends FilterImpl<Ability> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The existence of this class doesn't really make any sense. It appears to only be used inside TargetActivatedAbility, and never with any parameters. Maybe a separate refactor, but I think it should be removed entirely, and the one usage can return a FilterStackObject instead |
||
|
@@ -38,6 +40,14 @@ public static Predicate<Ability> type(AbilityType type) { | |
return new AbilityTypePredicate(type); | ||
} | ||
|
||
@Override | ||
public FilterAbility add(ObjectSourcePlayerPredicate predicate) { | ||
// Verify Checks | ||
Predicates.makeSurePredicateCompatibleWithFilter(predicate, Ability.class, StackObject.class); | ||
this.addExtra(predicate); | ||
return this; | ||
} | ||
|
||
@Override | ||
public boolean checkObjectClass(Object object) { | ||
return object instanceof Ability; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,13 @@ | ||
package mage.filter; | ||
|
||
import mage.abilities.Ability; | ||
import mage.cards.Card; | ||
import mage.constants.TargetController; | ||
import mage.filter.predicate.ObjectSourcePlayer; | ||
import mage.filter.predicate.ObjectSourcePlayerPredicate; | ||
import mage.filter.predicate.Predicate; | ||
import mage.filter.predicate.Predicates; | ||
import mage.game.Game; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
/** | ||
* Works with cards only. For objects like commanders you must override your canTarget method. | ||
|
@@ -22,7 +18,6 @@ | |
public class FilterCard extends FilterObject<Card> { | ||
|
||
private static final long serialVersionUID = 1L; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand why this serialVersionUID is here at all. Only FilterCard has it |
||
protected final List<ObjectSourcePlayerPredicate<Card>> extraPredicates = new ArrayList<>(); | ||
|
||
public FilterCard() { | ||
super("card"); | ||
|
@@ -34,71 +29,42 @@ public FilterCard(String name) { | |
|
||
protected FilterCard(final FilterCard filter) { | ||
super(filter); | ||
this.extraPredicates.addAll(filter.extraPredicates); | ||
} | ||
|
||
//20130711 708.6c | ||
/* If anything performs a comparison involving multiple characteristics or | ||
* values of one or more split cards in any zone other than the stack or | ||
* involving multiple characteristics or values of one or more fused split | ||
* spells, each characteristic or value is compared separately. If each of | ||
* the individual comparisons would return a “yes” answer, the whole | ||
* comparison returns a “yes” answer. The individual comparisons may involve | ||
* different halves of the same split card. | ||
*/ | ||
@Override | ||
public boolean match(Card card, Game game) { | ||
if (card == null) { | ||
return false; | ||
} | ||
return super.match(card, game); | ||
} | ||
|
||
public boolean match(Card card, UUID playerId, Ability source, Game game) { | ||
if (!this.match(card, game)) { | ||
return false; | ||
} | ||
ObjectSourcePlayer<Card> osp = new ObjectSourcePlayer<>(card, playerId, source); | ||
return extraPredicates.stream().allMatch(p -> p.apply(osp, game)); | ||
} | ||
|
||
public final void add(ObjectSourcePlayerPredicate predicate) { | ||
if (isLockedFilter()) { | ||
throw new UnsupportedOperationException("You may not modify a locked filter"); | ||
} | ||
|
||
// verify check | ||
checkPredicateIsSuitableForCardFilter(predicate); | ||
Predicates.makeSurePredicateCompatibleWithFilter(predicate, Card.class); | ||
|
||
extraPredicates.add(predicate); | ||
} | ||
|
||
public boolean hasPredicates() { | ||
return !predicates.isEmpty() || !extraPredicates.isEmpty(); | ||
} | ||
|
||
@Override | ||
public FilterCard copy() { | ||
return new FilterCard(this); | ||
} | ||
|
||
@Override | ||
public List<Predicate> getExtraPredicates() { | ||
return new ArrayList<>(extraPredicates); | ||
} | ||
|
||
public static void checkPredicateIsSuitableForCardFilter(Predicate predicate) { | ||
// card filter can't contain controller predicate (only permanents on battlefield have controller) | ||
// card filter can't contain controller predicate (only permanents on battlefield and StackObjects have controller) | ||
List<Predicate> list = new ArrayList<>(); | ||
Predicates.collectAllComponents(predicate, list); | ||
if (list.stream().anyMatch(TargetController.ControllerPredicate.class::isInstance)) { | ||
throw new IllegalArgumentException("Wrong code usage: card filter doesn't support controller predicate"); | ||
} | ||
} | ||
|
||
|
||
public FilterCard withMessage(String message) { | ||
this.setMessage(message); | ||
return this; | ||
} | ||
|
||
@Override | ||
public FilterCard add(ObjectSourcePlayerPredicate predicate) { | ||
// verify checks | ||
checkPredicateIsSuitableForCardFilter(predicate); | ||
Predicates.makeSurePredicateCompatibleWithFilter(predicate, Card.class); | ||
this.addExtra(predicate); | ||
return this; | ||
} | ||
|
||
@Override | ||
public boolean checkObjectClass(Object object) { | ||
// TODO: investigate if we can/should exclude Permanent here. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I vaguely recall that FilterCard is sometimes used for Spells. It's possible that it's (mis)used somewhere for Permanents as well, but I'm not really sure how to investigate |
||
// as it does extend Card (if so do cleanup the | ||
// MultiFilterImpl that match Permanent and Card/Spell) | ||
return object instanceof Card; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,15 @@ | ||
package mage.filter; | ||
|
||
import mage.abilities.Ability; | ||
import mage.filter.predicate.ObjectSourcePlayer; | ||
import mage.filter.predicate.ObjectSourcePlayerPredicate; | ||
import mage.filter.predicate.Predicate; | ||
import mage.filter.predicate.Predicates; | ||
import mage.game.Game; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
/** | ||
* @param <E> | ||
|
@@ -14,7 +18,8 @@ | |
*/ | ||
public abstract class FilterImpl<E> implements Filter<E> { | ||
|
||
protected List<Predicate<? super E>> predicates = new ArrayList<>(); | ||
private List<Predicate<? super E>> predicates = new ArrayList<>(); | ||
private List<ObjectSourcePlayerPredicate<E>> extraPredicates = new ArrayList<>(); | ||
protected String message; | ||
protected boolean lockedFilter; // Helps to prevent "accidentally" modifying the StaticFilters objects | ||
|
||
|
@@ -29,6 +34,7 @@ public FilterImpl(String name) { | |
protected FilterImpl(final FilterImpl<E> filter) { | ||
this.message = filter.message; | ||
this.predicates = new ArrayList<>(filter.predicates); | ||
this.extraPredicates = new ArrayList<>(filter.extraPredicates); | ||
this.lockedFilter = false;// After copying a filter it's allowed to modify | ||
xenohedron marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
|
@@ -41,25 +47,42 @@ public boolean match(E e, Game game) { | |
} | ||
|
||
@Override | ||
public final Filter<E> add(Predicate<? super E> predicate) { | ||
if (isLockedFilter()) { | ||
throw new UnsupportedOperationException("You may not modify a locked filter"); | ||
public boolean match(E object, UUID sourceControllerId, Ability source, Game game) { | ||
if (!this.match(object, game)) { | ||
return false; | ||
} | ||
ObjectSourcePlayer osp = new ObjectSourcePlayer<>(object, sourceControllerId, source); | ||
return extraPredicates.stream().allMatch(p -> p.apply(osp, game)); | ||
} | ||
|
||
@Override | ||
public Filter<E> add(Predicate<? super E> predicate) { | ||
checkUnlockedFilter(); | ||
predicates.add(predicate); | ||
return this; | ||
} | ||
|
||
@Override | ||
public final void addExtra(ObjectSourcePlayerPredicate predicate) { | ||
xenohedron marked this conversation as resolved.
Show resolved
Hide resolved
|
||
checkUnlockedFilter(); | ||
extraPredicates.add(predicate); | ||
} | ||
|
||
@Override | ||
public String getMessage() { | ||
return message; | ||
} | ||
|
||
@Override | ||
public final void setMessage(String message) { | ||
checkUnlockedFilter(); | ||
this.message = message; | ||
} | ||
|
||
protected void checkUnlockedFilter() { | ||
if (isLockedFilter()) { | ||
throw new UnsupportedOperationException("You may not modify a locked filter"); | ||
} | ||
this.message = message; | ||
} | ||
|
||
@Override | ||
|
@@ -80,4 +103,12 @@ public void setLockedFilter(boolean lockedFilter) { | |
public List<Predicate<? super E>> getPredicates() { | ||
return predicates; | ||
} | ||
|
||
public List<ObjectSourcePlayerPredicate<E>> getExtraPredicates() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remember to add |
||
return new ArrayList<>(extraPredicates); | ||
} | ||
|
||
public boolean hasPredicates() { | ||
return !predicates.isEmpty() || !extraPredicates.isEmpty(); | ||
} | ||
} |
Uh oh!
There was an error while loading. Please reload this page.