From cde9957f54c5128118baf3d25a90b03a0dc5a127 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Wed, 18 Dec 2019 22:44:42 +0400 Subject: [PATCH] * UI: added playable card marks in look-at windows; --- .../src/main/java/mage/client/cards/Card.java | 2 +- .../main/java/mage/client/game/GamePanel.java | 32 +++-- .../java/mage/client/game/PlayerPanelExt.java | 6 +- .../java/mage/client/util/CardsViewUtil.java | 4 +- .../src/main/java/mage/view/CardView.java | 46 ++------ .../src/main/java/mage/view/EmblemView.java | 13 +- .../src/main/java/mage/view/GameView.java | 11 +- .../src/main/java/mage/view/PlaneView.java | 13 +- .../java/mage/view/SelectableObjectView.java | 6 +- .../main/java/mage/view/SimpleCardView.java | 70 ++++++++++- Mage.Sets/src/mage/cards/w/WordOfCommand.java | 2 +- .../java/org/mage/test/player/TestPlayer.java | 2 +- .../java/org/mage/test/stub/PlayerStub.java | 2 +- Mage/src/main/java/mage/players/Player.java | 2 +- .../main/java/mage/players/PlayerImpl.java | 111 +++++++++--------- 15 files changed, 200 insertions(+), 122 deletions(-) diff --git a/Mage.Client/src/main/java/mage/client/cards/Card.java b/Mage.Client/src/main/java/mage/client/cards/Card.java index cde4acf2de..2b2ca38dba 100644 --- a/Mage.Client/src/main/java/mage/client/cards/Card.java +++ b/Mage.Client/src/main/java/mage/client/cards/Card.java @@ -517,7 +517,7 @@ public class Card extends MagePermanent implements MouseMotionListener, MouseLis } @Override - public void setSelected(boolean selected) { + public void setSelected(boolean isSelected) { } @Override diff --git a/Mage.Client/src/main/java/mage/client/game/GamePanel.java b/Mage.Client/src/main/java/mage/client/game/GamePanel.java index 5de5298eb3..0b2cf483d3 100644 --- a/Mage.Client/src/main/java/mage/client/game/GamePanel.java +++ b/Mage.Client/src/main/java/mage/client/game/GamePanel.java @@ -1205,11 +1205,11 @@ public final class GamePanel extends javax.swing.JPanel { needSelectable = new HashSet<>(); } - Set needPlayable; + Map needPlayable; if (showPlayable && gameView.getCanPlayObjects() != null) { needPlayable = gameView.getCanPlayObjects(); } else { - needPlayable = new HashSet<>(); + needPlayable = new HashMap<>(); } if (needChoosen.isEmpty() && needSelectable.isEmpty() && needPlayable.isEmpty()) { @@ -1225,8 +1225,9 @@ public final class GamePanel extends javax.swing.JPanel { if (needChoosen.contains(card.getId())) { card.setSelected(true); } - if (needPlayable.contains(card.getId())) { + if (needPlayable.containsKey(card.getId())) { card.setPlayable(true); + card.setPlayableAmount(needPlayable.get(card.getId())); } } } @@ -1254,8 +1255,9 @@ public final class GamePanel extends javax.swing.JPanel { if (needChoosen.contains(perm.getKey())) { perm.getValue().setSelected(true); } - if (needPlayable.contains(perm.getKey())) { + if (needPlayable.containsKey(perm.getKey())) { perm.getValue().setPlayable(true); + perm.getValue().setPlayableAmount(needPlayable.get(perm.getKey())); } } } @@ -1271,8 +1273,9 @@ public final class GamePanel extends javax.swing.JPanel { if (needChoosen.contains(card.getKey())) { card.getValue().setSelected(true); } - if (needPlayable.contains(card.getKey())) { + if (needPlayable.containsKey(card.getKey())) { card.getValue().setPlayable(true); + card.getValue().setPlayableAmount(needPlayable.get(card.getKey())); } } } @@ -1288,8 +1291,9 @@ public final class GamePanel extends javax.swing.JPanel { if (needChoosen.contains(card.getKey())) { card.getValue().setSelected(true); } - if (needPlayable.contains(card.getKey())) { + if (needPlayable.containsKey(card.getKey())) { card.getValue().setPlayable(true); + card.getValue().setPlayableAmount(needPlayable.get(card.getKey())); } } } @@ -1305,8 +1309,9 @@ public final class GamePanel extends javax.swing.JPanel { if (needChoosen.contains(com.getId())) { com.setSelected(true); } - if (needPlayable.contains(com.getId())) { + if (needPlayable.containsKey(com.getId())) { com.setPlayable(true); + com.setPlayableAmount(needPlayable.get(com.getId())); } } } @@ -1321,8 +1326,19 @@ public final class GamePanel extends javax.swing.JPanel { if (needChoosen.contains(card.getKey())) { card.getValue().setSelected(true); } - if (needPlayable.contains(card.getKey())) { + if (needPlayable.containsKey(card.getKey())) { card.getValue().setPlayable(true); + card.getValue().setPlayableAmount(needPlayable.get(card.getKey())); + } + } + } + + // looked at + for (LookedAtView look : gameView.getLookedAt()) { + for (Map.Entry card : look.getCards().entrySet()) { + if (needPlayable.containsKey(card.getKey())) { + card.getValue().setPlayable(true); + card.getValue().setPlayableAmount(needPlayable.get(card.getKey())); } } } diff --git a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java index f8b2065e1e..f0c8085cc6 100644 --- a/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java +++ b/Mage.Client/src/main/java/mage/client/game/PlayerPanelExt.java @@ -142,7 +142,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { // can play if (gameView != null && gameView.getCanPlayObjects() != null && !gameView.getCanPlayObjects().isEmpty()) { for (CardView card : cards) { - if (gameView.getCanPlayObjects().contains(card.getId())) { + if (gameView.getCanPlayObjects().containsKey(card.getId())) { return true; } } @@ -239,7 +239,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { Color commandColor = Color.BLACK; for (CommandObjectView com : player.getCommandObjectList()) { - if (game != null && game.getCanPlayObjects() != null && game.getCanPlayObjects().contains(com.getId())) { + if (game != null && game.getCanPlayObjects() != null && game.getCanPlayObjects().containsKey(com.getId())) { commandColor = activeValueColor; break; } @@ -269,7 +269,7 @@ public class PlayerPanelExt extends javax.swing.JPanel { if (!MageFrame.isLite()) { int id = player.getUserData().getAvatarId(); - if (!(id >= 1000) && (id <= 0 || (id <= MIN_AVATAR_ID && id > MAX_AVATAR_ID))) { + if (!(id > 1000) && (id != 64) && (id < MIN_AVATAR_ID || id > MAX_AVATAR_ID)) { id = DEFAULT_AVATAR_ID; } if (id != avatarId) { diff --git a/Mage.Client/src/main/java/mage/client/util/CardsViewUtil.java b/Mage.Client/src/main/java/mage/client/util/CardsViewUtil.java index 727a19adf9..941756d7bc 100644 --- a/Mage.Client/src/main/java/mage/client/util/CardsViewUtil.java +++ b/Mage.Client/src/main/java/mage/client/util/CardsViewUtil.java @@ -20,7 +20,7 @@ public final class CardsViewUtil { CardInfo cardInfo = CardRepository.instance.findCard(simple.getExpansionSetCode(), simple.getCardNumber()); Card card = cardInfo != null ? cardInfo.getMockCard() : null; if (card != null) { - cards.put(simple.getId(), new CardView(card, simple.getId())); + cards.put(simple.getId(), new CardView(card, simple)); } } @@ -39,7 +39,7 @@ public final class CardsViewUtil { loadedCards.put(key, card); } if (card != null) { - cards.put(simple.getId(), new CardView(card, simple.getId())); + cards.put(simple.getId(), new CardView(card, simple)); } } diff --git a/Mage.Common/src/main/java/mage/view/CardView.java b/Mage.Common/src/main/java/mage/view/CardView.java index e8e89b9d70..0e07c77f15 100644 --- a/Mage.Common/src/main/java/mage/view/CardView.java +++ b/Mage.Common/src/main/java/mage/view/CardView.java @@ -32,7 +32,7 @@ import java.util.stream.Collectors; /** * @author BetaSteward_at_googlemail.com */ -public class CardView extends SimpleCardView implements SelectableObjectView { +public class CardView extends SimpleCardView { private static final long serialVersionUID = 1L; @@ -104,9 +104,6 @@ public class CardView extends SimpleCardView implements SelectableObjectView { protected boolean rotate; protected boolean hideInfo; // controls if the tooltip window is shown (eg. controlled face down morph card) - protected boolean isPlayable; - protected boolean isChoosable; - protected boolean selected; protected boolean canAttack; protected boolean canBlock; protected boolean inViewerOnly; @@ -117,9 +114,13 @@ public class CardView extends SimpleCardView implements SelectableObjectView { this(card, null, false); } - public CardView(Card card, UUID cardId) { + public CardView(Card card, SimpleCardView simpleCardView) { this(card, null, false); - this.id = cardId; + this.id = simpleCardView.getId(); + + this.isPlayable = simpleCardView.isPlayable; + this.isChoosable = simpleCardView.isChoosable; + this.isSelected = simpleCardView.isSelected; } public CardView(Card card, Game game, UUID cardId) { @@ -128,10 +129,12 @@ public class CardView extends SimpleCardView implements SelectableObjectView { } public CardView(CardView cardView) { - super(cardView.id, cardView.expansionSetCode, cardView.cardNumber, cardView.usesVariousArt, cardView.tokenSetCode, cardView.gameObject, cardView.tokenDescriptor); + super(cardView); this.originalCard = cardView.originalCard; + // generetate new ID this.id = UUID.randomUUID(); + this.parentId = cardView.parentId; this.name = cardView.name; this.displayName = cardView.displayName; @@ -198,9 +201,6 @@ public class CardView extends SimpleCardView implements SelectableObjectView { this.rotate = cardView.rotate; this.hideInfo = cardView.hideInfo; - this.isPlayable = cardView.isPlayable; - this.isChoosable = cardView.isChoosable; - this.selected = cardView.selected; this.canAttack = cardView.canAttack; this.canBlock = cardView.canBlock; this.inViewerOnly = cardView.inViewerOnly; @@ -468,8 +468,6 @@ public class CardView extends SimpleCardView implements SelectableObjectView { // Get starting loyalty this.startingLoyalty = "" + card.getStartingLoyalty(); - - } public CardView(MageObject object) { @@ -964,30 +962,6 @@ public class CardView extends SimpleCardView implements SelectableObjectView { return hideInfo; } - public boolean isPlayable() { - return isPlayable; - } - - public void setPlayable(boolean isPlayable) { - this.isPlayable = isPlayable; - } - - public boolean isChoosable() { - return isChoosable; - } - - public void setChoosable(boolean isChoosable) { - this.isChoosable = isChoosable; - } - - public boolean isSelected() { - return selected; - } - - public void setSelected(boolean selected) { - this.selected = selected; - } - public boolean isCanAttack() { return canAttack; } diff --git a/Mage.Common/src/main/java/mage/view/EmblemView.java b/Mage.Common/src/main/java/mage/view/EmblemView.java index 2d3e11c96d..759050d58a 100644 --- a/Mage.Common/src/main/java/mage/view/EmblemView.java +++ b/Mage.Common/src/main/java/mage/view/EmblemView.java @@ -17,6 +17,7 @@ public class EmblemView implements CommandObjectView, Serializable { protected String expansionSetCode; protected List rules; protected boolean isPlayable = false; + protected int playableAmount = 0; public EmblemView(Emblem emblem, Card sourceCard) { this.id = emblem.getId(); @@ -67,6 +68,16 @@ public class EmblemView implements CommandObjectView, Serializable { this.isPlayable = isPlayable; } + @Override + public void setPlayableAmount(int playableAmount) { + this.playableAmount = playableAmount; + } + + @Override + public int getPlayableAmount() { + return playableAmount; + } + @Override public boolean isChoosable() { // unsupported @@ -85,7 +96,7 @@ public class EmblemView implements CommandObjectView, Serializable { } @Override - public void setSelected(boolean selected) { + public void setSelected(boolean isSelected) { // unsupported } } diff --git a/Mage.Common/src/main/java/mage/view/GameView.java b/Mage.Common/src/main/java/mage/view/GameView.java index f2e920408a..b7ef72500f 100644 --- a/Mage.Common/src/main/java/mage/view/GameView.java +++ b/Mage.Common/src/main/java/mage/view/GameView.java @@ -26,7 +26,10 @@ import mage.watchers.common.CastSpellLastTurnWatcher; import org.apache.log4j.Logger; import java.io.Serializable; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; /** * @author BetaSteward_at_googlemail.com @@ -39,7 +42,7 @@ public class GameView implements Serializable { private final int priorityTime; private final List players = new ArrayList<>(); private CardsView hand; - private Set canPlayObjects; + private Map canPlayObjects; private Map opponentHands; private Map watchedHands; private final CardsView stack = new CardsView(); @@ -300,11 +303,11 @@ public class GameView implements Serializable { return isPlayer; } - public Set getCanPlayObjects() { + public Map getCanPlayObjects() { return canPlayObjects; } - public void setCanPlayObjects(Set canPlayObjects) { + public void setCanPlayObjects(Map canPlayObjects) { this.canPlayObjects = canPlayObjects; } diff --git a/Mage.Common/src/main/java/mage/view/PlaneView.java b/Mage.Common/src/main/java/mage/view/PlaneView.java index 702e9577c0..9f4ea2040c 100644 --- a/Mage.Common/src/main/java/mage/view/PlaneView.java +++ b/Mage.Common/src/main/java/mage/view/PlaneView.java @@ -18,6 +18,7 @@ public class PlaneView implements CommandObjectView, Serializable { protected List rules; protected boolean isPlayable = false; + protected int playableAmount = 0; public PlaneView(Plane plane, Card sourceCard) { this.id = plane.getId(); @@ -67,6 +68,16 @@ public class PlaneView implements CommandObjectView, Serializable { this.isPlayable = isPlayable; } + @Override + public void setPlayableAmount(int playableAmount) { + this.playableAmount = playableAmount; + } + + @Override + public int getPlayableAmount() { + return playableAmount; + } + @Override public boolean isChoosable() { // unsupported @@ -85,7 +96,7 @@ public class PlaneView implements CommandObjectView, Serializable { } @Override - public void setSelected(boolean selected) { + public void setSelected(boolean isSelected) { // unsupported } } diff --git a/Mage.Common/src/main/java/mage/view/SelectableObjectView.java b/Mage.Common/src/main/java/mage/view/SelectableObjectView.java index d1ce8d0ec4..57004aec10 100644 --- a/Mage.Common/src/main/java/mage/view/SelectableObjectView.java +++ b/Mage.Common/src/main/java/mage/view/SelectableObjectView.java @@ -9,11 +9,15 @@ public interface SelectableObjectView { void setPlayable(boolean isPlayable); + void setPlayableAmount(int playableAmount); + + int getPlayableAmount(); + boolean isChoosable(); void setChoosable(boolean isChoosable); boolean isSelected(); - void setSelected(boolean selected); + void setSelected(boolean isSelected); } diff --git a/Mage.Common/src/main/java/mage/view/SimpleCardView.java b/Mage.Common/src/main/java/mage/view/SimpleCardView.java index 4d56e845f6..06660d2ae0 100644 --- a/Mage.Common/src/main/java/mage/view/SimpleCardView.java +++ b/Mage.Common/src/main/java/mage/view/SimpleCardView.java @@ -1,5 +1,3 @@ - - package mage.view; import com.google.gson.annotations.Expose; @@ -8,10 +6,9 @@ import java.io.Serializable; import java.util.UUID; /** - * * @author BetaSteward_at_googlemail.com */ -public class SimpleCardView implements Serializable { +public class SimpleCardView implements Serializable, SelectableObjectView { @Expose protected UUID id; protected String expansionSetCode; @@ -21,9 +18,30 @@ public class SimpleCardView implements Serializable { protected boolean usesVariousArt; protected boolean gameObject; + protected boolean isPlayable; + protected boolean isChoosable; + protected boolean isSelected; + protected int playableAmount; // playable abilities count on object + + public SimpleCardView(final SimpleCardView view) { + this.id = view.id; + this.expansionSetCode = view.expansionSetCode; + this.tokenSetCode = view.tokenSetCode; + this.tokenDescriptor = view.tokenDescriptor; + this.cardNumber = view.cardNumber; + this.usesVariousArt = view.usesVariousArt; + this.gameObject = view.gameObject; + + this.isPlayable = view.isPlayable; + this.isChoosable = view.isChoosable; + this.isSelected = view.isSelected; + this.playableAmount = view.playableAmount; + } + public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, String tokenDescriptor) { this(id, expansionSetCode, cardNumber, usesVariousArt, tokenSetCode, false, tokenDescriptor); } + public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, boolean isGameObject, String tokenDescriptor) { this.id = id; this.expansionSetCode = expansionSetCode; @@ -53,12 +71,52 @@ public class SimpleCardView implements Serializable { public String getTokenSetCode() { return tokenSetCode; } - + public String getTokenDescriptor() { return tokenDescriptor; } public boolean isGameObject() { return gameObject; - } + } + + @Override + public boolean isPlayable() { + return isPlayable; + } + + @Override + public void setPlayable(boolean isPlayable) { + this.isPlayable = isPlayable; + } + + @Override + public void setPlayableAmount(int playableAmount) { + this.playableAmount = playableAmount; + } + + @Override + public int getPlayableAmount() { + return playableAmount; + } + + @Override + public boolean isChoosable() { + return isChoosable; + } + + @Override + public void setChoosable(boolean isChoosable) { + this.isChoosable = isChoosable; + } + + @Override + public boolean isSelected() { + return isSelected; + } + + @Override + public void setSelected(boolean isSelected) { + this.isSelected = isSelected; + } } diff --git a/Mage.Sets/src/mage/cards/w/WordOfCommand.java b/Mage.Sets/src/mage/cards/w/WordOfCommand.java index 1feced2313..8dbd48ff5c 100644 --- a/Mage.Sets/src/mage/cards/w/WordOfCommand.java +++ b/Mage.Sets/src/mage/cards/w/WordOfCommand.java @@ -182,7 +182,7 @@ class WordOfCommandEffect extends OneShotEffect { } else { // Word of Command allows the chosen card to be played "as if it had flash" so we need to invoke such effect to bypass the check AsThoughEffectImpl effect2 = new WordOfCommandTestFlashEffect(); game.addEffect(effect2, source); - if (targetPlayer.getPlayableObjects(game, Zone.HAND).contains(card.getId())) { + if (targetPlayer.getPlayableObjects(game, Zone.HAND).containsKey(card.getId())) { canPlay = true; } for (AsThoughEffect eff : game.getContinuousEffects().getApplicableAsThoughEffects(AsThoughEffectType.CAST_AS_INSTANT, game)) { diff --git a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java index 5674010fb7..710cadd134 100644 --- a/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java +++ b/Mage.Tests/src/test/java/org/mage/test/player/TestPlayer.java @@ -2899,7 +2899,7 @@ public class TestPlayer implements Player { } @Override - public Set getPlayableObjects(Game game, Zone zone) { + public Map getPlayableObjects(Game game, Zone zone) { return computerPlayer.getPlayableObjects(game, zone); } diff --git a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java index d604b41e58..0a570d788c 100644 --- a/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java +++ b/Mage.Tests/src/test/java/org/mage/test/stub/PlayerStub.java @@ -1048,7 +1048,7 @@ public class PlayerStub implements Player { } @Override - public Set getPlayableObjects(Game game, Zone zone) { + public Map getPlayableObjects(Game game, Zone zone) { return null; } diff --git a/Mage/src/main/java/mage/players/Player.java b/Mage/src/main/java/mage/players/Player.java index 0bc22dbc94..21c1c4ec00 100644 --- a/Mage/src/main/java/mage/players/Player.java +++ b/Mage/src/main/java/mage/players/Player.java @@ -637,7 +637,7 @@ public interface Player extends MageItem, Copyable { List getPlayableOptions(Ability ability, Game game); - Set getPlayableObjects(Game game, Zone zone); + Map getPlayableObjects(Game game, Zone zone); LinkedHashMap getUseableActivatedAbilities(MageObject object, Zone zone, Game game); diff --git a/Mage/src/main/java/mage/players/PlayerImpl.java b/Mage/src/main/java/mage/players/PlayerImpl.java index 2ecee9f9cf..f063be29e2 100644 --- a/Mage/src/main/java/mage/players/PlayerImpl.java +++ b/Mage/src/main/java/mage/players/PlayerImpl.java @@ -1,9 +1,6 @@ package mage.players; import com.google.common.collect.ImmutableMap; -import java.io.Serializable; -import java.util.*; -import java.util.Map.Entry; import mage.ConditionalMana; import mage.MageObject; import mage.MageObjectReference; @@ -68,6 +65,10 @@ import mage.util.GameLog; import mage.util.RandomUtil; import org.apache.log4j.Logger; +import java.io.Serializable; +import java.util.*; +import java.util.Map.Entry; + public abstract class PlayerImpl implements Player, Serializable { private static final Logger logger = Logger.getLogger(PlayerImpl.class); @@ -618,7 +619,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (abilities.containsKey(HexproofAbility.getInstance().getId())) { if (sourceControllerId != null && this.hasOpponent(sourceControllerId, game) && null == game.getContinuousEffects().asThough(this.getId(), - AsThoughEffectType.HEXPROOF, null, sourceControllerId, game)) { + AsThoughEffectType.HEXPROOF, null, sourceControllerId, game)) { return false; } } @@ -626,7 +627,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (abilities.containsKey(HexproofFromWhiteAbility.getInstance().getId())) { if (sourceControllerId != null && this.hasOpponent(sourceControllerId, game) && null == game.getContinuousEffects().asThough(this.getId(), - AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) + AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) && source.getColor(game).isWhite()) { return false; } @@ -635,7 +636,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (abilities.containsKey(HexproofFromBlueAbility.getInstance().getId())) { if (sourceControllerId != null && this.hasOpponent(sourceControllerId, game) && null == game.getContinuousEffects().asThough(this.getId(), - AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) + AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) && source.getColor(game).isBlue()) { return false; } @@ -644,7 +645,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (abilities.containsKey(HexproofFromBlackAbility.getInstance().getId())) { if (sourceControllerId != null && this.hasOpponent(sourceControllerId, game) && null == game.getContinuousEffects().asThough(this.getId(), - AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) + AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) && source.getColor(game).isBlack()) { return false; } @@ -653,7 +654,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (abilities.containsKey(HexproofFromMonocoloredAbility.getInstance().getId())) { if (sourceControllerId != null && this.hasOpponent(sourceControllerId, game) && null == game.getContinuousEffects().asThough(this.getId(), - AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) + AsThoughEffectType.HEXPROOF, null, sourceControllerId, game) && !source.getColor(game).isColorless() && !source.getColor(game).isMulticolored()) { return false; @@ -696,7 +697,7 @@ public abstract class PlayerImpl implements Player, Serializable { game.informPlayers(getLogName() + " discards down to " + this.maxHandSize + (this.maxHandSize == 1 - ? " hand card" : " hand cards")); + ? " hand card" : " hand cards")); } discard(hand.size() - this.maxHandSize, null, game); } @@ -814,7 +815,7 @@ public abstract class PlayerImpl implements Player, Serializable { if (card != null) { GameEvent gameEvent = GameEvent.getEvent(GameEvent.EventType.DISCARD_CARD, card.getId(), source == null - ? null : source.getSourceId(), playerId); + ? null : source.getSourceId(), playerId); gameEvent.setFlag(source != null); // event from effect or from cost (source == null) if (!game.replaceEvent(gameEvent, source)) { // write info to game log first so game log infos from triggered or replacement effects follow in the game log @@ -829,7 +830,7 @@ public abstract class PlayerImpl implements Player, Serializable { // So discard is also successful if card is moved to another zone by replacement effect! game.fireEvent(GameEvent.getEvent(GameEvent.EventType.DISCARDED_CARD, card.getId(), source == null - ? null : source.getSourceId(), playerId)); + ? null : source.getSourceId(), playerId)); return true; } } @@ -1517,7 +1518,7 @@ public abstract class PlayerImpl implements Player, Serializable { // Also called on the whole split card but only passing the fuse ability and other whole-split-card shared abilities // as candidates. private void getUseableActivatedAbilitiesHalfImpl(MageObject object, Zone zone, Game game, Abilities candidateAbilites, - LinkedHashMap output) { + LinkedHashMap output) { boolean canUse = !(object instanceof Permanent) || ((Permanent) object).canUseActivatedAbilities(game); ManaOptions availableMana = null; // ManaOptions availableMana = getManaAvailable(game); // can only be activated if mana calculation works flawless otherwise player can't play spells they could play if calculation would work correctly @@ -1566,10 +1567,10 @@ public abstract class PlayerImpl implements Player, Serializable { != null // if anyone sees an issue with this code, please report it. Worked in my testing. || game.getContinuousEffects().asThough(object.getId(), - AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, - ability, - this.getId(), - game) + AsThoughEffectType.PLAY_FROM_NOT_OWN_HAND_ZONE, + ability, + this.getId(), + game) != null) { if (canUse || ability.getAbilityType() == AbilityType.SPECIAL_ACTION) { @@ -1924,9 +1925,9 @@ public abstract class PlayerImpl implements Player, Serializable { } private List getPermanentsThatCanBeUntapped(Game game, - List canBeUntapped, - RestrictionUntapNotMoreThanEffect handledEffect, - Map>, Integer> notMoreThanEffectsUsage) { + List canBeUntapped, + RestrictionUntapNotMoreThanEffect handledEffect, + Map>, Integer> notMoreThanEffectsUsage) { List leftForUntap = new ArrayList<>(); // select permanents that can still be untapped for (Permanent permanent : canBeUntapped) { @@ -2634,7 +2635,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean searchLibrary(TargetCardInLibrary target, Ability source, Game game, UUID targetPlayerId, - boolean triggerEvents) { + boolean triggerEvents) { //20091005 - 701.14c Library searchedLibrary = null; String searchInfo = null; @@ -2838,7 +2839,7 @@ public abstract class PlayerImpl implements Player, Serializable { /** * @param game * @param appliedEffects - * @param numSides Number of sides the dice has + * @param numSides Number of sides the dice has * @return the number that the player rolled */ @Override @@ -2875,16 +2876,16 @@ public abstract class PlayerImpl implements Player, Serializable { /** * @param game * @param appliedEffects - * @param numberChaosSides The number of chaos sides the planar die - * currently has (normally 1 but can be 5) + * @param numberChaosSides The number of chaos sides the planar die + * currently has (normally 1 but can be 5) * @param numberPlanarSides The number of chaos sides the planar die - * currently has (normally 1) + * currently has (normally 1) * @return the outcome that the player rolled. Either ChaosRoll, PlanarRoll * or NilRoll */ @Override public PlanarDieRoll rollPlanarDie(Game game, ArrayList appliedEffects, int numberChaosSides, - int numberPlanarSides) { + int numberPlanarSides) { int result = RandomUtil.nextInt(9) + 1; PlanarDieRoll roll = PlanarDieRoll.NIL_ROLL; if (numberChaosSides + numberPlanarSides > 9) { @@ -3041,7 +3042,7 @@ public abstract class PlayerImpl implements Player, Serializable { /** * @param ability - * @param available if null, it won't be checked if enough mana is available + * @param available if null, it won't be checked if enough mana is available * @param sourceObject * @param game * @return @@ -3346,8 +3347,8 @@ public abstract class PlayerImpl implements Player, Serializable { if (ability instanceof ActivatedAbility) { if (!(ability instanceof PlayLandAbility) || !game.getContinuousEffects().preventedByRuleModification( - GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), - ability.getSourceId(), playerId), ability, game, true)) { + GameEvent.getEvent(GameEvent.EventType.PLAY_LAND, ability.getSourceId(), + ability.getSourceId(), playerId), ability, game, true)) { if (canPlay((ActivatedAbility) ability, availableMana, card, game)) { playable.add(ability); } @@ -3461,24 +3462,24 @@ public abstract class PlayerImpl implements Player, Serializable { /** * Creates a list of card ids that are currently playable.
* Used to mark the playable cards in GameView + * Also contains number of playable abilities for that object (it's just info, server decides to show choose dialog or not) * * @param game - * @return A Set of cardIds that are playable + * @return A Set of cardIds that are playable and amount of playable abilities */ @Override - public Set getPlayableObjects(Game game, Zone zone) { - - List playableAbilities = getPlayable(game, true, zone, false); // do not hide duplicated abilities - Set playableObjects = new HashSet<>(); + public Map getPlayableObjects(Game game, Zone zone) { + List playableAbilities = getPlayable(game, true, zone, false); // do not hide duplicated abilities/cards + Map playableObjects = new HashMap<>(); for (Ability ability : playableAbilities) { if (ability.getSourceId() != null) { - playableObjects.add(ability.getSourceId()); + playableObjects.put(ability.getSourceId(), playableObjects.getOrDefault(ability.getSourceId(), 0) + 1); // main card must be marked playable in GUI Card card = game.getCard(ability.getSourceId()); if (card != null && card.getMainCard().getId() != card.getId()) { UUID mainCardId = card.getMainCard().getId(); - playableObjects.add(mainCardId); + playableObjects.put(mainCardId, playableObjects.getOrDefault(mainCardId, 0) + 1); } } } @@ -3668,7 +3669,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean canPaySacrificeCost(Permanent permanent, UUID sourceId, - UUID controllerId, Game game + UUID controllerId, Game game ) { return sacrificeCostFilter == null || !sacrificeCostFilter.match(permanent, sourceId, controllerId, game); } @@ -3822,8 +3823,8 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCards(Card card, Zone toZone, - Ability source, Game game, - boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects + Ability source, Game game, + boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects ) { Set cardList = new HashSet<>(); if (card != null) { @@ -3834,22 +3835,22 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCards(Cards cards, Zone toZone, - Ability source, Game game + Ability source, Game game ) { return moveCards(cards.getCards(game), toZone, source, game); } @Override public boolean moveCards(Set cards, Zone toZone, - Ability source, Game game + Ability source, Game game ) { return moveCards(cards, toZone, source, game, false, false, false, null); } @Override public boolean moveCards(Set cards, Zone toZone, - Ability source, Game game, - boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects + Ability source, Game game, + boolean tapped, boolean faceDown, boolean byOwner, List appliedEffects ) { if (cards.isEmpty()) { return true; @@ -3944,8 +3945,8 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardsToExile(Card card, Ability source, - Game game, boolean withName, UUID exileId, - String exileZoneName + Game game, boolean withName, UUID exileId, + String exileZoneName ) { Set cards = new HashSet<>(); cards.add(card); @@ -3954,8 +3955,8 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardsToExile(Set cards, Ability source, - Game game, boolean withName, UUID exileId, - String exileZoneName + Game game, boolean withName, UUID exileId, + String exileZoneName ) { if (cards.isEmpty()) { return true; @@ -3971,14 +3972,14 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToHandWithInfo(Card card, UUID sourceId, - Game game + Game game ) { return this.moveCardToHandWithInfo(card, sourceId, game, true); } @Override public boolean moveCardToHandWithInfo(Card card, UUID sourceId, - Game game, boolean withName + Game game, boolean withName ) { boolean result = false; Zone fromZone = game.getState().getZone(card.getId()); @@ -4003,7 +4004,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public Set moveCardsToGraveyardWithInfo(Set allCards, Ability source, - Game game, Zone fromZone + Game game, Zone fromZone ) { UUID sourceId = source == null ? null : source.getSourceId(); Set movedCards = new LinkedHashSet<>(); @@ -4011,7 +4012,7 @@ public abstract class PlayerImpl implements Player, Serializable { // identify cards from one owner Cards cards = new CardsImpl(); UUID ownerId = null; - for (Iterator it = allCards.iterator(); it.hasNext();) { + for (Iterator it = allCards.iterator(); it.hasNext(); ) { Card card = it.next(); if (cards.isEmpty()) { ownerId = card.getOwnerId(); @@ -4074,7 +4075,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToGraveyardWithInfo(Card card, UUID sourceId, - Game game, Zone fromZone + Game game, Zone fromZone ) { if (card == null) { return false; @@ -4103,8 +4104,8 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToLibraryWithInfo(Card card, UUID sourceId, - Game game, Zone fromZone, - boolean toTop, boolean withName + Game game, Zone fromZone, + boolean toTop, boolean withName ) { if (card == null) { return false; @@ -4138,7 +4139,7 @@ public abstract class PlayerImpl implements Player, Serializable { @Override public boolean moveCardToExileWithInfo(Card card, UUID exileId, String exileName, UUID sourceId, - Game game, Zone fromZone, boolean withName) { + Game game, Zone fromZone, boolean withName) { if (card == null) { return false; } @@ -4161,7 +4162,7 @@ public abstract class PlayerImpl implements Player, Serializable { game.informPlayers(this.getLogName() + " moves " + (withName ? card.getLogName() + (card.isCopy() ? " (Copy)" : "") : "a card face down") + ' ' + (fromZone != null ? "from " + fromZone.toString().toLowerCase(Locale.ENGLISH) - + ' ' : "") + "to the exile zone"); + + ' ' : "") + "to the exile zone"); } result = true;