Refactor: removed server side objects from a client side game's data (#10788)

* Clean original values transmitted with CardView.originalObject
* Move RateCard to mage.Common, support cardView as argument.
* Clean PermanentView constructor for TestCardRenderDialog
This commit is contained in:
Susucre 2023-08-24 10:04:07 +02:00 committed by GitHub
parent ba411e0054
commit 5062c84098
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 285 additions and 149 deletions

View file

@ -37,7 +37,7 @@ import mage.client.util.stats.UpdateMemUsageTask;
import mage.components.ImagePanel;
import mage.components.ImagePanelStyle;
import mage.constants.PlayerAction;
import mage.game.draft.RateCard;
import mage.cards.RateCard;
import mage.interfaces.MageClient;
import mage.interfaces.callback.CallbackClient;
import mage.interfaces.callback.ClientCallback;
@ -73,7 +73,6 @@ import java.io.InputStream;
import java.net.SocketException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.Executors;

View file

@ -1,5 +1,6 @@
package mage.client.deckeditor.collection.viewer;
import static java.lang.Math.min;
import mage.abilities.icon.CardIconRenderSettings;
import mage.cards.CardDimensions;
import mage.cards.ExpansionSet;
@ -21,7 +22,7 @@ import mage.components.ImagePanelStyle;
import mage.game.command.Dungeon;
import mage.game.command.Emblem;
import mage.game.command.Plane;
import mage.game.draft.RateCard;
import mage.cards.RateCard;
import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.Token;
import mage.game.permanent.token.TokenImpl;
@ -42,8 +43,6 @@ import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import static java.lang.Math.min;
/**
* Card viewer (mage book) with cards and page flipping
*
@ -388,9 +387,9 @@ public class MageBook extends JComponent {
draftRating.setBounds(rectangle.x, rectangle.y + cardImg.getCardLocation().getCardHeight() + dy, cardDimensions.getFrameWidth(), 20);
draftRating.setHorizontalAlignment(SwingConstants.CENTER);
draftRating.setFont(jLayeredPane.getFont().deriveFont(jLayeredPane.getFont().getStyle() | Font.BOLD));
if (card.getOriginalCard() != null) {
if (card.isOriginalACard()) {
// card
draftRating.setText("draft rating: " + RateCard.rateCard(card.getOriginalCard(), null));
draftRating.setText("draft rating: " + RateCard.rateCard(card, null));
} else {
// token
draftRating.setText("");

View file

@ -2,7 +2,7 @@ package mage.client.deckeditor.table;
import mage.cards.MageCard;
import mage.client.util.comparators.CardViewComparator;
import mage.game.draft.RateCard;
import mage.cards.RateCard;
import mage.view.CardView;
import org.apache.log4j.Logger;
@ -83,8 +83,8 @@ public class MageCardComparator implements CardViewComparator {
bCom = Integer.parseInt(b.getCardNumber().replaceAll("[\\D]", ""));
break;
case 9:
aCom = RateCard.rateCard(a.getOriginalCard(), null);
bCom = RateCard.rateCard(b.getOriginalCard(), null);
aCom = RateCard.rateCard(a, null);
bCom = RateCard.rateCard(b, null);
break;
case 10:
aCom = a.getColorIdentityStr();

View file

@ -12,7 +12,7 @@ import mage.client.util.Event;
import mage.client.util.Listener;
import mage.client.util.gui.GuiDisplayUtil;
import mage.constants.EnlargeMode;
import mage.game.draft.RateCard;
import mage.cards.RateCard;
import mage.view.CardView;
import mage.view.CardsView;
import org.apache.log4j.Logger;
@ -253,7 +253,7 @@ public class TableModel extends AbstractTableModel implements ICardGrid {
case 8:
return c.getCardNumber();
case 9:
return RateCard.rateCard(c.getOriginalCard(), null);
return RateCard.rateCard(c, null);
case 10:
return ManaSymbols.getClearManaCost(c.getColorIdentityStr());
default:

View file

@ -28,7 +28,6 @@ import mage.game.command.Plane;
import mage.game.match.MatchType;
import mage.game.mulligan.Mulligan;
import mage.game.mulligan.MulliganType;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentCard;
import mage.game.permanent.PermanentMeld;
import mage.game.permanent.PermanentToken;
@ -402,9 +401,9 @@ public class TestCardRenderDialog extends MageDialog {
if (main.getGameCard() instanceof PermanentView) {
// new settings must be as a new copy -- it would activate the animations
PermanentView oldPermanent = (PermanentView) main.getGameCard();
PermanentView newPermament = new PermanentView( // ???
(Permanent) oldPermanent.getOriginalCard(),
game.getCard(oldPermanent.getOriginalCard().getId()),
PermanentView newPermament = new PermanentView(
oldPermanent,
game.getCard(oldPermanent.getOriginalId()),
UUID.randomUUID(),
game
);

View file

@ -446,20 +446,8 @@ public class CardPanelRenderModeImage extends CardPanel {
if (cardView.showPT()) {
// real PT info
MageInt currentPower;
MageInt currentToughness;
if (cardView.getOriginalCard() != null) {
// card
currentPower = cardView.getOriginalCard().getPower();
currentToughness = cardView.getOriginalCard().getToughness();
} else if (cardView.getOriginalToken() != null) {
// token
currentPower = cardView.getOriginalToken().getPower();
currentToughness = cardView.getOriginalToken().getToughness();
} else {
currentPower = null;
currentToughness = null;
}
MageInt currentPower = cardView.getOriginalPower();
MageInt currentToughness = cardView.getOriginalToughness();
prepareGlowFont(ptText1, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), currentPower, false);
prepareGlowFont(ptText2, Math.max(CARD_PT_FONT_MIN_SIZE, fontSize), null, false);

View file

@ -1096,20 +1096,8 @@ public class ModernCardRenderer extends CardRenderer {
g.setFont(ptTextFont);
// real PT info
MageInt currentPower;
MageInt currentToughness;
if (cardView.getOriginalCard() != null) {
// card
currentPower = cardView.getOriginalCard().getPower();
currentToughness = cardView.getOriginalCard().getToughness();
} else if (cardView.getOriginalToken() != null) {
// token
currentPower = cardView.getOriginalToken().getPower();
currentToughness = cardView.getOriginalToken().getToughness();
} else {
currentPower = null;
currentToughness = null;
}
MageInt currentPower = cardView.getOriginalPower();
MageInt currentToughness = cardView.getOriginalToughness();
// draws
int ptEmptySpace = (partBoxWidth - ptContentWidth) / 2;

View file

@ -1,19 +1,18 @@
package mage.game.draft;
package mage.cards;
import mage.abilities.Ability;
import mage.abilities.Mode;
import mage.abilities.effects.Effect;
import mage.abilities.effects.common.*;
import mage.abilities.effects.common.continuous.BoostEnchantedEffect;
import mage.abilities.effects.common.continuous.BoostTargetEffect;
import mage.cards.Card;
import mage.cards.repository.CardScanner;
import mage.constants.ColoredManaSymbol;
import mage.constants.Outcome;
import mage.constants.Rarity;
import mage.constants.SubType;
import mage.target.Target;
import mage.target.TargetPermanent;
import mage.target.common.TargetPlayerOrPlaneswalker;
import mage.view.CardView;
import org.apache.log4j.Logger;
import java.io.InputStream;
@ -30,7 +29,8 @@ public final class RateCard {
public static final boolean PRELOAD_CARD_RATINGS_ON_STARTUP = false; // warning, rating and card classes preloading can cause lags for users with low memory
private static Map<String, Integer> baseRatings = new HashMap<>();
private static final Map<String, Integer> rated = new HashMap<>();
private static final Map<String, Integer> ratedCard = new HashMap<>();
private static final Map<String, Integer> ratedCardView = new HashMap<>(); // Rating is not exactly the same for CardView, so cached in a different map.
private static boolean isLoaded = false;
/**
@ -80,42 +80,96 @@ public final class RateCard {
return rateCard(card, allowedColors, true);
}
public static int rateCard(CardView cardview, List<ColoredManaSymbol> allowedColors) {
return rateCard(cardview, allowedColors, true);
}
public static int rateCard(Card card, List<ColoredManaSymbol> allowedColors, boolean useCache) {
if (card == null) {
return 0;
}
if (useCache && allowedColors == null && rated.containsKey(card.getName())) {
int rate = rated.get(card.getName());
String name = card.getName();
if (useCache && allowedColors == null && ratedCard.containsKey(name)) {
int rate = ratedCard.get(name);
return rate;
}
int type;
if (card.isPlaneswalker()) {
type = 15;
} else if (card.isCreature()) {
type = 10;
} else if (card.getSubtype().contains(SubType.EQUIPMENT)) {
type = 8;
} else if (card.getSubtype().contains(SubType.AURA)) {
type = 5;
} else if (card.isInstant()) {
type = 7;
} else {
type = 6;
}
int score = getBaseCardScore(card) + 2 * type + getManaCostScore(card, allowedColors)
int typeMultiplier = typeMultiplier(card);
int score = getBaseCardScore(card) + 2 * typeMultiplier + getManaCostScore(card, allowedColors)
+ 40 * isRemoval(card);
if (useCache && allowedColors == null)
rated.put(card.getName(), score);
ratedCard.put(name, score);
return score;
}
public static int rateCard(CardView cardview, List<ColoredManaSymbol> allowedColors, boolean useCache) {
if (cardview == null) {
return 0;
}
String name = cardview.getName();
if (useCache && allowedColors == null && ratedCardView.containsKey(name)) {
int rate = ratedCardView.get(name);
return rate;
}
int typeMultiplier = typeMultiplier(cardview);
int score = getBaseCardScore(cardview) + 2 * typeMultiplier + getManaCostScore(cardview, allowedColors);
// Cardview does not have enough info to know the card is a removal.
if (useCache && allowedColors == null)
ratedCardView.put(name, score);
return score;
}
protected static int typeMultiplier(Card card) {
return typeMultiplier(
card.isPlaneswalker(),
card.isCreature(),
card.getSubtype().contains(SubType.EQUIPMENT),
card.getSubtype().contains(SubType.AURA),
card.isInstant()
);
}
protected static int typeMultiplier(CardView cardview) {
return typeMultiplier(
cardview.isPlaneswalker(),
cardview.isCreature(),
cardview.getSubTypes().contains(SubType.EQUIPMENT),
cardview.getSubTypes().contains(SubType.AURA),
cardview.isInstant()
);
}
protected static int typeMultiplier(
boolean isPlaneswalker,
boolean isCreature,
boolean isEquipment,
boolean isAura,
boolean isInstant
) {
if (isPlaneswalker) {
return 15;
} else if (isCreature) {
return 10;
} else if (isEquipment) {
return 8;
} else if (isAura) {
return 5;
} else if (isInstant) {
return 7;
} else {
return 6;
}
}
private static int isRemoval(Card card) {
if (card.isEnchantment() || card.isInstantOrSorcery()) {
for (Ability ability : card.getAbilities()) {
for (Effect effect : ability.getEffects()) {
if (isEffectRemoval(card, ability, effect) == 1) {
@ -130,7 +184,6 @@ public final class RateCard {
}
}
}
}
return 0;
}
@ -168,7 +221,6 @@ public final class RateCard {
return 0;
}
/**
* Return rating of the card.
*
@ -176,6 +228,20 @@ public final class RateCard {
* @return Rating number from [1:100].
*/
public static int getBaseCardScore(Card card) {
return getBaseScore(
card.getName(),
card.getRarity()
);
}
public static int getBaseCardScore(CardView cardview) {
return getBaseScore(
cardview.getName(),
cardview.getRarity()
);
}
protected static int getBaseScore(String name, Rarity rarity) {
// same card name must have same rating
// ratings from files
@ -185,8 +251,8 @@ public final class RateCard {
// ratings from card rarity
// some cards can have different rarity -- it's will be used from first set
int newRating;
if (card.getRarity() != null) {
switch (card.getRarity()) {
if (rarity != null) {
switch (rarity) {
case COMMON:
newRating = DEFAULT_NOT_RATED_CARD_RATING;
break;
@ -200,7 +266,7 @@ public final class RateCard {
newRating = DEFAULT_NOT_RATED_MYTHIC_RATING;
break;
default:
if (isBasicLand(card)) {
if (isBasicLand(name)) {
newRating = DEFAULT_BASIC_LAND_RATING;
} else {
newRating = DEFAULT_NOT_RATED_CARD_RATING;
@ -212,7 +278,7 @@ public final class RateCard {
newRating = DEFAULT_NOT_RATED_CARD_RATING;
}
int oldRating = baseRatings.getOrDefault(card.getName(), 0);
int oldRating = baseRatings.getOrDefault(name, 0);
if (oldRating != 0 && oldRating != newRating) {
//log.info("card have different rating by sets: " + card.getName() + " (" + oldRating + " <> " + newRating + ")");
}
@ -220,7 +286,7 @@ public final class RateCard {
if (oldRating != 0) {
return oldRating;
} else {
baseRatings.put(card.getName(), newRating);
baseRatings.put(name, newRating);
return newRating;
}
}
@ -316,26 +382,44 @@ public final class RateCard {
* @param allowedColors Can be null.
* @return
*/
private static int getManaCostScore(Card card, List<ColoredManaSymbol> allowedColors) {
int converted = card.getManaValue();
return getManaCostScore(
card.getName(),
card.getManaValue(),
card.getManaCostSymbols(),
allowedColors
);
}
private static int getManaCostScore(CardView cardview, List<ColoredManaSymbol> allowedColors) {
return getManaCostScore(
cardview.getName(),
cardview.getManaValue(),
cardview.getManaCostSymbols(),
allowedColors
);
}
private static int getManaCostScore(String name, int manaValue, List<String> manaCostSymbols, List<ColoredManaSymbol> allowedColors) {
if (allowedColors == null) {
int colorPenalty = 0;
for (String symbol : card.getManaCostSymbols()) {
for (String symbol : manaCostSymbols) {
if (isColoredMana(symbol)) {
colorPenalty++;
}
}
return 2 * (converted - colorPenalty + 1);
return 2 * (manaValue - colorPenalty + 1);
}
// Basic lands have no value so they're always treated as off-color
if (isBasicLand(card)) {
if (isBasicLand(name)) {
return OFF_COLOR_PENALTY;
}
final Map<String, Integer> singleCount = new HashMap<>();
int maxSingleCount = 0;
for (String symbol : card.getManaCostSymbols()) {
for (String symbol : manaCostSymbols) {
int count = 0;
symbol = symbol.replace("{", "").replace("}", "");
if (isColoredMana(symbol)) {
@ -359,7 +443,7 @@ public final class RateCard {
if (maxSingleCount > 5)
maxSingleCount = 5;
int rate = 2 * converted + 3 * (10 - SINGLE_PENALTY[maxSingleCount]);
int rate = 2 * manaValue + 3 * (10 - SINGLE_PENALTY[maxSingleCount]);
if (singleCount.size() > 1 && singleCount.size() < 5) {
rate += MULTICOLOR_BONUS;
}
@ -414,15 +498,14 @@ public final class RateCard {
}
return symbols.size();
}
/**
* Return true if the card is one of the basic land types that can be added to the deck for free.
*
* @param card
* @param name
* @return
*/
public static boolean isBasicLand(Card card) {
String name = card.getName();
public static boolean isBasicLand(String name) {
if (name.equals("Plains")
|| name.equals("Island")
|| name.equals("Swamp")

View file

@ -31,8 +31,8 @@ public class AbilityView extends CardView {
this.subTypes = new SubTypes();
this.superTypes = new ArrayList<>();
this.color = new ObjectColor();
this.manaCostLeftStr = String.join("", ability.getManaCostSymbols());
this.manaCostRightStr = "";
this.manaCostLeftStr = ability.getManaCostSymbols();
this.manaCostRightStr = new ArrayList<>();
}
public CardView getSourceCard() {

View file

@ -1,6 +1,7 @@
package mage.view;
import com.google.gson.annotations.Expose;
import mage.MageInt;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Abilities;
@ -74,8 +75,8 @@ public class CardView extends SimpleCardView {
protected ObjectColor frameColor;
protected FrameStyle frameStyle;
// can combine multiple costs for MockCard from deck editor or db (left/right, card/adventure)
protected String manaCostLeftStr;
protected String manaCostRightStr;
protected List<String> manaCostLeftStr;
protected List<String> manaCostRightStr;
protected int manaValue;
protected Rarity rarity;
@ -130,7 +131,13 @@ public class CardView extends SimpleCardView {
protected boolean inViewerOnly; // GUI render: show object as a card instead permanent (without PT, etc)
protected List<CardIcon> cardIcons = new ArrayList<>(); // additional icons to render
protected MageObject originalObject = null; // GUI related: additional info about current object (example: real PT)
// GUI related: additional info about current object (example: real PT)
protected MageInt originalPower = null;
protected MageInt originalToughness = null;
protected FilterMana originalColorIdentity = null;
protected UUID originalId = null;
protected boolean originalIsCopy = false;
protected boolean originalIsCard = false;
/**
* Non game usage like deck editor
@ -237,7 +244,12 @@ public class CardView extends SimpleCardView {
this.canAttack = cardView.canAttack;
this.canBlock = cardView.canBlock;
this.inViewerOnly = cardView.inViewerOnly;
this.originalObject = cardView.originalObject == null ? null : cardView.originalObject.copy();
this.originalPower = cardView.originalPower;
this.originalToughness = cardView.originalToughness;
this.originalColorIdentity = cardView.originalColorIdentity;
this.originalId = cardView.originalId;
this.originalIsCard = cardView.originalIsCard;
this.originalIsCopy = cardView.originalIsCopy;
if (cardView.cardIcons != null) {
cardView.cardIcons.forEach(icon -> this.cardIcons.add(icon.copy()));
}
@ -287,7 +299,7 @@ public class CardView extends SimpleCardView {
*/
public CardView(Card card, Game game, boolean controlled, boolean showFaceDownCard, boolean storeZone) {
super(card.getId(), card.getExpansionSetCode(), card.getCardNumber(), card.getUsesVariousArt(), game != null);
this.originalObject = card;
this.setOriginalValues(card);
this.imageNumber = card.getImageNumber();
// no information available for face down cards as long it's not a controlled face down morph card
@ -375,29 +387,29 @@ public class CardView extends SimpleCardView {
rightSplitTypeLine = getCardTypeLine(game, splitCard.getRightHalfCard());
fullCardName = card.getName(); // split card contains full name as normal
this.manaCostLeftStr = String.join("", splitCard.getLeftHalfCard().getManaCostSymbols());
this.manaCostRightStr = String.join("", splitCard.getRightHalfCard().getManaCostSymbols());
this.manaCostLeftStr = splitCard.getLeftHalfCard().getManaCostSymbols();
this.manaCostRightStr = splitCard.getRightHalfCard().getManaCostSymbols();
} else if (card instanceof ModalDoubleFacedCard) {
this.isModalDoubleFacedCard = true;
ModalDoubleFacedCard mainCard = ((ModalDoubleFacedCard) card);
fullCardName = mainCard.getLeftHalfCard().getName() + MockCard.MODAL_DOUBLE_FACES_NAME_SEPARATOR + mainCard.getRightHalfCard().getName();
this.manaCostLeftStr = String.join("", mainCard.getLeftHalfCard().getManaCostSymbols());
this.manaCostRightStr = String.join("", mainCard.getRightHalfCard().getManaCostSymbols());
this.manaCostLeftStr = mainCard.getLeftHalfCard().getManaCostSymbols();
this.manaCostRightStr = mainCard.getRightHalfCard().getManaCostSymbols();
} else if (card instanceof AdventureCard) {
AdventureCard adventureCard = ((AdventureCard) card);
AdventureCardSpell adventureCardSpell = adventureCard.getSpellCard();
fullCardName = adventureCard.getName() + MockCard.ADVENTURE_NAME_SEPARATOR + adventureCardSpell.getName();
this.manaCostLeftStr = String.join("", adventureCardSpell.getManaCostSymbols());
this.manaCostRightStr = String.join("", adventureCard.getManaCostSymbols());
this.manaCostLeftStr = adventureCardSpell.getManaCostSymbols();
this.manaCostRightStr = adventureCard.getManaCostSymbols();
} else if (card instanceof MockCard) {
// deck editor cards
fullCardName = ((MockCard) card).getFullName(true);
this.manaCostLeftStr = String.join("", ((MockCard) card).getManaCostStr(CardInfo.ManaCostSide.LEFT));
this.manaCostRightStr = String.join("", ((MockCard) card).getManaCostStr(CardInfo.ManaCostSide.RIGHT));
this.manaCostLeftStr = ((MockCard) card).getManaCostStr(CardInfo.ManaCostSide.LEFT);
this.manaCostRightStr = ((MockCard) card).getManaCostStr(CardInfo.ManaCostSide.RIGHT);
} else {
fullCardName = card.getName();
this.manaCostLeftStr = String.join("", card.getManaCostSymbols());
this.manaCostRightStr = "";
this.manaCostLeftStr = card.getManaCostSymbols();
this.manaCostRightStr = new ArrayList<>();
}
this.name = card.getName();
@ -616,7 +628,7 @@ public class CardView extends SimpleCardView {
public CardView(MageObject object, Game game) {
super(object.getId(), object.getExpansionSetCode(), object.getCardNumber(), false, true);
this.originalObject = object;
this.setOriginalValues(object);
this.imageNumber = object.getImageNumber();
this.name = object.getName();
@ -638,8 +650,8 @@ public class CardView extends SimpleCardView {
this.subTypes = object.getSubtype(game).copy();
this.superTypes = new ArrayList<>(object.getSuperType(game));
this.color = object.getColor(game).copy();
this.manaCostLeftStr = String.join("", object.getManaCostSymbols());
this.manaCostRightStr = "";
this.manaCostLeftStr = object.getManaCostSymbols();
this.manaCostRightStr = new ArrayList<>();
this.manaValue = object.getManaCost().manaValue();
if (object instanceof PermanentToken) {
this.mageObjectType = MageObjectType.TOKEN;
@ -694,7 +706,6 @@ public class CardView extends SimpleCardView {
public CardView(EmblemView emblem) {
this(true);
this.originalObject = null;
this.gameObject = true;
this.id = emblem.getId();
this.mageObjectType = MageObjectType.EMBLEM;
@ -716,7 +727,6 @@ public class CardView extends SimpleCardView {
public CardView(DungeonView dungeon) {
this(true);
this.originalObject = null;
this.gameObject = true;
this.id = dungeon.getId();
this.mageObjectType = MageObjectType.DUNGEON;
@ -738,7 +748,6 @@ public class CardView extends SimpleCardView {
public CardView(PlaneView plane) {
this(true);
this.originalObject = null;
this.gameObject = true;
this.id = plane.getId();
this.mageObjectType = MageObjectType.PLANE;
@ -761,7 +770,6 @@ public class CardView extends SimpleCardView {
public CardView(Designation designation, StackAbility stackAbility) {
this(true);
this.originalObject = null;
this.gameObject = true;
this.id = designation.getId();
this.mageObjectType = MageObjectType.NULL;
@ -788,7 +796,6 @@ public class CardView extends SimpleCardView {
}
private void fillEmpty(Card card, boolean controlled) {
this.originalObject = null;
this.name = "Face Down";
this.displayName = name;
this.displayFullName = name;
@ -805,8 +812,8 @@ public class CardView extends SimpleCardView {
this.color = new ObjectColor();
this.frameColor = new ObjectColor();
this.frameStyle = FrameStyle.M15_NORMAL;
this.manaCostLeftStr = "";
this.manaCostRightStr = "";
this.manaCostLeftStr = new ArrayList<>();
this.manaCostRightStr = new ArrayList<>();
this.manaValue = 0;
// the controller can see more information (e.g. enlarged image) than other players for face down cards (e.g. Morph played face down)
@ -857,8 +864,8 @@ public class CardView extends SimpleCardView {
this.color = token.getColor(game).copy();
this.frameColor = token.getFrameColor(game).copy();
this.frameStyle = token.getFrameStyle();
this.manaCostLeftStr = String.join("", token.getManaCostSymbols());
this.manaCostRightStr = "";
this.manaCostLeftStr = token.getManaCostSymbols();
this.manaCostRightStr = new ArrayList<>();
this.rarity = Rarity.SPECIAL;
// source object is a token, so no card number
@ -894,6 +901,26 @@ public class CardView extends SimpleCardView {
this.targets.addAll(newTargets);
}
private void setOriginalValues(MageObject object) {
if (object == null) {
return;
}
// Only valid objects to transfer original values are Card and Token
if (object instanceof Card || object instanceof Token) {
this.originalPower = object.getPower();
this.originalToughness = object.getToughness();
this.originalIsCopy = object.isCopy();
this.originalId = object.getId();
if (object instanceof Card) {
this.originalColorIdentity = ((Card) object).getColorIdentity();
this.originalIsCard = true;
} else if (object instanceof Token) {
this.originalColorIdentity = ManaUtil.getColorIdentity((Token) object);
}
}
}
public String getName() {
return name;
}
@ -979,7 +1006,22 @@ public class CardView extends SimpleCardView {
}
public String getManaCostStr() {
return CardUtil.concatManaSymbols(CardInfo.SPLIT_MANA_SEPARATOR_FULL, this.manaCostLeftStr, this.manaCostRightStr);
return CardUtil.concatManaSymbols(
CardInfo.SPLIT_MANA_SEPARATOR_FULL,
String.join("", this.manaCostLeftStr),
String.join("", this.manaCostRightStr)
);
}
public List<String> getManaCostSymbols() {
List<String> symbols = new ArrayList<>();
for (String symbol : this.manaCostLeftStr) {
symbols.add(symbol);
}
for (String symbol : this.manaCostRightStr) {
symbols.add(symbol);
}
return symbols;
}
public int getManaValue() {
@ -991,14 +1033,8 @@ public class CardView extends SimpleCardView {
}
public String getColorIdentityStr() {
FilterMana colorInfo;
if (getOriginalCard() != null) {
// card
colorInfo = getOriginalCard().getColorIdentity();
} else if (getOriginalToken() != null) {
// token
colorInfo = ManaUtil.getColorIdentity(getOriginalToken());
} else {
FilterMana colorInfo = this.originalColorIdentity;
if (colorInfo != null) {
colorInfo = new FilterMana();
}
@ -1285,20 +1321,24 @@ public class CardView extends SimpleCardView {
return inViewerOnly;
}
public Card getOriginalCard() {
if (this.originalObject instanceof Card) {
return (Card) this.originalObject;
} else {
return null;
}
public MageInt getOriginalPower() {
return this.originalPower;
}
public Token getOriginalToken() {
if (this.originalObject instanceof Token) {
return (Token) this.originalObject;
} else {
return null;
}
public MageInt getOriginalToughness() {
return this.originalToughness;
}
public UUID getOriginalId() {
return this.originalId;
}
public boolean isOriginalACopy() {
return this.originalIsCopy;
}
public boolean isOriginalACard() {
return this.originalIsCard;
}
public List<CardIcon> getCardIcons() {

View file

@ -6,12 +6,12 @@ import mage.cards.Card;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.game.permanent.PermanentToken;
import mage.game.permanent.token.Token;
import mage.players.Player;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* @author BetaSteward_at_googlemail.com
@ -142,6 +142,41 @@ public class PermanentView extends CardView {
this.attachedControllerDiffers = attachedControllerDiffers;
}
public PermanentView(PermanentView permanentView, Card card, UUID createdForPlayerId, Game game) {
super(permanentView);
this.controlled = permanentView.controlled;
this.tapped = permanentView.isTapped();
this.flipped = permanentView.isFlipped();
this.phasedIn = permanentView.isPhasedIn();
this.summoningSickness = permanentView.summoningSickness;
this.damage = permanentView.damage;
this.attachments = permanentView.attachments.stream().collect(Collectors.toList());
boolean showFaceDownInfo = controlled || (game != null && game.hasEnded());
if (isToken()) {
original = new CardView(permanentView.original);
original.expansionSetCode = permanentView.original.getExpansionSetCode();
expansionSetCode = permanentView.original.getExpansionSetCode();
} else {
if (card != null && showFaceDownInfo) {
// face down card must be hidden from opponent, but shown on game end for all
original = new CardView(card.copy(), (Game) null);
} else {
original = null;
}
}
this.copy = permanentView.copy;
this.nameOwner = permanentView.nameOwner;
this.nameController = permanentView.nameController;
this.attachedTo = permanentView.attachedTo;
this.morphed = permanentView.morphed;
this.manifested = permanentView.manifested;
this.attachedToPermanent = permanentView.attachedToPermanent;
this.attachedControllerDiffers = permanentView.attachedControllerDiffers;
}
public boolean isTapped() {
return tapped;
}

View file

@ -14,6 +14,8 @@ import mage.constants.CardType;
import mage.constants.MageObjectType;
import mage.game.Game;
import mage.game.stack.StackAbility;
import mage.game.stack.StackObject;
import mage.target.Target;
import mage.target.targetpointer.FixedTarget;
import mage.target.targetpointer.TargetPointer;
import mage.util.GameLog;
@ -21,8 +23,6 @@ import mage.util.GameLog;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.game.stack.StackObject;
import mage.target.Target;
/**
* @author BetaSteward_at_googlemail.com
@ -49,8 +49,8 @@ public class StackAbilityView extends CardView {
this.subTypes = ability.getSubtype(game);
this.superTypes = ability.getSuperType(game);
this.color = ability.getColor(game);
this.manaCostLeftStr = String.join("", ability.getManaCostSymbols());
this.manaCostRightStr = "";
this.manaCostLeftStr = ability.getManaCostSymbols();
this.manaCostRightStr = new ArrayList<>();
this.cardTypes = ability.getCardType(game);
this.subTypes = ability.getSubtype(game);
this.superTypes = ability.getSuperType(game);
@ -65,8 +65,8 @@ public class StackAbilityView extends CardView {
tmpSourceCard.subTypes.clear();
tmpSourceCard.cardTypes.clear();
tmpSourceCard.cardTypes.add(CardType.CREATURE);
tmpSourceCard.manaCostLeftStr = "";
tmpSourceCard.manaCostRightStr = "";
tmpSourceCard.manaCostLeftStr = new ArrayList<>();
tmpSourceCard.manaCostRightStr = new ArrayList<>();
tmpSourceCard.power = "2";
tmpSourceCard.toughness = "2";
nameToShow = "creature without name";

View file

@ -20,6 +20,11 @@
<artifactId>mage</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>mage-sets</artifactId>

View file

@ -16,6 +16,7 @@ import mage.abilities.mana.ManaOptions;
import mage.cards.Card;
import mage.cards.Cards;
import mage.cards.CardsImpl;
import mage.cards.RateCard;
import mage.cards.decks.Deck;
import mage.cards.decks.DeckValidator;
import mage.cards.decks.DeckValidatorFactory;
@ -34,7 +35,6 @@ import mage.filter.predicate.permanent.ControllerIdPredicate;
import mage.game.Game;
import mage.game.combat.CombatGroup;
import mage.game.draft.Draft;
import mage.game.draft.RateCard;
import mage.game.events.GameEvent;
import mage.game.match.Match;
import mage.game.permanent.Permanent;

View file

@ -6,7 +6,7 @@ import mage.cards.decks.DeckValidatorFactory;
import mage.cards.repository.CardScanner;
import mage.cards.repository.PluginClassloaderRegistery;
import mage.cards.repository.RepositoryUtil;
import mage.game.draft.RateCard;
import mage.cards.RateCard;
import mage.game.match.MatchType;
import mage.game.tournament.TournamentType;
import mage.interfaces.MageServer;

View file

@ -98,12 +98,12 @@ public class CardIconsTest extends CardTestPlayerBase {
Assert.assertEquals("must have 2 cards in stack", 2, gameView.getStack().values().size());
CardView originalCardView = gameView.getStack().values()
.stream()
.filter(c -> !c.getOriginalCard().isCopy())
.filter(c -> !c.isOriginalACopy())
.findFirst()
.get();
CardView copiedCardView = gameView.getStack().values()
.stream()
.filter(c -> c.getOriginalCard().isCopy())
.filter(c -> c.isOriginalACopy())
.findFirst()
.get();
Assert.assertNotNull("stack must have original spell", originalCardView);

View file

@ -29,7 +29,7 @@ import mage.filter.Filter;
import mage.game.command.Dungeon;
import mage.game.command.Plane;
import mage.game.draft.DraftCube;
import mage.game.draft.RateCard;
import mage.cards.RateCard;
import mage.game.permanent.token.Token;
import mage.game.permanent.token.TokenImpl;
import mage.game.permanent.token.custom.CreatureToken;