Merge pull request #3688 from ingmargoudt/master

talk to interfaces rather than implementations
This commit is contained in:
ingmargoudt 2017-07-16 11:08:40 +02:00 committed by GitHub
commit a3af890c02
32 changed files with 259 additions and 299 deletions

View file

@ -27,10 +27,6 @@
*/ */
package mage.server; package mage.server;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import mage.cards.repository.CardInfo; import mage.cards.repository.CardInfo;
import mage.cards.repository.CardRepository; import mage.cards.repository.CardRepository;
import mage.server.exceptions.UserNotFoundException; import mage.server.exceptions.UserNotFoundException;
@ -40,6 +36,11 @@ import mage.view.ChatMessage.MessageType;
import mage.view.ChatMessage.SoundToPlay; import mage.view.ChatMessage.SoundToPlay;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -290,7 +291,7 @@ public enum ChatManager {
} }
} }
public ArrayList<ChatSession> getChatSessions() { public List<ChatSession> getChatSessions() {
return new ArrayList<>(chatSessions.values()); return new ArrayList<>(chatSessions.values());
} }

View file

@ -36,10 +36,7 @@ import mage.view.ChatMessage.SoundToPlay;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.text.DateFormat; import java.text.DateFormat;
import java.util.Date; import java.util.*;
import java.util.HashSet;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
@ -119,7 +116,7 @@ public class ChatSession {
public void broadcast(String userName, String message, MessageColor color, boolean withTime, MessageType messageType, SoundToPlay soundToPlay) { public void broadcast(String userName, String message, MessageColor color, boolean withTime, MessageType messageType, SoundToPlay soundToPlay) {
if (!message.isEmpty()) { if (!message.isEmpty()) {
HashSet<UUID> clientsToRemove = new HashSet<>(); Set<UUID> clientsToRemove = new HashSet<>();
ClientCallback clientCallback = new ClientCallback(ClientCallbackMethod.CHATMESSAGE, chatId, new ChatMessage(userName, message, (withTime ? timeFormatter.format(new Date()) : ""), color, messageType, soundToPlay)); ClientCallback clientCallback = new ClientCallback(ClientCallbackMethod.CHATMESSAGE, chatId, new ChatMessage(userName, message, (withTime ? timeFormatter.format(new Date()) : ""), color, messageType, soundToPlay));
for (UUID userId : clients.keySet()) { for (UUID userId : clients.keySet()) {
Optional<User> user = UserManager.instance.getUser(userId); Optional<User> user = UserManager.instance.getUser(userId);

View file

@ -369,7 +369,7 @@ public enum TableManager {
+ " | " + sessionState + " | " + sessionState
+ " | " + user.getName() + " (" + user.getUserState().toString() + " - " + user.getPingInfo() + ')'); + " | " + user.getName() + " (" + user.getUserState().toString() + " - " + user.getPingInfo() + ')');
} }
ArrayList<ChatSession> chatSessions = ChatManager.instance.getChatSessions(); List<ChatSession> chatSessions = ChatManager.instance.getChatSessions();
logger.debug("------- ChatSessions: " + chatSessions.size() + " ----------------------------------"); logger.debug("------- ChatSessions: " + chatSessions.size() + " ----------------------------------");
for (ChatSession chatSession : chatSessions) { for (ChatSession chatSession : chatSessions) {
logger.debug(chatSession.getChatId() + " " + formatter.format(chatSession.getCreateTime()) + ' ' + chatSession.getInfo() + ' ' + chatSession.getClients().values().toString()); logger.debug(chatSession.getChatId() + " " + formatter.format(chatSession.getCreateTime()) + ' ' + chatSession.getInfo() + ' ' + chatSession.getClients().values().toString());
@ -387,7 +387,7 @@ public enum TableManager {
debugServerState(); debugServerState();
} }
logger.debug("TABLE HEALTH CHECK"); logger.debug("TABLE HEALTH CHECK");
ArrayList<Table> tableCopy = new ArrayList<>(tables.values()); List<Table> tableCopy = new ArrayList<>(tables.values());
for (Table table : tableCopy) { for (Table table : tableCopy) {
try { try {
if (table.getState() != TableState.FINISHED) { if (table.getState() != TableState.FINISHED) {

View file

@ -73,7 +73,7 @@ public class User {
private final String host; private final String host;
private final Date connectionTime; private final Date connectionTime;
private final Map<UUID, Table> tables; private final Map<UUID, Table> tables;
private final ArrayList<UUID> tablesToDelete; private final List<UUID> tablesToDelete;
private final Map<UUID, GameSessionPlayer> gameSessions; private final Map<UUID, GameSessionPlayer> gameSessions;
private final Map<UUID, DraftSession> draftSessions; private final Map<UUID, DraftSession> draftSessions;
private final Map<UUID, UUID> userTournaments; // playerId, tournamentId private final Map<UUID, UUID> userTournaments; // playerId, tournamentId

View file

@ -88,8 +88,8 @@ public class GamesRoomImpl extends RoomImpl implements GamesRoom, Serializable {
private void update() { private void update() {
List<Table> allTables = new ArrayList<>(tables.values()); List<Table> allTables = new ArrayList<>(tables.values());
allTables.sort(new TableListSorter()); allTables.sort(new TableListSorter());
ArrayList<MatchView> matchList = new ArrayList<>(); List<MatchView> matchList = new ArrayList<>();
ArrayList<TableView> tableList = new ArrayList<>(); List<TableView> tableList = new ArrayList<>();
for (Table table : allTables) { for (Table table : allTables) {
if (table.getState() != TableState.FINISHED) { if (table.getState() != TableState.FINISHED) {
tableList.add(new TableView(table)); tableList.add(new TableView(table));

View file

@ -18,6 +18,7 @@ import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
public enum UserStatsRepository { public enum UserStatsRepository {
@ -107,7 +108,7 @@ public enum UserStatsRepository {
// updateUserStats reads tables finished after the last DB update and reflects it to the DB. // updateUserStats reads tables finished after the last DB update and reflects it to the DB.
// It returns the list of user names that are upated. // It returns the list of user names that are upated.
public List<String> updateUserStats() { public List<String> updateUserStats() {
HashSet<String> updatedUsers = new HashSet<>(); Set<String> updatedUsers = new HashSet<>();
// Lock the DB so that no other updateUserStats runs at the same time. // Lock the DB so that no other updateUserStats runs at the same time.
synchronized(this) { synchronized(this) {
long latestEndTimeMs = this.getLatestEndTimeMs(); long latestEndTimeMs = this.getLatestEndTimeMs();

View file

@ -27,9 +27,6 @@
*/ */
package mage.cards.t; package mage.cards.t;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -49,6 +46,10 @@ import mage.game.Game;
import mage.game.combat.CombatGroup; import mage.game.combat.CombatGroup;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
/** /**
* *
* @author LevelX2 * @author LevelX2
@ -113,7 +114,7 @@ class CantBeBlockedUnlessAllEffect extends RestrictionEffect {
return false; return false;
} }
// check blocker restrictions // check blocker restrictions
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry: game.getContinuousEffects().getApplicableRestrictionEffects(permanent, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> entry: game.getContinuousEffects().getApplicableRestrictionEffects(permanent, game).entrySet()) {
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
if (!entry.getKey().canBlock(attacker, permanent, ability, game)) { if (!entry.getKey().canBlock(attacker, permanent, ability, game)) {
return false; return false;
@ -121,7 +122,7 @@ class CantBeBlockedUnlessAllEffect extends RestrictionEffect {
} }
} }
// check also attacker's restriction effects // check also attacker's restriction effects
for (Map.Entry<RestrictionEffect, HashSet<Ability>> restrictionEntry: game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> restrictionEntry: game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game).entrySet()) {
for (Ability ability : restrictionEntry.getValue()) { for (Ability ability : restrictionEntry.getValue()) {
if (!(restrictionEntry.getKey() instanceof CantBeBlockedUnlessAllEffect) if (!(restrictionEntry.getKey() instanceof CantBeBlockedUnlessAllEffect)
&& !restrictionEntry.getKey().canBeBlocked(attacker, permanent, ability, game)) { && !restrictionEntry.getKey().canBeBlocked(attacker, permanent, ability, game)) {

View file

@ -27,19 +27,9 @@
*/ */
package org.mage.test.player; package org.mage.test.player;
import java.io.Serializable;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import mage.MageObject; import mage.MageObject;
import mage.MageObjectReference; import mage.MageObjectReference;
import mage.abilities.Abilities; import mage.abilities.*;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.Mode;
import mage.abilities.Modes;
import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.costs.AlternativeSourceCosts; import mage.abilities.costs.AlternativeSourceCosts;
import mage.abilities.costs.Cost; import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs; import mage.abilities.costs.Costs;
@ -52,13 +42,7 @@ import mage.cards.Card;
import mage.cards.Cards; import mage.cards.Cards;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.choices.Choice; import mage.choices.Choice;
import mage.constants.AbilityType; import mage.constants.*;
import mage.constants.ManaType;
import mage.constants.Outcome;
import mage.constants.PhaseStep;
import mage.constants.RangeOfInfluence;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.counters.Counter; import mage.counters.Counter;
import mage.counters.Counters; import mage.counters.Counters;
import mage.filter.Filter; import mage.filter.Filter;
@ -83,22 +67,15 @@ import mage.players.Library;
import mage.players.ManaPool; import mage.players.ManaPool;
import mage.players.Player; import mage.players.Player;
import mage.players.net.UserData; import mage.players.net.UserData;
import mage.target.Target; import mage.target.*;
import mage.target.TargetAmount; import mage.target.common.*;
import mage.target.TargetCard;
import mage.target.TargetPermanent;
import mage.target.TargetPlayer;
import mage.target.TargetSource;
import mage.target.TargetSpell;
import mage.target.common.TargetCardInHand;
import mage.target.common.TargetCardInLibrary;
import mage.target.common.TargetCardInOpponentsGraveyard;
import mage.target.common.TargetCardInYourGraveyard;
import mage.target.common.TargetCreatureOrPlayer;
import mage.target.common.TargetCreaturePermanentAmount;
import mage.target.common.TargetPermanentOrPlayer;
import org.junit.Ignore; import org.junit.Ignore;
import java.io.Serializable;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
* @author Simown * @author Simown
@ -1329,7 +1306,7 @@ public class TestPlayer implements Player {
} }
@Override @Override
public int drawCards(int num, Game game, ArrayList<UUID> appliedEffects) { public int drawCards(int num, Game game, List<UUID> appliedEffects) {
return computerPlayer.drawCards(num, game, appliedEffects); return computerPlayer.drawCards(num, game, appliedEffects);
} }
@ -1619,7 +1596,7 @@ public class TestPlayer implements Player {
} }
@Override @Override
public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects) { public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects) {
return computerPlayer.damage(damage, sourceId, game, combatDamage, preventable, appliedEffects); return computerPlayer.damage(damage, sourceId, game, combatDamage, preventable, appliedEffects);
} }
@ -2284,7 +2261,7 @@ public class TestPlayer implements Player {
} }
@Override @Override
public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) { public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
return computerPlayer.moveCards(card, toZone, source, game, tapped, faceDown, byOwner, appliedEffects); return computerPlayer.moveCards(card, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
} }
@ -2299,7 +2276,7 @@ public class TestPlayer implements Player {
} }
@Override @Override
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) { public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
return computerPlayer.moveCards(cards, toZone, source, game, tapped, faceDown, byOwner, appliedEffects); return computerPlayer.moveCards(cards, toZone, source, game, tapped, faceDown, byOwner, appliedEffects);
} }

View file

@ -27,21 +27,8 @@
*/ */
package org.mage.test.stub; package org.mage.test.stub;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Abilities; import mage.abilities.*;
import mage.abilities.Ability;
import mage.abilities.ActivatedAbility;
import mage.abilities.Mode;
import mage.abilities.Modes;
import mage.abilities.SpellAbility;
import mage.abilities.TriggeredAbility;
import mage.abilities.costs.AlternativeSourceCosts; import mage.abilities.costs.AlternativeSourceCosts;
import mage.abilities.costs.Cost; import mage.abilities.costs.Cost;
import mage.abilities.costs.Costs; import mage.abilities.costs.Costs;
@ -53,12 +40,7 @@ import mage.cards.Card;
import mage.cards.Cards; import mage.cards.Cards;
import mage.cards.decks.Deck; import mage.cards.decks.Deck;
import mage.choices.Choice; import mage.choices.Choice;
import mage.constants.AbilityType; import mage.constants.*;
import mage.constants.ManaType;
import mage.constants.Outcome;
import mage.constants.PlayerAction;
import mage.constants.RangeOfInfluence;
import mage.constants.Zone;
import mage.counters.Counter; import mage.counters.Counter;
import mage.counters.Counters; import mage.counters.Counters;
import mage.filter.FilterPermanent; import mage.filter.FilterPermanent;
@ -80,6 +62,9 @@ import mage.target.TargetAmount;
import mage.target.TargetCard; import mage.target.TargetCard;
import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInLibrary;
import java.io.Serializable;
import java.util.*;
/** /**
* *
* @author Quercitron * @author Quercitron
@ -174,7 +159,7 @@ public class PlayerStub implements Player {
} }
@Override @Override
public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects) { public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects) {
return 0; return 0;
} }
@ -563,7 +548,7 @@ public class PlayerStub implements Player {
} }
@Override @Override
public int drawCards(int num, Game game, ArrayList<UUID> appliedEffects) { public int drawCards(int num, Game game, List<UUID> appliedEffects) {
return 0; return 0;
} }
@ -1098,7 +1083,7 @@ public class PlayerStub implements Player {
} }
@Override @Override
public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) { public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
return false; return false;
} }
@ -1113,7 +1098,7 @@ public class PlayerStub implements Player {
} }
@Override @Override
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) { public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
return false; return false;
} }

View file

@ -28,9 +28,6 @@
package mage.abilities.common; package mage.abilities.common;
import java.util.ArrayList;
import java.util.Set;
import mage.MageObject; import mage.MageObject;
import mage.abilities.ActivatedAbilityImpl; import mage.abilities.ActivatedAbilityImpl;
import mage.abilities.costs.common.PayLifeCost; import mage.abilities.costs.common.PayLifeCost;
@ -48,6 +45,10 @@ import mage.filter.predicate.mageobject.CardTypePredicate;
import mage.filter.predicate.mageobject.SubtypePredicate; import mage.filter.predicate.mageobject.SubtypePredicate;
import mage.target.common.TargetCardInLibrary; import mage.target.common.TargetCardInLibrary;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
@ -67,7 +68,7 @@ public class FetchLandActivatedAbility extends ActivatedAbilityImpl {
addCost(new SacrificeSourceCost()); addCost(new SacrificeSourceCost());
FilterCard filter = new FilterCard(subTypeNames(subtypes)); FilterCard filter = new FilterCard(subTypeNames(subtypes));
filter.add(new CardTypePredicate(CardType.LAND)); filter.add(new CardTypePredicate(CardType.LAND));
ArrayList<Predicate<MageObject>> subtypePredicates = new ArrayList<>(); List<Predicate<MageObject>> subtypePredicates = new ArrayList<>();
for (SubType subtype : subtypes) { for (SubType subtype : subtypes) {
subtypePredicates.add(new SubtypePredicate(subtype)); subtypePredicates.add(new SubtypePredicate(subtype));
} }

View file

@ -27,13 +27,15 @@
*/ */
package mage.abilities.condition.common; package mage.abilities.condition.common;
import java.util.ArrayList;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.condition.Condition; import mage.abilities.condition.Condition;
import mage.abilities.keyword.SurgeAbility; import mage.abilities.keyword.SurgeAbility;
import mage.constants.AbilityType; import mage.constants.AbilityType;
import mage.game.Game; import mage.game.Game;
import java.util.ArrayList;
import java.util.List;
/** /**
* *
* @author LevelX2 * @author LevelX2
@ -46,7 +48,7 @@ public enum SurgedCondition implements Condition {
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
if (source.getAbilityType() == AbilityType.TRIGGERED) { if (source.getAbilityType() == AbilityType.TRIGGERED) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
ArrayList<Integer> surgeActivations = (ArrayList) game.getState().getValue(SurgeAbility.SURGE_ACTIVATION_VALUE_KEY + source.getSourceId()); List<Integer> surgeActivations = (ArrayList) game.getState().getValue(SurgeAbility.SURGE_ACTIVATION_VALUE_KEY + source.getSourceId());
if (surgeActivations != null) { if (surgeActivations != null) {
return surgeActivations.contains(game.getState().getZoneChangeCounter(source.getSourceId()) - 1); return surgeActivations.contains(game.getState().getZoneChangeCounter(source.getSourceId()) - 1);
} }

View file

@ -27,11 +27,6 @@
*/ */
package mage.abilities.effects; package mage.abilities.effects;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import mage.MageObject; import mage.MageObject;
import mage.abilities.*; import mage.abilities.*;
import mage.abilities.keyword.SpliceOntoArcaneAbility; import mage.abilities.keyword.SpliceOntoArcaneAbility;
@ -54,6 +49,11 @@ import mage.players.Player;
import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInHand;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -192,7 +192,7 @@ public class ContinuousEffects implements Serializable {
case WhileOnBattlefield: case WhileOnBattlefield:
case WhileOnStack: case WhileOnStack:
case WhileInGraveyard: case WhileInGraveyard:
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
if (!abilities.isEmpty()) { if (!abilities.isEmpty()) {
for (Ability ability : abilities) { for (Ability ability : abilities) {
// If e.g. triggerd abilities (non static) created the effect, the ability must not be in usable zone (e.g. Unearth giving Haste effect) // If e.g. triggerd abilities (non static) created the effect, the ability must not be in usable zone (e.g. Unearth giving Haste effect)
@ -244,11 +244,11 @@ public class ContinuousEffects implements Serializable {
return effects.stream().filter(effect->effect.hasLayer(layer)).collect(Collectors.toList()); return effects.stream().filter(effect->effect.hasLayer(layer)).collect(Collectors.toList());
} }
public HashMap<RequirementEffect, HashSet<Ability>> getApplicableRequirementEffects(Permanent permanent, Game game) { public Map<RequirementEffect, Set<Ability>> getApplicableRequirementEffects(Permanent permanent, Game game) {
HashMap<RequirementEffect, HashSet<Ability>> effects = new HashMap<>(); Map<RequirementEffect, Set<Ability>> effects = new HashMap<>();
for (RequirementEffect effect : requirementEffects) { for (RequirementEffect effect : requirementEffects) {
HashSet<Ability> abilities = requirementEffects.getAbility(effect.getId()); Set<Ability> abilities = requirementEffects.getAbility(effect.getId());
HashSet<Ability> applicableAbilities = new HashSet<>(); Set<Ability> applicableAbilities = new HashSet<>();
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, ability instanceof MageSingleton ? permanent : null, null)) { if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, ability instanceof MageSingleton ? permanent : null, null)) {
if (effect.applies(permanent, ability, game)) { if (effect.applies(permanent, ability, game)) {
@ -263,11 +263,11 @@ public class ContinuousEffects implements Serializable {
return effects; return effects;
} }
public HashMap<RestrictionEffect, HashSet<Ability>> getApplicableRestrictionEffects(Permanent permanent, Game game) { public Map<RestrictionEffect, Set<Ability>> getApplicableRestrictionEffects(Permanent permanent, Game game) {
HashMap<RestrictionEffect, HashSet<Ability>> effects = new HashMap<>(); Map<RestrictionEffect, Set<Ability>> effects = new HashMap<>();
for (RestrictionEffect effect : restrictionEffects) { for (RestrictionEffect effect : restrictionEffects) {
HashSet<Ability> abilities = restrictionEffects.getAbility(effect.getId()); Set<Ability> abilities = restrictionEffects.getAbility(effect.getId());
HashSet<Ability> applicableAbilities = new HashSet<>(); Set<Ability> applicableAbilities = new HashSet<>();
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, ability instanceof MageSingleton ? permanent : null, null)) { if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, ability instanceof MageSingleton ? permanent : null, null)) {
if (effect.applies(permanent, ability, game)) { if (effect.applies(permanent, ability, game)) {
@ -282,11 +282,11 @@ public class ContinuousEffects implements Serializable {
return effects; return effects;
} }
public HashMap<RestrictionUntapNotMoreThanEffect, HashSet<Ability>> getApplicableRestrictionUntapNotMoreThanEffects(Player player, Game game) { public Map<RestrictionUntapNotMoreThanEffect, Set<Ability>> getApplicableRestrictionUntapNotMoreThanEffects(Player player, Game game) {
HashMap<RestrictionUntapNotMoreThanEffect, HashSet<Ability>> effects = new HashMap<>(); Map<RestrictionUntapNotMoreThanEffect, Set<Ability>> effects = new HashMap<>();
for (RestrictionUntapNotMoreThanEffect effect : restrictionUntapNotMoreThanEffects) { for (RestrictionUntapNotMoreThanEffect effect : restrictionUntapNotMoreThanEffects) {
HashSet<Ability> abilities = restrictionUntapNotMoreThanEffects.getAbility(effect.getId()); Set<Ability> abilities = restrictionUntapNotMoreThanEffects.getAbility(effect.getId());
HashSet<Ability> applicableAbilities = new HashSet<>(); Set<Ability> applicableAbilities = new HashSet<>();
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) { if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) {
if (effect.applies(player, ability, game)) { if (effect.applies(player, ability, game)) {
@ -307,7 +307,7 @@ public class ContinuousEffects implements Serializable {
continue; continue;
} }
if (effect instanceof PayCostToAttackBlockEffect) { if (effect instanceof PayCostToAttackBlockEffect) {
HashSet<Ability> abilities = replacementEffects.getAbility(effect.getId()); Set<Ability> abilities = replacementEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
// for replacment effects of static abilities do not use LKI to check if to apply // for replacment effects of static abilities do not use LKI to check if to apply
if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) { if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) {
@ -332,8 +332,8 @@ public class ContinuousEffects implements Serializable {
* @return a list of all {@link ReplacementEffect} that apply to the current * @return a list of all {@link ReplacementEffect} that apply to the current
* event * event
*/ */
private HashMap<ReplacementEffect, HashSet<Ability>> getApplicableReplacementEffects(GameEvent event, Game game) { private Map<ReplacementEffect, Set<Ability>> getApplicableReplacementEffects(GameEvent event, Game game) {
HashMap<ReplacementEffect, HashSet<Ability>> replaceEffects = new HashMap<>(); Map<ReplacementEffect, Set<Ability>> replaceEffects = new HashMap<>();
if (planeswalkerRedirectionEffect.checksEventType(event, game) && planeswalkerRedirectionEffect.applies(event, null, game)) { if (planeswalkerRedirectionEffect.checksEventType(event, game) && planeswalkerRedirectionEffect.applies(event, null, game)) {
replaceEffects.put(planeswalkerRedirectionEffect, null); replaceEffects.put(planeswalkerRedirectionEffect, null);
} }
@ -351,8 +351,8 @@ public class ContinuousEffects implements Serializable {
// TODO: Handle also gained effect that are connected to different abilities. // TODO: Handle also gained effect that are connected to different abilities.
continue; continue;
} }
HashSet<Ability> abilities = replacementEffects.getAbility(effect.getId()); Set<Ability> abilities = replacementEffects.getAbility(effect.getId());
HashSet<Ability> applicableAbilities = new HashSet<>(); Set<Ability> applicableAbilities = new HashSet<>();
for (Ability ability : abilities) { for (Ability ability : abilities) {
// for replacment effects of static abilities do not use LKI to check if to apply // for replacment effects of static abilities do not use LKI to check if to apply
if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) { if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) {
@ -380,8 +380,8 @@ public class ContinuousEffects implements Serializable {
// TODO: Handle also gained effect that are connected to different abilities. // TODO: Handle also gained effect that are connected to different abilities.
continue; continue;
} }
HashSet<Ability> abilities = preventionEffects.getAbility(effect.getId()); Set<Ability> abilities = preventionEffects.getAbility(effect.getId());
HashSet<Ability> applicableAbilities = new HashSet<>(); Set<Ability> applicableAbilities = new HashSet<>();
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) { if (ability.getAbilityType() != AbilityType.STATIC || ability.isInUseableZone(game, null, event)) {
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
@ -455,7 +455,7 @@ public class ContinuousEffects implements Serializable {
List<CostModificationEffect> costEffects = new ArrayList<>(); List<CostModificationEffect> costEffects = new ArrayList<>();
for (CostModificationEffect effect : costModificationEffects) { for (CostModificationEffect effect : costModificationEffects) {
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId()); Set<Ability> abilities = costModificationEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) { if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) {
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
@ -479,7 +479,7 @@ public class ContinuousEffects implements Serializable {
List<SpliceCardEffect> spliceEffects = new ArrayList<>(); List<SpliceCardEffect> spliceEffects = new ArrayList<>();
for (SpliceCardEffect effect : spliceCardEffects) { for (SpliceCardEffect effect : spliceCardEffects) {
HashSet<Ability> abilities = spliceCardEffects.getAbility(effect.getId()); Set<Ability> abilities = spliceCardEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (ability.getControllerId().equals(playerId) && (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null))) { if (ability.getControllerId().equals(playerId) && (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null))) {
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
@ -500,7 +500,7 @@ public class ContinuousEffects implements Serializable {
public boolean asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) { public boolean asThough(UUID objectId, AsThoughEffectType type, Ability affectedAbility, UUID controllerId, Game game) {
List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(type, game); List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(type, game);
for (AsThoughEffect effect : asThoughEffectsList) { for (AsThoughEffect effect : asThoughEffectsList) {
HashSet<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId()); Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (affectedAbility == null) { if (affectedAbility == null) {
if (effect.applies(objectId, ability, controllerId, game)) { if (effect.applies(objectId, ability, controllerId, game)) {
@ -519,7 +519,7 @@ public class ContinuousEffects implements Serializable {
// First check existing only effects // First check existing only effects
List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(AsThoughEffectType.SPEND_ONLY_MANA, game); List<AsThoughEffect> asThoughEffectsList = getApplicableAsThoughEffects(AsThoughEffectType.SPEND_ONLY_MANA, game);
for (AsThoughEffect effect : asThoughEffectsList) { for (AsThoughEffect effect : asThoughEffectsList) {
HashSet<Ability> abilities = asThoughEffectsMap.get(AsThoughEffectType.SPEND_ONLY_MANA).getAbility(effect.getId()); Set<Ability> abilities = asThoughEffectsMap.get(AsThoughEffectType.SPEND_ONLY_MANA).getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if ((affectedAbility == null && effect.applies(objectId, ability, controllerId, game)) if ((affectedAbility == null && effect.applies(objectId, ability, controllerId, game))
|| effect.applies(objectId, affectedAbility, ability, game)) { || effect.applies(objectId, affectedAbility, ability, game)) {
@ -532,7 +532,7 @@ public class ContinuousEffects implements Serializable {
// then check effects that allow to use other mana types to pay the current mana type to pay // then check effects that allow to use other mana types to pay the current mana type to pay
asThoughEffectsList = getApplicableAsThoughEffects(AsThoughEffectType.SPEND_OTHER_MANA, game); asThoughEffectsList = getApplicableAsThoughEffects(AsThoughEffectType.SPEND_OTHER_MANA, game);
for (AsThoughEffect effect : asThoughEffectsList) { for (AsThoughEffect effect : asThoughEffectsList) {
HashSet<Ability> abilities = asThoughEffectsMap.get(AsThoughEffectType.SPEND_OTHER_MANA).getAbility(effect.getId()); Set<Ability> abilities = asThoughEffectsMap.get(AsThoughEffectType.SPEND_OTHER_MANA).getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if ((affectedAbility == null && effect.applies(objectId, ability, controllerId, game)) if ((affectedAbility == null && effect.applies(objectId, ability, controllerId, game))
|| effect.applies(objectId, affectedAbility, ability, game)) { || effect.applies(objectId, affectedAbility, ability, game)) {
@ -557,7 +557,7 @@ public class ContinuousEffects implements Serializable {
List<AsThoughEffect> asThoughEffectsList = new ArrayList<>(); List<AsThoughEffect> asThoughEffectsList = new ArrayList<>();
if (asThoughEffectsMap.containsKey(type)) { if (asThoughEffectsMap.containsKey(type)) {
for (AsThoughEffect effect : asThoughEffectsMap.get(type)) { for (AsThoughEffect effect : asThoughEffectsMap.get(type)) {
HashSet<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId()); Set<Ability> abilities = asThoughEffectsMap.get(type).getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) { if (!(ability instanceof StaticAbility) || ability.isInUseableZone(game, null, null)) {
if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) { if (effect.getDuration() != Duration.OneUse || !effect.isUsed()) {
@ -600,7 +600,7 @@ public class ContinuousEffects implements Serializable {
for (CostModificationEffect effect : costEffects) { for (CostModificationEffect effect : costEffects) {
if (effect.getModificationType() == CostModificationType.INCREASE_COST) { if (effect.getModificationType() == CostModificationType.INCREASE_COST) {
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId()); Set<Ability> abilities = costModificationEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (effect.applies(abilityToModify, ability, game)) { if (effect.applies(abilityToModify, ability, game)) {
effect.apply(game, ability, abilityToModify); effect.apply(game, ability, abilityToModify);
@ -611,7 +611,7 @@ public class ContinuousEffects implements Serializable {
for (CostModificationEffect effect : costEffects) { for (CostModificationEffect effect : costEffects) {
if (effect.getModificationType() == CostModificationType.REDUCE_COST) { if (effect.getModificationType() == CostModificationType.REDUCE_COST) {
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId()); Set<Ability> abilities = costModificationEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (effect.applies(abilityToModify, ability, game)) { if (effect.applies(abilityToModify, ability, game)) {
effect.apply(game, ability, abilityToModify); effect.apply(game, ability, abilityToModify);
@ -622,7 +622,7 @@ public class ContinuousEffects implements Serializable {
for (CostModificationEffect effect : costEffects) { for (CostModificationEffect effect : costEffects) {
if (effect.getModificationType() == CostModificationType.SET_COST) { if (effect.getModificationType() == CostModificationType.SET_COST) {
HashSet<Ability> abilities = costModificationEffects.getAbility(effect.getId()); Set<Ability> abilities = costModificationEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (effect.applies(abilityToModify, ability, game)) { if (effect.applies(abilityToModify, ability, game)) {
effect.apply(game, ability, abilityToModify); effect.apply(game, ability, abilityToModify);
@ -647,7 +647,7 @@ public class ContinuousEffects implements Serializable {
// get the applyable splice abilities // get the applyable splice abilities
List<SpliceOntoArcaneAbility> spliceAbilities = new ArrayList<>(); List<SpliceOntoArcaneAbility> spliceAbilities = new ArrayList<>();
for (SpliceCardEffect effect : spliceEffects) { for (SpliceCardEffect effect : spliceEffects) {
HashSet<Ability> abilities = spliceCardEffects.getAbility(effect.getId()); Set<Ability> abilities = spliceCardEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (effect.applies(abilityToModify, ability, game)) { if (effect.applies(abilityToModify, ability, game)) {
spliceAbilities.add((SpliceOntoArcaneAbility) ability); spliceAbilities.add((SpliceOntoArcaneAbility) ability);
@ -741,14 +741,14 @@ public class ContinuousEffects implements Serializable {
public boolean replaceEvent(GameEvent event, Game game) { public boolean replaceEvent(GameEvent event, Game game) {
boolean caught = false; boolean caught = false;
HashMap<UUID, HashSet<UUID>> consumed = new HashMap<>(); Map<UUID, Set<UUID>> consumed = new HashMap<>();
do { do {
HashMap<ReplacementEffect, HashSet<Ability>> rEffects = getApplicableReplacementEffects(event, game); Map<ReplacementEffect, Set<Ability>> rEffects = getApplicableReplacementEffects(event, game);
// Remove all consumed effects (ability dependant) // Remove all consumed effects (ability dependant)
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext();) { for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext();) {
ReplacementEffect entry = it1.next(); ReplacementEffect entry = it1.next();
if (consumed.containsKey(entry.getId())) { if (consumed.containsKey(entry.getId())) {
HashSet<UUID> consumedAbilitiesIds = consumed.get(entry.getId()); Set<UUID> consumedAbilitiesIds = consumed.get(entry.getId());
if (rEffects.get(entry) == null || consumedAbilitiesIds.size() == rEffects.get(entry).size()) { if (rEffects.get(entry) == null || consumedAbilitiesIds.size() == rEffects.get(entry).size()) {
it1.remove(); it1.remove();
} else { } else {
@ -770,7 +770,7 @@ public class ContinuousEffects implements Serializable {
boolean onlyOne = false; boolean onlyOne = false;
if (rEffects.size() == 1) { if (rEffects.size() == 1) {
ReplacementEffect effect = rEffects.keySet().iterator().next(); ReplacementEffect effect = rEffects.keySet().iterator().next();
HashSet<Ability> abilities; Set<Ability> abilities;
if (effect.getEffectType() == EffectType.REPLACEMENT) { if (effect.getEffectType() == EffectType.REPLACEMENT) {
abilities = replacementEffects.getAbility(effect.getId()); abilities = replacementEffects.getAbility(effect.getId());
} else { } else {
@ -791,7 +791,7 @@ public class ContinuousEffects implements Serializable {
int checked = 0; int checked = 0;
ReplacementEffect rEffect = null; ReplacementEffect rEffect = null;
Ability rAbility = null; Ability rAbility = null;
for (Map.Entry<ReplacementEffect, HashSet<Ability>> entry : rEffects.entrySet()) { for (Map.Entry<ReplacementEffect, Set<Ability>> entry : rEffects.entrySet()) {
if (entry.getValue() == null) { if (entry.getValue() == null) {
if (checked == index) { if (checked == index) {
rEffect = entry.getKey(); rEffect = entry.getKey();
@ -800,7 +800,7 @@ public class ContinuousEffects implements Serializable {
checked++; checked++;
} }
} else { } else {
HashSet<Ability> abilities = entry.getValue(); Set<Ability> abilities = entry.getValue();
int size = abilities.size(); int size = abilities.size();
if (index > (checked + size - 1)) { if (index > (checked + size - 1)) {
checked += size; checked += size;
@ -831,13 +831,13 @@ public class ContinuousEffects implements Serializable {
// add the applied effect to the consumed effects // add the applied effect to the consumed effects
if (rEffect != null) { if (rEffect != null) {
if (consumed.containsKey(rEffect.getId())) { if (consumed.containsKey(rEffect.getId())) {
HashSet<UUID> set = consumed.get(rEffect.getId()); Set<UUID> set = consumed.get(rEffect.getId());
if (rAbility != null) { if (rAbility != null) {
set.add(rAbility.getId()); set.add(rAbility.getId());
} }
} else { } else {
HashSet<UUID> set = new HashSet<>(); Set<UUID> set = new HashSet<>();
if (rAbility != null) { // in case of AuraReplacementEffect or PlaneswalkerReplacementEffect there is no Ability if (rAbility != null) { // in case of AuraReplacementEffect or PlaneswalkerReplacementEffect there is no Ability
set.add(rAbility.getId()); set.add(rAbility.getId());
} }
@ -860,7 +860,7 @@ public class ContinuousEffects implements Serializable {
List<ContinuousEffect> layer = filterLayeredEffects(activeLayerEffects, Layer.CopyEffects_1); List<ContinuousEffect> layer = filterLayeredEffects(activeLayerEffects, Layer.CopyEffects_1);
for (ContinuousEffect effect : layer) { for (ContinuousEffect effect : layer) {
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
effect.apply(Layer.CopyEffects_1, SubLayer.NA, ability, game); effect.apply(Layer.CopyEffects_1, SubLayer.NA, ability, game);
} }
@ -876,7 +876,7 @@ public class ContinuousEffects implements Serializable {
// e.g. Mind Control is controlled by Steal Enchantment // e.g. Mind Control is controlled by Steal Enchantment
while (true) { while (true) {
for (ContinuousEffect effect : layer) { for (ContinuousEffect effect : layer) {
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
effect.apply(Layer.ControlChangingEffects_2, SubLayer.NA, ability, game); effect.apply(Layer.ControlChangingEffects_2, SubLayer.NA, ability, game);
} }
@ -908,7 +908,7 @@ public class ContinuousEffects implements Serializable {
continue; continue;
} }
List<Ability> appliedAbilities = appliedEffectAbilities.get(effect); List<Ability> appliedAbilities = appliedEffectAbilities.get(effect);
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (appliedAbilities == null || !appliedAbilities.contains(ability)) { if (appliedAbilities == null || !appliedAbilities.contains(ability)) {
if (appliedAbilities == null) { if (appliedAbilities == null) {
@ -955,7 +955,7 @@ public class ContinuousEffects implements Serializable {
layer = filterLayeredEffects(activeLayerEffects, Layer.PTChangingEffects_7); layer = filterLayeredEffects(activeLayerEffects, Layer.PTChangingEffects_7);
for (ContinuousEffect effect : layer) { for (ContinuousEffect effect : layer) {
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (abilityActive(ability, game)) { if (abilityActive(ability, game)) {
effect.apply(Layer.PTChangingEffects_7, SubLayer.CharacteristicDefining_7a, ability, game); effect.apply(Layer.PTChangingEffects_7, SubLayer.CharacteristicDefining_7a, ability, game);
@ -963,13 +963,13 @@ public class ContinuousEffects implements Serializable {
} }
} }
for (ContinuousEffect effect : layer) { for (ContinuousEffect effect : layer) {
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
effect.apply(Layer.PTChangingEffects_7, SubLayer.SetPT_7b, ability, game); effect.apply(Layer.PTChangingEffects_7, SubLayer.SetPT_7b, ability, game);
} }
} }
for (ContinuousEffect effect : layer) { for (ContinuousEffect effect : layer) {
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
effect.apply(Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, ability, game); effect.apply(Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, ability, game);
} }
@ -978,21 +978,21 @@ public class ContinuousEffects implements Serializable {
applyCounters.apply(Layer.PTChangingEffects_7, SubLayer.Counters_7d, null, game); applyCounters.apply(Layer.PTChangingEffects_7, SubLayer.Counters_7d, null, game);
for (ContinuousEffect effect : layer) { for (ContinuousEffect effect : layer) {
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
effect.apply(Layer.PTChangingEffects_7, SubLayer.SwitchPT_e, ability, game); effect.apply(Layer.PTChangingEffects_7, SubLayer.SwitchPT_e, ability, game);
} }
} }
layer = filterLayeredEffects(activeLayerEffects, Layer.PlayerEffects); layer = filterLayeredEffects(activeLayerEffects, Layer.PlayerEffects);
for (ContinuousEffect effect : layer) { for (ContinuousEffect effect : layer) {
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
effect.apply(Layer.PlayerEffects, SubLayer.NA, ability, game); effect.apply(Layer.PlayerEffects, SubLayer.NA, ability, game);
} }
} }
layer = filterLayeredEffects(activeLayerEffects, Layer.RulesEffects); layer = filterLayeredEffects(activeLayerEffects, Layer.RulesEffects);
for (ContinuousEffect effect : layer) { for (ContinuousEffect effect : layer) {
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
effect.apply(Layer.RulesEffects, SubLayer.NA, ability, game); effect.apply(Layer.RulesEffects, SubLayer.NA, ability, game);
} }
@ -1034,13 +1034,13 @@ public class ContinuousEffects implements Serializable {
} }
private void applyContinuousEffect(ContinuousEffect effect, Layer currentLayer, Game game) { private void applyContinuousEffect(ContinuousEffect effect, Layer currentLayer, Game game) {
HashSet<Ability> abilities = layeredEffects.getAbility(effect.getId()); Set<Ability> abilities = layeredEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
effect.apply(currentLayer, SubLayer.NA, ability, game); effect.apply(currentLayer, SubLayer.NA, ability, game);
} }
} }
public HashSet<Ability> getLayeredEffectAbilities(ContinuousEffect effect) { public Set<Ability> getLayeredEffectAbilities(ContinuousEffect effect) {
return layeredEffects.getAbility(effect.getId()); return layeredEffects.getAbility(effect.getId());
} }
@ -1135,7 +1135,7 @@ public class ContinuousEffects implements Serializable {
private void setControllerForEffect(ContinuousEffectsList<?> effects, UUID sourceId, UUID controllerId) { private void setControllerForEffect(ContinuousEffectsList<?> effects, UUID sourceId, UUID controllerId) {
for (Effect effect : effects) { for (Effect effect : effects) {
HashSet<Ability> abilities = effects.getAbility(effect.getId()); Set<Ability> abilities = effects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (ability.getSourceId() != null) { if (ability.getSourceId() != null) {
if (ability.getSourceId().equals(sourceId)) { if (ability.getSourceId().equals(sourceId)) {
@ -1200,9 +1200,9 @@ public class ContinuousEffects implements Serializable {
temporaryEffects.clear(); temporaryEffects.clear();
} }
public Map<String, String> getReplacementEffectsTexts(HashMap<ReplacementEffect, HashSet<Ability>> rEffects, Game game) { public Map<String, String> getReplacementEffectsTexts(Map<ReplacementEffect, Set<Ability>> rEffects, Game game) {
Map<String, String> texts = new LinkedHashMap<>(); Map<String, String> texts = new LinkedHashMap<>();
for (Map.Entry<ReplacementEffect, HashSet<Ability>> entry : rEffects.entrySet()) { for (Map.Entry<ReplacementEffect, Set<Ability>> entry : rEffects.entrySet()) {
if (entry.getValue() != null) { if (entry.getValue() != null) {
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
MageObject object = game.getObject(ability.getSourceId()); MageObject object = game.getObject(ability.getSourceId());
@ -1229,7 +1229,7 @@ public class ContinuousEffects implements Serializable {
public UUID getControllerOfSourceId(UUID sourceId) { public UUID getControllerOfSourceId(UUID sourceId) {
UUID controllerFound = null; UUID controllerFound = null;
for (PreventionEffect effect : preventionEffects) { for (PreventionEffect effect : preventionEffects) {
HashSet<Ability> abilities = preventionEffects.getAbility(effect.getId()); Set<Ability> abilities = preventionEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (ability.getSourceId().equals(sourceId)) { if (ability.getSourceId().equals(sourceId)) {
if (controllerFound == null || controllerFound.equals(ability.getControllerId())) { if (controllerFound == null || controllerFound.equals(ability.getControllerId())) {
@ -1242,7 +1242,7 @@ public class ContinuousEffects implements Serializable {
} }
} }
for (ReplacementEffect effect : replacementEffects) { for (ReplacementEffect effect : replacementEffects) {
HashSet<Ability> abilities = replacementEffects.getAbility(effect.getId()); Set<Ability> abilities = replacementEffects.getAbility(effect.getId());
for (Ability ability : abilities) { for (Ability ability : abilities) {
if (ability.getSourceId() != null) { if (ability.getSourceId() != null) {
if (ability.getSourceId().equals(sourceId)) { if (ability.getSourceId().equals(sourceId)) {

View file

@ -27,20 +27,14 @@
*/ */
package mage.abilities.effects; package mage.abilities.effects;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.MageSingleton; import mage.abilities.MageSingleton;
import mage.constants.Duration; import mage.constants.Duration;
import mage.game.Game; import mage.game.Game;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.util.*;
/** /**
* @param <T> * @param <T>
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
@ -50,7 +44,7 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
private static final Logger logger = Logger.getLogger(ContinuousEffectsList.class); private static final Logger logger = Logger.getLogger(ContinuousEffectsList.class);
// the effectAbilityMap holds for each effect all abilities that are connected (used) with this effect // the effectAbilityMap holds for each effect all abilities that are connected (used) with this effect
private final Map<UUID, HashSet<Ability>> effectAbilityMap = new HashMap<>(); private final Map<UUID, Set<Ability>> effectAbilityMap = new HashMap<>();
public ContinuousEffectsList() { public ContinuousEffectsList() {
} }
@ -60,8 +54,8 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
for (ContinuousEffect cost : effects) { for (ContinuousEffect cost : effects) {
this.add((T) cost.copy()); this.add((T) cost.copy());
} }
for (Map.Entry<UUID, HashSet<Ability>> entry : effects.effectAbilityMap.entrySet()) { for (Map.Entry<UUID, Set<Ability>> entry : effects.effectAbilityMap.entrySet()) {
HashSet<Ability> newSet = new HashSet<>(); Set<Ability> newSet = new HashSet<>();
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
newSet.add(ability.copy()); newSet.add(ability.copy());
} }
@ -104,7 +98,7 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
} }
private boolean isInactive(T effect, Game game) { private boolean isInactive(T effect, Game game) {
HashSet<Ability> set = effectAbilityMap.get(effect.getId()); Set<Ability> set = effectAbilityMap.get(effect.getId());
if (set == null) { if (set == null) {
logger.debug("No abilities for effect found: " + effect.toString()); logger.debug("No abilities for effect found: " + effect.toString());
return false; return false;
@ -153,7 +147,7 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
*/ */
public void addEffect(T effect, Ability source) { public void addEffect(T effect, Ability source) {
if (effectAbilityMap.containsKey(effect.getId())) { if (effectAbilityMap.containsKey(effect.getId())) {
HashSet<Ability> set = effectAbilityMap.get(effect.getId()); Set<Ability> set = effectAbilityMap.get(effect.getId());
for (Ability ability : set) { for (Ability ability : set) {
if (ability.getId().equals(source.getId()) && ability.getSourceId().equals(source.getSourceId())) { if (ability.getId().equals(source.getId()) && ability.getSourceId().equals(source.getSourceId())) {
return; return;
@ -162,18 +156,18 @@ public class ContinuousEffectsList<T extends ContinuousEffect> extends ArrayList
set.add(source); set.add(source);
return; return;
} }
HashSet<Ability> set = new HashSet<>(); Set<Ability> set = new HashSet<>();
set.add(source); set.add(source);
this.effectAbilityMap.put(effect.getId(), set); this.effectAbilityMap.put(effect.getId(), set);
this.add(effect); this.add(effect);
} }
public HashSet<Ability> getAbility(UUID effectId) { public Set<Ability> getAbility(UUID effectId) {
return effectAbilityMap.getOrDefault(effectId, new HashSet<>()); return effectAbilityMap.getOrDefault(effectId, new HashSet<>());
} }
public void removeEffects(UUID effectIdToRemove, Set<Ability> abilitiesToRemove) { public void removeEffects(UUID effectIdToRemove, Set<Ability> abilitiesToRemove) {
HashSet<Ability> abilities = effectAbilityMap.get(effectIdToRemove); Set<Ability> abilities = effectAbilityMap.get(effectIdToRemove);
if (abilitiesToRemove != null && abilities != null) { if (abilitiesToRemove != null && abilities != null) {
abilities.removeAll(abilitiesToRemove); abilities.removeAll(abilitiesToRemove);
} }

View file

@ -27,8 +27,6 @@
*/ */
package mage.abilities.effects.common; package mage.abilities.effects.common;
import java.util.ArrayList;
import java.util.Arrays;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.choices.Choice; import mage.choices.Choice;
@ -38,13 +36,17 @@ import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/** /**
* *
* @author LevelX2 * @author LevelX2
*/ */
public class ChooseModeEffect extends OneShotEffect { public class ChooseModeEffect extends OneShotEffect {
protected final ArrayList<String> modes = new ArrayList(); protected final List<String> modes = new ArrayList();
protected final String choiceMessage; protected final String choiceMessage;
public ChooseModeEffect(String choiceMessage, String... modes) { public ChooseModeEffect(String choiceMessage, String... modes) {

View file

@ -27,8 +27,6 @@
*/ */
package mage.abilities.effects.common; package mage.abilities.effects.common;
import java.util.ArrayList;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.EntersBattlefieldEffect;
@ -39,6 +37,10 @@ import mage.counters.Counter;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/** /**
* Use this effect only (I guess) with EntersBattlefieldAbility like abilities * Use this effect only (I guess) with EntersBattlefieldAbility like abilities
* *
@ -77,7 +79,7 @@ public class EntersBattlefieldWithXCountersEffect extends OneShotEffect {
if (amount > 0) { if (amount > 0) {
Counter counterToAdd = counter.copy(); Counter counterToAdd = counter.copy();
counterToAdd.add(amount - counter.getCount()); counterToAdd.add(amount - counter.getCount());
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects"); List<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
permanent.addCounters(counterToAdd, source, game, appliedEffects); permanent.addCounters(counterToAdd, source, game, appliedEffects);
} }
} }

View file

@ -27,7 +27,6 @@
*/ */
package mage.abilities.effects.common.continuous; package mage.abilities.effects.common.continuous;
import java.util.HashSet;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.Mode; import mage.abilities.Mode;
import mage.choices.ChoiceImpl; import mage.choices.ChoiceImpl;
@ -37,6 +36,9 @@ import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.Target; import mage.target.Target;
import java.util.HashSet;
import java.util.Set;
/** /**
* *
* @author a * @author a
@ -71,7 +73,7 @@ public class LoseAbilityOrAnotherAbilityTargetEffect extends LoseAbilityTargetEf
ChoiceImpl chooseAbility = new ChoiceImpl(); ChoiceImpl chooseAbility = new ChoiceImpl();
chooseAbility.setMessage("What ability do you wish to remove?"); chooseAbility.setMessage("What ability do you wish to remove?");
HashSet<String> choice = new HashSet<>(); Set<String> choice = new HashSet<>();
if (permanent.getAbilities().contains(ability)) { if (permanent.getAbilities().contains(ability)) {
choice.add(ability.getRule()); choice.add(ability.getRule());

View file

@ -1,8 +1,5 @@
package mage.actions; package mage.actions;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.actions.impl.MageAction; import mage.actions.impl.MageAction;
import mage.actions.score.ArtificialScoringSystem; import mage.actions.score.ArtificialScoringSystem;
import mage.cards.Card; import mage.cards.Card;
@ -12,6 +9,10 @@ import mage.game.events.GameEvent;
import mage.players.Player; import mage.players.Player;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/** /**
* Action for drawing cards. * Action for drawing cards.
* *
@ -21,12 +22,12 @@ public class MageDrawAction extends MageAction {
private final Player player; private final Player player;
private final int amount; private final int amount;
private final ArrayList<UUID> appliedEffects; private final List<UUID> appliedEffects;
private final List<Card> drawnCards; private final List<Card> drawnCards;
private static final int NEGATIVE_VALUE = -1000000; private static final int NEGATIVE_VALUE = -1000000;
public MageDrawAction(Player player, int amount, ArrayList<UUID> appliedEffects) { public MageDrawAction(Player player, int amount, List<UUID> appliedEffects) {
this.player = player; this.player = player;
this.amount = amount; this.amount = amount;
this.appliedEffects = appliedEffects; this.appliedEffects = appliedEffects;

View file

@ -27,16 +27,12 @@
*/ */
package mage.cards; package mage.cards;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.Mana; import mage.Mana;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Abilities; import mage.abilities.Abilities;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.constants.CardType;
import mage.constants.Rarity; import mage.constants.Rarity;
import mage.constants.Zone; import mage.constants.Zone;
import mage.counters.Counter; import mage.counters.Counter;
@ -46,6 +42,9 @@ import mage.game.Game;
import mage.game.GameState; import mage.game.GameState;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.List;
import java.util.UUID;
public interface Card extends MageObject { public interface Card extends MageObject {
@ -127,7 +126,7 @@ public interface Card extends MageObject {
*/ */
boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag); boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag);
boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects); boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects);
/** /**
* Moves the card to an exile zone * Moves the card to an exile zone
@ -140,7 +139,7 @@ public interface Card extends MageObject {
*/ */
boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game); boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game);
boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects); boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects);
boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId); boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId);
@ -152,7 +151,7 @@ public interface Card extends MageObject {
boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown); boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown);
boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, ArrayList<UUID> appliedEffects); boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, List<UUID> appliedEffects);
void setZone(Zone zone, Game game); void setZone(Zone zone, Game game);
@ -170,7 +169,7 @@ public interface Card extends MageObject {
boolean addCounters(Counter counter, Ability source, Game game); boolean addCounters(Counter counter, Ability source, Game game);
boolean addCounters(Counter counter, Ability source, Game game, ArrayList<UUID> appliedEffects); boolean addCounters(Counter counter, Ability source, Game game, List<UUID> appliedEffects);
void removeCounters(String name, int amount, Game game); void removeCounters(String name, int amount, Game game);

View file

@ -27,25 +27,14 @@
*/ */
package mage.cards; package mage.cards;
import java.lang.reflect.Constructor;
import java.util.*;
import mage.MageObject; import mage.MageObject;
import mage.MageObjectImpl; import mage.MageObjectImpl;
import mage.Mana; import mage.Mana;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Abilities; import mage.abilities.*;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
import mage.abilities.PlayLandAbility;
import mage.abilities.SpellAbility;
import mage.abilities.mana.ActivatedManaAbilityImpl; import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.cards.repository.PluginClassloaderRegistery; import mage.cards.repository.PluginClassloaderRegistery;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.ColoredManaSymbol;
import mage.constants.Rarity;
import mage.constants.SpellAbilityType;
import mage.constants.TimingRule;
import mage.constants.Zone;
import mage.counters.Counter; import mage.counters.Counter;
import mage.counters.Counters; import mage.counters.Counters;
import mage.game.*; import mage.game.*;
@ -58,6 +47,12 @@ import mage.util.GameLog;
import mage.watchers.Watcher; import mage.watchers.Watcher;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
public abstract class CardImpl extends MageObjectImpl implements Card { public abstract class CardImpl extends MageObjectImpl implements Card {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
@ -358,7 +353,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
} }
@Override @Override
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) { public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
Zone fromZone = game.getState().getZone(objectId); Zone fromZone = game.getState().getZone(objectId);
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone, appliedEffects); ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, toZone, appliedEffects);
ZoneChangeInfo zoneChangeInfo; ZoneChangeInfo zoneChangeInfo;
@ -394,7 +389,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
} }
@Override @Override
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) { public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
Zone fromZone = game.getState().getZone(objectId); Zone fromZone = game.getState().getZone(objectId);
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, Zone.EXILED, appliedEffects); ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, ownerId, fromZone, Zone.EXILED, appliedEffects);
ZoneChangeInfo.Exile info = new ZoneChangeInfo.Exile(event, exileId, name); ZoneChangeInfo.Exile info = new ZoneChangeInfo.Exile(event, exileId, name);
@ -417,7 +412,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
} }
@Override @Override
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean faceDown, ArrayList<UUID> appliedEffects) { public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean faceDown, List<UUID> appliedEffects) {
ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, controllerId, fromZone, Zone.BATTLEFIELD, appliedEffects); ZoneChangeEvent event = new ZoneChangeEvent(this.objectId, sourceId, controllerId, fromZone, Zone.BATTLEFIELD, appliedEffects);
ZoneChangeInfo.Battlefield info = new ZoneChangeInfo.Battlefield(event, faceDown, tapped); ZoneChangeInfo.Battlefield info = new ZoneChangeInfo.Battlefield(event, faceDown, tapped);
return ZonesHandler.moveCard(info, game); return ZonesHandler.moveCard(info, game);
@ -627,7 +622,7 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
} }
@Override @Override
public boolean addCounters(Counter counter, Ability source, Game game, ArrayList<UUID> appliedEffects) { public boolean addCounters(Counter counter, Ability source, Game game, List<UUID> appliedEffects) {
boolean returnCode = true; boolean returnCode = true;
UUID sourceId = (source == null ? null : source.getSourceId()); UUID sourceId = (source == null ? null : source.getSourceId());
GameEvent countersEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, sourceId, getControllerOrOwner(), counter.getName(), counter.getCount()); GameEvent countersEvent = GameEvent.getEvent(GameEvent.EventType.ADD_COUNTERS, objectId, sourceId, getControllerOrOwner(), counter.getName(), counter.getCount());

View file

@ -27,8 +27,6 @@
*/ */
package mage.cards; package mage.cards;
import java.util.ArrayList;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Zone; import mage.constants.Zone;
@ -37,6 +35,9 @@ import mage.game.Game;
import mage.game.events.ZoneChangeEvent; import mage.game.events.ZoneChangeEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.List;
import java.util.UUID;
/** /**
* *
* @author emerald000 * @author emerald000
@ -133,7 +134,7 @@ public abstract class MeldCard extends CardImpl {
} }
@Override @Override
public boolean addCounters(Counter counter, Ability source, Game game, ArrayList<UUID> appliedEffects) { public boolean addCounters(Counter counter, Ability source, Game game, List<UUID> appliedEffects) {
if (this.isMelded()) { if (this.isMelded()) {
return super.addCounters(counter, source, game, appliedEffects); return super.addCounters(counter, source, game, appliedEffects);
} else { } else {

View file

@ -27,9 +27,6 @@
*/ */
package mage.cards; package mage.cards;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.abilities.Abilities; import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl; import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -39,6 +36,10 @@ import mage.constants.SpellAbilityType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/** /**
* *
* @author LevelX2 * @author LevelX2
@ -91,7 +92,7 @@ public abstract class SplitCard extends CardImpl {
} }
@Override @Override
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) { public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
if (super.moveToZone(toZone, sourceId, game, flag, appliedEffects)) { if (super.moveToZone(toZone, sourceId, game, flag, appliedEffects)) {
game.getState().setZone(getLeftHalfCard().getId(), toZone); game.getState().setZone(getLeftHalfCard().getId(), toZone);
game.getState().setZone(getRightHalfCard().getId(), toZone); game.getState().setZone(getRightHalfCard().getId(), toZone);
@ -101,7 +102,7 @@ public abstract class SplitCard extends CardImpl {
} }
@Override @Override
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) { public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
if (super.moveToExile(exileId, name, sourceId, game, appliedEffects)) { if (super.moveToExile(exileId, name, sourceId, game, appliedEffects)) {
Zone currentZone = game.getState().getZone(getId()); Zone currentZone = game.getState().getZone(getId());
game.getState().setZone(getLeftHalfCard().getId(), currentZone); game.getState().setZone(getLeftHalfCard().getId(), currentZone);

View file

@ -5,13 +5,15 @@
*/ */
package mage.cards; package mage.cards;
import java.util.ArrayList;
import java.util.UUID;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.SpellAbilityType; import mage.constants.SpellAbilityType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/** /**
* *
* @author LevelX2 * @author LevelX2
@ -51,12 +53,12 @@ public class SplitCardHalfImpl extends CardImpl implements SplitCardHalf {
} }
@Override @Override
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) { public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
return splitCardParent.moveToZone(toZone, sourceId, game, flag, appliedEffects); return splitCardParent.moveToZone(toZone, sourceId, game, flag, appliedEffects);
} }
@Override @Override
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) { public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
return splitCardParent.moveToExile(exileId, name, sourceId, game, appliedEffects); return splitCardParent.moveToExile(exileId, name, sourceId, game, appliedEffects);
} }

View file

@ -27,15 +27,6 @@
*/ */
package mage.game.combat; package mage.game.combat;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.RequirementEffect; import mage.abilities.effects.RequirementEffect;
@ -59,6 +50,9 @@ import mage.util.Copyable;
import mage.util.trace.TraceUtil; import mage.util.trace.TraceUtil;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.io.Serializable;
import java.util.*;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -308,7 +302,7 @@ public class Combat implements Serializable, Copyable<Combat> {
for (Permanent creature : player.getAvailableAttackers(game)) { for (Permanent creature : player.getAvailableAttackers(game)) {
boolean mustAttack = false; boolean mustAttack = false;
Set<UUID> defendersForcedToAttack = new HashSet<>(); Set<UUID> defendersForcedToAttack = new HashSet<>();
for (Map.Entry<RequirementEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) { for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
RequirementEffect effect = entry.getKey(); RequirementEffect effect = entry.getKey();
if (effect.mustAttack(game)) { if (effect.mustAttack(game)) {
mustAttack = true; mustAttack = true;
@ -395,7 +389,7 @@ public class Combat implements Serializable, Copyable<Combat> {
} }
for (UUID attackingCreatureId : this.getAttackers()) { for (UUID attackingCreatureId : this.getAttackers()) {
Permanent attackingCreature = game.getPermanent(attackingCreatureId); Permanent attackingCreature = game.getPermanent(attackingCreatureId);
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(attackingCreature, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(attackingCreature, game).entrySet()) {
RestrictionEffect effect = entry.getKey(); RestrictionEffect effect = entry.getKey();
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
if (!effect.canAttackCheckAfter(numberAttackers, ability, game)) { if (!effect.canAttackCheckAfter(numberAttackers, ability, game)) {
@ -581,7 +575,7 @@ public class Combat implements Serializable, Copyable<Combat> {
return; return;
} }
for (Permanent possibleBlocker : game.getBattlefield().getActivePermanents(filterBlockers, attackingPlayer.getId(), game)) { for (Permanent possibleBlocker : game.getBattlefield().getActivePermanents(filterBlockers, attackingPlayer.getId(), game)) {
for (Map.Entry<RequirementEffect, HashSet<Ability>> requirementEntry : game.getContinuousEffects().getApplicableRequirementEffects(possibleBlocker, game).entrySet()) { for (Map.Entry<RequirementEffect, Set<Ability>> requirementEntry : game.getContinuousEffects().getApplicableRequirementEffects(possibleBlocker, game).entrySet()) {
if (requirementEntry.getKey().mustBlock(game)) { if (requirementEntry.getKey().mustBlock(game)) {
for (Ability ability : requirementEntry.getValue()) { for (Ability ability : requirementEntry.getValue()) {
UUID attackingCreatureId = requirementEntry.getKey().mustBlockAttacker(ability, game); UUID attackingCreatureId = requirementEntry.getKey().mustBlockAttacker(ability, game);
@ -658,7 +652,7 @@ public class Combat implements Serializable, Copyable<Combat> {
// Creature is already blocking but not forced to do so // Creature is already blocking but not forced to do so
if (creature.getBlocking() > 0) { if (creature.getBlocking() > 0) {
// get all requirement effects that apply to the creature (e.g. is able to block attacker) // get all requirement effects that apply to the creature (e.g. is able to block attacker)
for (Map.Entry<RequirementEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) { for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
RequirementEffect effect = entry.getKey(); RequirementEffect effect = entry.getKey();
// get possible mustBeBlockedByAtLeastOne blocker // get possible mustBeBlockedByAtLeastOne blocker
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
@ -680,7 +674,7 @@ public class Combat implements Serializable, Copyable<Combat> {
// Creature is not blocking yet // Creature is not blocking yet
if (creature.getBlocking() == 0) { if (creature.getBlocking() == 0) {
// get all requirement effects that apply to the creature // get all requirement effects that apply to the creature
for (Map.Entry<RequirementEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) { for (Map.Entry<RequirementEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRequirementEffects(creature, game).entrySet()) {
RequirementEffect effect = entry.getKey(); RequirementEffect effect = entry.getKey();
// get possible mustBeBlockedByAtLeastOne blocker // get possible mustBeBlockedByAtLeastOne blocker
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
@ -980,7 +974,7 @@ public class Combat implements Serializable, Copyable<Combat> {
for (UUID blockingCreatureId : this.getBlockers()) { for (UUID blockingCreatureId : this.getBlockers()) {
Permanent blockingCreature = game.getPermanent(blockingCreatureId); Permanent blockingCreature = game.getPermanent(blockingCreatureId);
if (blockingCreature != null) { if (blockingCreature != null) {
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(blockingCreature, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(blockingCreature, game).entrySet()) {
RestrictionEffect effect = entry.getKey(); RestrictionEffect effect = entry.getKey();
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
if (!effect.canBlockCheckAfter(ability, game)) { if (!effect.canBlockCheckAfter(ability, game)) {
@ -1000,7 +994,7 @@ public class Combat implements Serializable, Copyable<Combat> {
for (UUID attackingCreatureId : this.getAttackers()) { for (UUID attackingCreatureId : this.getAttackers()) {
Permanent attackingCreature = game.getPermanent(attackingCreatureId); Permanent attackingCreature = game.getPermanent(attackingCreatureId);
if (attackingCreature != null) { if (attackingCreature != null) {
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(attackingCreature, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(attackingCreature, game).entrySet()) {
RestrictionEffect effect = entry.getKey(); RestrictionEffect effect = entry.getKey();
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
if (!effect.canBeBlockedCheckAfter(attackingCreature, ability, game)) { if (!effect.canBeBlockedCheckAfter(attackingCreature, ability, game)) {

View file

@ -340,7 +340,7 @@ public abstract class DraftImpl implements Draft {
@Override @Override
public void resetBufferedCards() { public void resetBufferedCards() {
HashSet<ExpansionSet> setsDone = new HashSet<>(); Set<ExpansionSet> setsDone = new HashSet<>();
for(ExpansionSet set: sets) { for(ExpansionSet set: sets) {
if (!setsDone.contains(set)) { if (!setsDone.contains(set)) {
set.removeSavedCards(); set.removeSavedCards();

View file

@ -27,10 +27,12 @@
*/ */
package mage.game.events; package mage.game.events;
import mage.constants.Zone;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import java.util.UUID; import java.util.UUID;
import mage.constants.Zone;
/** /**
* *
@ -46,7 +48,7 @@ public class GameEvent implements Serializable {
protected boolean flag; protected boolean flag;
protected String data; protected String data;
protected Zone zone; protected Zone zone;
protected ArrayList<UUID> appliedEffects = new ArrayList<>(); protected List<UUID> appliedEffects = new ArrayList<>();
protected UUID customEventType = null; protected UUID customEventType = null;
public enum EventType { public enum EventType {
@ -460,7 +462,7 @@ public class GameEvent implements Serializable {
* *
* @return * @return
*/ */
public ArrayList<UUID> getAppliedEffects() { public List<UUID> getAppliedEffects() {
return appliedEffects; return appliedEffects;
} }
@ -468,13 +470,13 @@ public class GameEvent implements Serializable {
return type == EventType.CUSTOM_EVENT && this.customEventType.equals(customEventType); return type == EventType.CUSTOM_EVENT && this.customEventType.equals(customEventType);
} }
public void addAppliedEffects(ArrayList<UUID> appliedEffects) { public void addAppliedEffects(List<UUID> appliedEffects) {
if (appliedEffects != null) { if (appliedEffects != null) {
this.appliedEffects.addAll(appliedEffects); this.appliedEffects.addAll(appliedEffects);
} }
} }
public void setAppliedEffects(ArrayList<UUID> appliedEffects) { public void setAppliedEffects(List<UUID> appliedEffects) {
if (appliedEffects != null) { if (appliedEffects != null) {
if (this.appliedEffects.isEmpty()) { if (this.appliedEffects.isEmpty()) {
this.appliedEffects = appliedEffects; // Use object refecence to handle that an replacement effect can only be once applied to an event this.appliedEffects = appliedEffects; // Use object refecence to handle that an replacement effect can only be once applied to an event

View file

@ -28,11 +28,12 @@
package mage.game.events; package mage.game.events;
import java.util.ArrayList;
import java.util.UUID;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.List;
import java.util.UUID;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
@ -50,7 +51,7 @@ public class ZoneChangeEvent extends GameEvent {
this.target = target; this.target = target;
} }
public ZoneChangeEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone, ArrayList<UUID> appliedEffects) { public ZoneChangeEvent(Permanent target, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone, List<UUID> appliedEffects) {
super(EventType.ZONE_CHANGE, target.getId(), sourceId, playerId); super(EventType.ZONE_CHANGE, target.getId(), sourceId, playerId);
this.fromZone = fromZone; this.fromZone = fromZone;
this.toZone = toZone; this.toZone = toZone;
@ -66,7 +67,7 @@ public class ZoneChangeEvent extends GameEvent {
this.toZone = toZone; this.toZone = toZone;
} }
public ZoneChangeEvent(UUID targetId, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone, ArrayList<UUID> appliedEffects) { public ZoneChangeEvent(UUID targetId, UUID sourceId, UUID playerId, Zone fromZone, Zone toZone, List<UUID> appliedEffects) {
super(EventType.ZONE_CHANGE, targetId, sourceId, playerId); super(EventType.ZONE_CHANGE, targetId, sourceId, playerId);
this.fromZone = fromZone; this.fromZone = fromZone;
this.toZone = toZone; this.toZone = toZone;

View file

@ -27,10 +27,6 @@
*/ */
package mage.game.permanent; package mage.game.permanent;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.MageObjectReference; import mage.MageObjectReference;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -41,6 +37,10 @@ import mage.game.Controllable;
import mage.game.Game; import mage.game.Game;
import mage.game.GameState; import mage.game.GameState;
import java.util.List;
import java.util.Set;
import java.util.UUID;
public interface Permanent extends Card, Controllable { public interface Permanent extends Card, Controllable {
void setControllerId(UUID controllerId); void setControllerId(UUID controllerId);
@ -129,7 +129,7 @@ public interface Permanent extends Card, Controllable {
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, List<UUID> appliedEffects);
/** /**
* used in combat only to deal damage at the same time * used in combat only to deal damage at the same time
@ -267,7 +267,7 @@ public interface Permanent extends Card, Controllable {
* *
* @return * @return
*/ */
HashSet<MageObjectReference> getDealtDamageByThisTurn(); Set<MageObjectReference> getDealtDamageByThisTurn();
/** /**
* Imprint some other card to this one. * Imprint some other card to this one.

View file

@ -27,7 +27,6 @@
*/ */
package mage.game.permanent; package mage.game.permanent;
import java.util.*;
import mage.MageObject; import mage.MageObject;
import mage.MageObjectReference; import mage.MageObjectReference;
import mage.ObjectColor; import mage.ObjectColor;
@ -56,6 +55,8 @@ import mage.players.Player;
import mage.util.GameLog; import mage.util.GameLog;
import mage.util.ThreadLocalStringBuilder; import mage.util.ThreadLocalStringBuilder;
import java.util.*;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -100,7 +101,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
protected boolean deathtouched; protected boolean deathtouched;
protected List<UUID> attachments = new ArrayList<>(); protected List<UUID> attachments = new ArrayList<>();
protected Map<String, List<UUID>> connectedCards = new HashMap<>(); protected Map<String, List<UUID>> connectedCards = new HashMap<>();
protected HashSet<MageObjectReference> dealtDamageByThisTurn; protected Set<MageObjectReference> dealtDamageByThisTurn;
protected UUID attachedTo; protected UUID attachedTo;
protected int attachedToZoneChangeCounter; protected int attachedToZoneChangeCounter;
protected MageObjectReference pairedPermanent; protected MageObjectReference pairedPermanent;
@ -695,7 +696,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} }
@Override @Override
public int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, ArrayList<UUID> appliedEffects) { public int damage(int damage, UUID sourceId, Game game, boolean combat, boolean preventable, List<UUID> appliedEffects) {
return damage(damage, sourceId, game, preventable, combat, false, appliedEffects); return damage(damage, sourceId, game, preventable, combat, false, appliedEffects);
} }
@ -709,7 +710,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
* method * method
* @return * @return
*/ */
private int damage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, ArrayList<UUID> appliedEffects) { private int damage(int damageAmount, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
int damageDone = 0; int damageDone = 0;
if (damageAmount > 0 && canDamage(game.getObject(sourceId), game)) { if (damageAmount > 0 && canDamage(game.getObject(sourceId), game)) {
if (this.isPlaneswalker()) { if (this.isPlaneswalker()) {
@ -794,7 +795,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
deathtouched = false; deathtouched = false;
} }
protected int damagePlaneswalker(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, ArrayList<UUID> appliedEffects) { protected int damagePlaneswalker(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
GameEvent event = new DamagePlaneswalkerEvent(objectId, sourceId, controllerId, damage, preventable, combat); GameEvent event = new DamagePlaneswalkerEvent(objectId, sourceId, controllerId, damage, preventable, combat);
event.setAppliedEffects(appliedEffects); event.setAppliedEffects(appliedEffects);
if (!game.replaceEvent(event)) { if (!game.replaceEvent(event)) {
@ -812,7 +813,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
return 0; return 0;
} }
protected int damageCreature(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, ArrayList<UUID> appliedEffects) { protected int damageCreature(int damage, UUID sourceId, Game game, boolean preventable, boolean combat, boolean markDamage, List<UUID> appliedEffects) {
GameEvent event = new DamageCreatureEvent(objectId, sourceId, controllerId, damage, preventable, combat); GameEvent event = new DamageCreatureEvent(objectId, sourceId, controllerId, damage, preventable, combat);
event.setAppliedEffects(appliedEffects); event.setAppliedEffects(appliedEffects);
if (!game.replaceEvent(event)) { if (!game.replaceEvent(event)) {
@ -1062,7 +1063,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
private boolean canAttackCheckRestrictionEffects(UUID defenderId, Game game) { private boolean canAttackCheckRestrictionEffects(UUID defenderId, Game game) {
//20101001 - 508.1c //20101001 - 508.1c
for (Map.Entry<RestrictionEffect, HashSet<Ability>> effectEntry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> effectEntry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
if (!effectEntry.getKey().canAttack(game)) { if (!effectEntry.getKey().canAttack(game)) {
return false; return false;
} }
@ -1090,7 +1091,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} }
//20101001 - 509.1b //20101001 - 509.1b
// check blocker restrictions // check blocker restrictions
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
if (!entry.getKey().canBlock(attacker, this, ability, game)) { if (!entry.getKey().canBlock(attacker, this, ability, game)) {
return false; return false;
@ -1098,7 +1099,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} }
} }
// check also attacker's restriction effects // check also attacker's restriction effects
for (Map.Entry<RestrictionEffect, HashSet<Ability>> restrictionEntry : game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> restrictionEntry : game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game).entrySet()) {
for (Ability ability : restrictionEntry.getValue()) { for (Ability ability : restrictionEntry.getValue()) {
if (!restrictionEntry.getKey().canBeBlocked(attacker, this, ability, game)) { if (!restrictionEntry.getKey().canBeBlocked(attacker, this, ability, game)) {
return false; return false;
@ -1115,7 +1116,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} }
//20101001 - 509.1b //20101001 - 509.1b
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
RestrictionEffect effect = entry.getKey(); RestrictionEffect effect = entry.getKey();
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
if (!effect.canBlock(null, this, ability, game)) { if (!effect.canBlock(null, this, ability, game)) {
@ -1136,7 +1137,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
*/ */
@Override @Override
public boolean canUseActivatedAbilities(Game game) { public boolean canUseActivatedAbilities(Game game) {
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
RestrictionEffect effect = entry.getKey(); RestrictionEffect effect = entry.getKey();
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
if (!effect.canUseActivatedAbilities(this, ability, game)) { if (!effect.canUseActivatedAbilities(this, ability, game)) {
@ -1150,7 +1151,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
@Override @Override
public boolean canTransform(Ability source, Game game) { public boolean canTransform(Ability source, Game game) {
if (transformable) { if (transformable) {
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> entry : game.getContinuousEffects().getApplicableRestrictionEffects(this, game).entrySet()) {
RestrictionEffect effect = entry.getKey(); RestrictionEffect effect = entry.getKey();
for (Ability ability : entry.getValue()) { for (Ability ability : entry.getValue()) {
if (!effect.canTransform(this, ability, game)) { if (!effect.canTransform(this, ability, game)) {
@ -1237,7 +1238,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} }
@Override @Override
public HashSet<MageObjectReference> getDealtDamageByThisTurn() { public Set<MageObjectReference> getDealtDamageByThisTurn() {
if (dealtDamageByThisTurn == null) { if (dealtDamageByThisTurn == null) {
return new HashSet<>(); return new HashSet<>();
} }
@ -1376,7 +1377,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} }
@Override @Override
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) { public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
Zone fromZone = game.getState().getZone(objectId); Zone fromZone = game.getState().getZone(objectId);
Player controller = game.getPlayer(controllerId); Player controller = game.getPlayer(controllerId);
if (controller != null) { if (controller != null) {
@ -1393,7 +1394,7 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} }
@Override @Override
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) { public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
Zone fromZone = game.getState().getZone(objectId); Zone fromZone = game.getState().getZone(objectId);
ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, ownerId, fromZone, Zone.EXILED, appliedEffects); ZoneChangeEvent event = new ZoneChangeEvent(this, sourceId, ownerId, fromZone, Zone.EXILED, appliedEffects);
ZoneChangeInfo.Exile info = new ZoneChangeInfo.Exile(event, exileId, name); ZoneChangeInfo.Exile info = new ZoneChangeInfo.Exile(event, exileId, name);

View file

@ -27,10 +27,6 @@
*/ */
package mage.game.stack; package mage.game.stack;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.Mana; import mage.Mana;
@ -62,6 +58,11 @@ import mage.game.permanent.PermanentCard;
import mage.players.Player; import mage.players.Player;
import mage.util.GameLog; import mage.util.GameLog;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
/** /**
* *
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
@ -732,7 +733,7 @@ public class Spell extends StackObjImpl implements Card {
} }
@Override @Override
public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag, ArrayList<UUID> appliedEffects) { public boolean moveToZone(Zone zone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
// 706.10a If a copy of a spell is in a zone other than the stack, it ceases to exist. // 706.10a If a copy of a spell is in a zone other than the stack, it ceases to exist.
// If a copy of a card is in any zone other than the stack or the battlefield, it ceases to exist. // If a copy of a card is in any zone other than the stack or the battlefield, it ceases to exist.
// These are state-based actions. See rule 704. // These are state-based actions. See rule 704.
@ -748,7 +749,7 @@ public class Spell extends StackObjImpl implements Card {
} }
@Override @Override
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, ArrayList<UUID> appliedEffects) { public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
return this.card.moveToExile(exileId, name, sourceId, game, appliedEffects); return this.card.moveToExile(exileId, name, sourceId, game, appliedEffects);
} }
@ -768,7 +769,7 @@ public class Spell extends StackObjImpl implements Card {
} }
@Override @Override
public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, ArrayList<UUID> appliedEffects) { public boolean putOntoBattlefield(Game game, Zone fromZone, UUID sourceId, UUID controllerId, boolean tapped, boolean facedown, List<UUID> appliedEffects) {
throw new UnsupportedOperationException("Not supported yet."); throw new UnsupportedOperationException("Not supported yet.");
} }
@ -865,7 +866,7 @@ public class Spell extends StackObjImpl implements Card {
} }
@Override @Override
public boolean addCounters(Counter counter, Ability source, Game game, ArrayList<UUID> appliedEffects) { public boolean addCounters(Counter counter, Ability source, Game game, List<UUID> appliedEffects) {
return card.addCounters(counter, source, game, appliedEffects); return card.addCounters(counter, source, game, appliedEffects);
} }

View file

@ -124,7 +124,7 @@ public interface Player extends MageItem, Copyable<Player> {
int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable); int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable);
int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects); int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects);
// to handle rule changing effects (613.10) // to handle rule changing effects (613.10)
boolean isCanLoseLife(); boolean isCanLoseLife();
@ -350,7 +350,7 @@ public interface Player extends MageItem, Copyable<Player> {
int drawCards(int num, Game game); int drawCards(int num, Game game);
int drawCards(int num, Game game, ArrayList<UUID> appliedEffects); int drawCards(int num, Game game, List<UUID> appliedEffects);
boolean cast(SpellAbility ability, Game game, boolean noMana); boolean cast(SpellAbility ability, Game game, boolean noMana);
@ -674,7 +674,7 @@ public interface Player extends MageItem, Copyable<Player> {
boolean moveCards(Card card, Zone toZone, Ability source, Game game); boolean moveCards(Card card, Zone toZone, Ability source, Game game);
boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects); boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects);
boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game); boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game);
@ -694,7 +694,7 @@ public interface Player extends MageItem, Copyable<Player> {
* @param appliedEffects * @param appliedEffects
* @return * @return
*/ */
boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects); boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects);
boolean moveCardsToExile(Card card, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName); boolean moveCardsToExile(Card card, Ability source, Game game, boolean withName, UUID exileId, String exileZoneName);

View file

@ -27,10 +27,6 @@
*/ */
package mage.players; package mage.players;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import mage.ConditionalMana; import mage.ConditionalMana;
import mage.MageObject; import mage.MageObject;
import mage.Mana; import mage.Mana;
@ -91,6 +87,11 @@ import mage.util.GameLog;
import mage.util.RandomUtil; import mage.util.RandomUtil;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
public abstract class PlayerImpl implements Player, Serializable { public abstract class PlayerImpl implements Player, Serializable {
private static final Logger logger = Logger.getLogger(PlayerImpl.class); private static final Logger logger = Logger.getLogger(PlayerImpl.class);
@ -621,7 +622,7 @@ public abstract class PlayerImpl implements Player, Serializable {
} }
@Override @Override
public int drawCards(int num, Game game, ArrayList<UUID> appliedEffects) { public int drawCards(int num, Game game, List<UUID> appliedEffects) {
return game.doAction(new MageDrawAction(this, num, appliedEffects)); return game.doAction(new MageDrawAction(this, num, appliedEffects));
} }
@ -1472,8 +1473,8 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override @Override
public void untap(Game game) { public void untap(Game game) {
// create list of all "notMoreThan" effects to track which one are consumed // create list of all "notMoreThan" effects to track which one are consumed
HashMap<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> notMoreThanEffectsUsage = new HashMap<>(); HashMap<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffectsUsage = new HashMap<>();
for (Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>> restrictionEffect : game.getContinuousEffects().getApplicableRestrictionUntapNotMoreThanEffects(this, game).entrySet()) { for (Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>> restrictionEffect : game.getContinuousEffects().getApplicableRestrictionUntapNotMoreThanEffects(this, game).entrySet()) {
notMoreThanEffectsUsage.put(restrictionEffect, restrictionEffect.getKey().getNumber()); notMoreThanEffectsUsage.put(restrictionEffect, restrictionEffect.getKey().getNumber());
} }
@ -1497,7 +1498,7 @@ public abstract class PlayerImpl implements Player, Serializable {
do { do {
playerCanceledSelection = false; playerCanceledSelection = false;
// select permanents to untap to consume the "notMoreThan" effects // select permanents to untap to consume the "notMoreThan" effects
for (Map.Entry<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> handledEntry : notMoreThanEffectsUsage.entrySet()) { for (Map.Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> handledEntry : notMoreThanEffectsUsage.entrySet()) {
// select a permanent to untap for this entry // select a permanent to untap for this entry
int numberToUntap = handledEntry.getValue(); int numberToUntap = handledEntry.getValue();
if (numberToUntap > 0) { if (numberToUntap > 0) {
@ -1535,7 +1536,7 @@ public abstract class PlayerImpl implements Player, Serializable {
// don't allow to select same permanent twice // don't allow to select same permanent twice
filter.add(Predicates.not(new PermanentIdPredicate(selectedPermanent.getId()))); filter.add(Predicates.not(new PermanentIdPredicate(selectedPermanent.getId())));
// reduce available untap numbers from other "UntapNotMoreThan" effects if selected permanent applies to their filter too // reduce available untap numbers from other "UntapNotMoreThan" effects if selected permanent applies to their filter too
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) { for (Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
if (notMoreThanEffect.getValue() > 0 && notMoreThanEffect.getKey().getKey().getFilter().match(selectedPermanent, game)) { if (notMoreThanEffect.getValue() > 0 && notMoreThanEffect.getKey().getKey().getFilter().match(selectedPermanent, game)) {
notMoreThanEffect.setValue(notMoreThanEffect.getValue() - 1); notMoreThanEffect.setValue(notMoreThanEffect.getValue() - 1);
} }
@ -1574,7 +1575,7 @@ public abstract class PlayerImpl implements Player, Serializable {
boolean doUntap = true; boolean doUntap = true;
if (!selectedToUntap.contains(permanent)) { if (!selectedToUntap.contains(permanent)) {
// if the permanent is covered by one of the restriction effects, don't untap it // if the permanent is covered by one of the restriction effects, don't untap it
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) { for (Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
if (notMoreThanEffect.getKey().getKey().getFilter().match(permanent, game)) { if (notMoreThanEffect.getKey().getKey().getFilter().match(permanent, game)) {
doUntap = false; doUntap = false;
break; break;
@ -1601,14 +1602,14 @@ public abstract class PlayerImpl implements Player, Serializable {
} }
} }
private List<Permanent> getPermanentsThatCanBeUntapped(Game game, List<Permanent> canBeUntapped, RestrictionUntapNotMoreThanEffect handledEffect, HashMap<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> notMoreThanEffectsUsage) { private List<Permanent> getPermanentsThatCanBeUntapped(Game game, List<Permanent> canBeUntapped, RestrictionUntapNotMoreThanEffect handledEffect, Map<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffectsUsage) {
List<Permanent> leftForUntap = new ArrayList<>(); List<Permanent> leftForUntap = new ArrayList<>();
// select permanents that can still be untapped // select permanents that can still be untapped
for (Permanent permanent : canBeUntapped) { for (Permanent permanent : canBeUntapped) {
if (handledEffect.getFilter().match(permanent, game)) { // matches the restricted permanents of handled entry if (handledEffect.getFilter().match(permanent, game)) { // matches the restricted permanents of handled entry
boolean canBeSelected = true; boolean canBeSelected = true;
// check if the permanent is restriced by another restriction that has left no permanent // check if the permanent is restriced by another restriction that has left no permanent
for (Entry<Entry<RestrictionUntapNotMoreThanEffect, HashSet<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) { for (Entry<Entry<RestrictionUntapNotMoreThanEffect, Set<Ability>>, Integer> notMoreThanEffect : notMoreThanEffectsUsage.entrySet()) {
if (notMoreThanEffect.getKey().getKey().getFilter().match(permanent, game) && notMoreThanEffect.getValue() == 0) { if (notMoreThanEffect.getKey().getKey().getFilter().match(permanent, game) && notMoreThanEffect.getValue() == 0) {
canBeSelected = false; canBeSelected = false;
break; break;
@ -1763,12 +1764,12 @@ public abstract class PlayerImpl implements Player, Serializable {
} }
@Override @Override
public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects) { public int damage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects) {
return doDamage(damage, sourceId, game, combatDamage, preventable, appliedEffects); return doDamage(damage, sourceId, game, combatDamage, preventable, appliedEffects);
} }
@SuppressWarnings({"null", "ConstantConditions"}) @SuppressWarnings({"null", "ConstantConditions"})
private int doDamage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, ArrayList<UUID> appliedEffects) { private int doDamage(int damage, UUID sourceId, Game game, boolean combatDamage, boolean preventable, List<UUID> appliedEffects) {
if (damage > 0 && canDamage(game.getObject(sourceId), game)) { if (damage > 0 && canDamage(game.getObject(sourceId), game)) {
GameEvent event = new DamagePlayerEvent(playerId, sourceId, playerId, damage, preventable, combatDamage); GameEvent event = new DamagePlayerEvent(playerId, sourceId, playerId, damage, preventable, combatDamage);
event.setAppliedEffects(appliedEffects); event.setAppliedEffects(appliedEffects);
@ -3093,7 +3094,7 @@ public abstract class PlayerImpl implements Player, Serializable {
} }
@Override @Override
public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) { public boolean moveCards(Card card, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
Set<Card> cardList = new HashSet<>(); Set<Card> cardList = new HashSet<>();
if (card != null) { if (card != null) {
cardList.add(card); cardList.add(card);
@ -3112,7 +3113,7 @@ public abstract class PlayerImpl implements Player, Serializable {
} }
@Override @Override
public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, ArrayList<UUID> appliedEffects) { public boolean moveCards(Set<Card> cards, Zone toZone, Ability source, Game game, boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects) {
if (cards.isEmpty()) { if (cards.isEmpty()) {
return true; return true;
} }

View file

@ -1,16 +1,14 @@
package mage.util.trace; package mage.util.trace;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.StaticAbility; import mage.abilities.StaticAbility;
import mage.abilities.effects.ContinuousEffectsList; import mage.abilities.effects.ContinuousEffectsList;
import mage.abilities.effects.RestrictionEffect; import mage.abilities.effects.RestrictionEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.ReachAbility;
import mage.abilities.keyword.CantBeBlockedSourceAbility; import mage.abilities.keyword.CantBeBlockedSourceAbility;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.IntimidateAbility;
import mage.abilities.keyword.ReachAbility;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.combat.Combat; import mage.game.combat.Combat;
@ -18,9 +16,7 @@ import mage.game.combat.CombatGroup;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.util.UUID; import java.util.*;
import mage.abilities.keyword.IntimidateAbility;
import mage.constants.CardType;
/** /**
* @author magenoxx_at_gmail.com * @author magenoxx_at_gmail.com
@ -146,8 +142,8 @@ public final class TraceUtil {
log.error(prefix+"Restriction effects:"); log.error(prefix+"Restriction effects:");
log.error(prefix+" Applied to ATTACKER:"); log.error(prefix+" Applied to ATTACKER:");
HashMap<RestrictionEffect, HashSet<Ability>> attackerResEffects = game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game); Map<RestrictionEffect, Set<Ability>> attackerResEffects = game.getContinuousEffects().getApplicableRestrictionEffects(attacker, game);
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : attackerResEffects.entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> entry : attackerResEffects.entrySet()) {
log.error(prefix+" " + entry.getKey()); log.error(prefix+" " + entry.getKey());
log.error(prefix+" id=" + entry.getKey().getId()); log.error(prefix+" id=" + entry.getKey().getId());
for (Ability ability: entry.getValue()) { for (Ability ability: entry.getValue()) {
@ -156,8 +152,8 @@ public final class TraceUtil {
} }
log.error(prefix+" Applied to BLOCKER:"); log.error(prefix+" Applied to BLOCKER:");
if (blocker != null) { if (blocker != null) {
HashMap<RestrictionEffect, HashSet<Ability>> blockerResEffects = game.getContinuousEffects().getApplicableRestrictionEffects(blocker, game); Map<RestrictionEffect, Set<Ability>> blockerResEffects = game.getContinuousEffects().getApplicableRestrictionEffects(blocker, game);
for (Map.Entry<RestrictionEffect, HashSet<Ability>> entry : blockerResEffects.entrySet()) { for (Map.Entry<RestrictionEffect, Set<Ability>> entry : blockerResEffects.entrySet()) {
log.error(prefix+" " + entry.getKey()); log.error(prefix+" " + entry.getKey());
log.error(prefix+" id=" + entry.getKey().getId()); log.error(prefix+" id=" + entry.getKey().getId());
for (Ability ability: entry.getValue()) { for (Ability ability: entry.getValue()) {