* GUI: new reworked GUI and card render engine, card icons and dozens of other fixes (see full list in related PR);

This commit is contained in:
Oleg Agafonov 2021-01-30 16:38:55 +04:00
parent df98cc3e62
commit a1da5ef437
304 changed files with 7266 additions and 5093 deletions

View file

@ -1,13 +1,30 @@
package mage.cards;
import mage.cards.action.ActionCallback;
import mage.constants.Zone;
import mage.view.CardView;
import org.apache.log4j.Logger;
import javax.swing.*;
import java.awt.*;
import java.util.UUID;
import java.util.List;
public abstract class MageCard extends JPanel {
/**
* @author JayDi85
*/
public abstract class MageCard extends JLayeredPane {
private static final Logger logger = Logger.getLogger(MageCard.class);
/**
* Return real MageCard panel (example: card icons uses MageLayerCard to implement additional panels)
* <p>
* If you need callback from card then use CardEventSource from form (search for example, e.g. card clicks processing)
*
* @return
*/
public MageCard getMainPanel() {
return this;
}
private static final long serialVersionUID = 6089945326434301879L;
@ -36,11 +53,9 @@ public abstract class MageCard extends JPanel {
public abstract Image getImage();
public abstract void setZone(String zone);
public abstract void setZone(Zone zone);
public abstract String getZone();
public abstract void updateCallback(ActionCallback callback, UUID gameId);
public abstract Zone getZone();
public abstract void toggleTransformed();
@ -50,11 +65,124 @@ public abstract class MageCard extends JPanel {
public abstract void setSelected(boolean selected);
public abstract void setCardAreaRef(JPanel cardArea);
/**
* Set link to cards list panel that contains the card component (can process mouse events from the card)
*
* @param cardContainer
*/
public abstract void setCardContainerRef(Container cardContainer);
public abstract void setTopPanelRef(MageCard mageCard);
public abstract MageCard getTopPanelRef();
public abstract Container getCardContainer();
public abstract void setChoosable(boolean isChoosable);
public abstract boolean isChoosable();
public abstract void setPopupMenu(JPopupMenu popupMenu);
public abstract JPopupMenu getPopupMenu();
public abstract void cleanUp();
public abstract int getCardWidth();
public abstract int getCardHeight();
public abstract MageCardAnimationSettings getAnimationSettings(int offsetX, int offsetY, float cardBoundWidth, float cardBoundHeight);
public abstract List<MageCard> getLinks();
public abstract MageCardSpace getOuterSpace();
/**
* Return top layer component location without outer/draw space (real card)
*
* @return
*/
public MageCardLocation getCardLocation() {
return getTopPanelRef().getCardLocation();
}
/**
* Set card location (top left corner of the main card panel). All calls goes to top layer panel.
*
* @param x
* @param y
*/
public void setCardLocation(int x, int y) {
setLocation(x, y);
}
/**
* Return top layer component location without outer/draw space (real card)
*
* @return
*/
public MageCardLocation getCardLocationOnScreen() {
return getTopPanelRef().getCardLocationOnScreen();
}
@Override
@Deprecated // default getLocationOnScreen for Swing engine only, use getCardLocationOnScreen instead
public Point getLocationOnScreen() {
return super.getLocationOnScreen();
}
@Override
@Deprecated // default getLocation for Swing engine only, use getCardLocation instead
public Point getLocation() {
return super.getLocation();
}
@Override
@Deprecated // default setLocation for inner usage only, call setCardLocation instead
public void setLocation(int x, int y) {
super.setLocation(x, y);
}
@Override
@Deprecated // default setLocation for inner usage only, call setCardLocation instead
public void setLocation(Point p) {
super.setLocation(p);
}
@Override
@Deprecated // default getBounds for Swing engine only, use getCardLocation instead
public Rectangle getBounds() {
return super.getBounds();
}
@Override
@Deprecated // default setBounds for inner usage only, call setCardBounds instead
public void setBounds(Rectangle r) {
super.setBounds(r);
}
@Override
@Deprecated // default setBounds for inner usage only, call setCardBounds instead
public void setBounds(int x, int y, int width, int height) {
super.setBounds(x, y, width, height);
}
@Override
@Deprecated // default getHeight for inner usage only, call getCardLocation instead
public int getHeight() {
return super.getHeight();
}
@Override
@Deprecated // default getWidth for inner usage only, call getCardLocation instead
public int getWidth() {
return super.getWidth();
}
@Override
@Deprecated // default getSize for inner usage only, call getCardLocation.getCardWidth instead
public Dimension getSize() {
return super.getSize();
}
}

View file

@ -0,0 +1,104 @@
package mage.cards;
import java.awt.*;
/**
* Contains animation/scale settings to send from card panel to parent panel
*
* @author JayDi85
*/
public class MageCardAnimationSettings {
private boolean visible = true;
private double translateX = 0;
private double translateY = 0;
private double scaleX = 0;
private double scaleY = 0;
private double rotateTheta = 0;
private double rotateX = 0;
private double rotateY = 0;
public MageCardAnimationSettings withVisible(boolean visible) {
this.visible = visible;
return this;
}
public MageCardAnimationSettings withTranslate(double x, double y) {
this.translateX = x;
this.translateY = y;
return this;
}
public MageCardAnimationSettings withScale(double x, double y) {
this.scaleX = x;
this.scaleY = y;
return this;
}
public MageCardAnimationSettings withRotate(double rotateTheta, double x, double y) {
this.rotateTheta = rotateTheta;
this.rotateX = x;
this.rotateY = y;
return this;
}
public boolean isVisible() {
return visible;
}
/**
* Move the position (uses for animation/rotation in multi layer cards)
*
* @param offsetX
* @param offsetY
*/
public void applyOffsets(int offsetX, int offsetY) {
// translate
if (translateX != 0 || translateY != 0) {
translateX += offsetX;
translateY += offsetY;
}
// scale don't have offsets
// rotate
if (rotateTheta != 0 || rotateX != 0 || rotateY != 0) {
rotateX += offsetX;
rotateY += offsetY;
}
}
/**
* Transform draw context (example: card rotate)
* Draw settings calculates by child panel, but drawing and animation goes from parent, so you must use scale factor
*
* @param g2d graphic context of the card's top layer
*/
public void doTransforms(Graphics2D g2d) {
if (!visible) {
return;
}
double factorX = 1;
double factorY = 1;
// translate
if (translateX != 0 || translateY != 0) {
g2d.translate(translateX * factorX, translateY * factorY);
}
// scale
if (scaleX != 0 || scaleY != 0) {
g2d.scale(scaleX * factorX, scaleY * factorY);
}
// rotate
if (rotateTheta != 0 || rotateX != 0 || rotateY != 0) {
g2d.rotate(rotateTheta, rotateX * factorX, rotateY * factorY); // rotateTheta don't have scale factor
}
}
}

View file

@ -0,0 +1,88 @@
package mage.cards;
import java.awt.*;
/**
* Card's location with real component coords and sizes (can be related to screen or related to parent panel)
*
* @author JayDi85
*/
public class MageCardLocation {
final private Rectangle componentRect;
final private Rectangle cardRect;
public MageCardLocation(Point componentLocation, MageCardSpace cardOuterSpace, Rectangle componentBounds) {
this.componentRect = new Rectangle(componentLocation.x, componentLocation.y, componentBounds.width, componentBounds.height);
this.cardRect = new Rectangle(
this.componentRect.x + cardOuterSpace.left,
this.componentRect.y + cardOuterSpace.top,
this.componentRect.width - cardOuterSpace.getWidth(),
this.componentRect.height - cardOuterSpace.getHeight()
);
}
public int getCardX() {
return cardRect.x;
}
public int getCardY() {
return cardRect.y;
}
/**
* Card's coord for relative calcs (0,0 is component's top left corner)
*
* @return
*/
public int getCardRelativeX() {
return cardRect.x - componentRect.x;
}
/**
* Card's coord for relative calcs (0,0 is component's top left corner)
*
* @return
*/
public int getCardRelativeY() {
return cardRect.y - componentRect.y;
}
public int getCardWidth() {
return cardRect.width;
}
public int getCardHeight() {
return cardRect.height;
}
public Point getCardPoint() {
return new Point(this.cardRect.x, this.cardRect.y);
}
public int getComponentX() {
return componentRect.x;
}
public int getComponentY() {
return componentRect.y;
}
public int getComponentWidth() {
return componentRect.width;
}
public int getComponentHeight() {
return componentRect.height;
}
public Rectangle getCardBounds() {
// must be copy
return new Rectangle(this.cardRect);
}
public Rectangle getComponentBounds() {
// must be copy
return new Rectangle(this.componentRect);
}
}

View file

@ -0,0 +1,77 @@
package mage.cards;
import java.awt.*;
/**
* Inner our outer/draw spaces in cards (example: if you want add free space for animation for icons drawing)
*
* @author JayDi85
*/
public class MageCardSpace {
public static final MageCardSpace empty = new MageCardSpace(0, 0, 0, 0);
int left;
int right;
int top;
int bottom;
Color debugColor = null; // add colored border for draw debug
public MageCardSpace(int left, int right, int top, int bottom) {
this.left = left;
this.right = right;
this.top = top;
this.bottom = bottom;
}
public MageCardSpace withDebugColor(Color color) {
this.debugColor = color;
return this;
}
public int getLeft() {
return left;
}
public int getRight() {
return right;
}
public int getTop() {
return top;
}
public int getBottom() {
return bottom;
}
public int getWidth() {
return this.left + this.right;
}
public int getHeight() {
return this.top + this.bottom;
}
public Color getDebugColor() {
return debugColor;
}
/**
* Creates combined space (sums all values from each space and clear a debug color)
*
* @param spaces list of spaces to combine
* @return
*/
public static MageCardSpace combine(MageCardSpace... spaces) {
MageCardSpace res = new MageCardSpace(0, 0, 0, 0);
for (MageCardSpace space : spaces) {
res.left += space.left;
res.right += space.right;
res.top += space.top;
res.bottom += space.bottom;
}
return res;
}
}

View file

@ -2,19 +2,19 @@ package mage.cards;
import mage.view.PermanentView;
import java.util.List;
public abstract class MagePermanent extends MageCard {
private static final long serialVersionUID = -3469258620601702171L;
public abstract List<MagePermanent> getLinks();
public abstract void update(PermanentView card);
public abstract PermanentView getOriginalPermanent();
public boolean isCreature(){
public boolean isCreature() {
return getOriginal().isCreature();
}
public boolean isLand(){
public boolean isLand() {
return getOriginal().isLand();
}

View file

@ -1,11 +1,3 @@
/*
* TextPopup.java
*
* Created on Apr 6, 2010, 9:36:13 AM
*/
package mage.cards;
/**

View file

@ -1,11 +1,12 @@
package mage.cards.action;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
public interface ActionCallback {
void mouseClicked(MouseEvent e, TransferData data);
void mouseClicked(MouseEvent e, TransferData data, boolean doubleClick);
void mousePressed(MouseEvent e, TransferData data);
@ -23,4 +24,13 @@ public interface ActionCallback {
void hideOpenComponents();
void popupMenuCard(MouseEvent e, TransferData data);
/**
* Show popup menu
*
* @param e
* @param sourceComponent custom source component for the event, must support CardEventProducer
*/
void popupMenuPanel(MouseEvent e, Component sourceComponent);
}

View file

@ -1,25 +1,35 @@
package mage.cards.action;
import java.awt.Component;
import java.awt.Point;
import java.util.UUID;
import mage.cards.MageCard;
import mage.cards.TextPopup;
import mage.view.CardView;
import java.awt.*;
import java.util.UUID;
/**
* Data for main card panel events like mouse moves or clicks
*/
public class TransferData {
private Component component;
private MageCard component; // real card panel (it may lie under multiple layer panels, so use getTopPanelRef for top)
private TextPopup popupText;
private Point locationOnScreen;
private Point locationOnScreen; // must contains REAL card location (e.g. without outer/draw spaces), so use getCardLocationOnScreen to update it
private int popupOffsetX;
private int popupOffsetY;
private UUID gameId;
private CardView card;
public Component getComponent() {
/**
* If you use it with cards then call top layer panel like data.getComponent().getTopPanelRef()
*
* @return
*/
public MageCard getComponent() {
return component;
}
public void setComponent(Component component) {
public void setComponent(MageCard component) {
this.component = component;
}

View file

@ -1,10 +1,12 @@
package mage.cards.action.impl;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import mage.cards.action.ActionCallback;
import mage.cards.action.TransferData;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
/**
* Callback that does nothing on any action
*
@ -38,7 +40,7 @@ public class EmptyCallback implements ActionCallback {
}
@Override
public void mouseClicked(MouseEvent e, TransferData data) {
public void mouseClicked(MouseEvent e, TransferData data, boolean doubleClick) {
}
@Override
@ -49,4 +51,13 @@ public class EmptyCallback implements ActionCallback {
public void mouseReleased(MouseEvent e, TransferData data) {
}
@Override
public void popupMenuCard(MouseEvent e, TransferData data) {
}
@Override
public void popupMenuPanel(MouseEvent e, Component sourceComponent) {
}
}

View file

@ -28,6 +28,7 @@ public enum ClientCallbackMethod {
GAME_INFORM_PERSONAL("gameInformPersonal"),
GAME_ERROR("gameError"),
GAME_UPDATE("gameUpdate"),
GAME_REDRAW_GUI("gameRedrawGUI", true),
DRAFT_OVER("draftOver"),
REPLAY_DONE("replayDone"),
USER_REQUEST_DIALOG("userRequestDialog"),
@ -44,13 +45,22 @@ public enum ClientCallbackMethod {
GAME_PLAY_XMANA("gamePlayXMana"),
GAME_GET_AMOUNT("gameSelectAmount"),
DRAFT_INIT("draftInit"),
// DRAFT_INFORM("draftInform"),
DRAFT_PICK("draftPick"),
DRAFT_UPDATE("draftUpdate");
String value;
String code;
boolean isClientSideMessage;
ClientCallbackMethod(String value) {
this.value = value;
ClientCallbackMethod(String code) {
this(code, false);
}
ClientCallbackMethod(String code, boolean isClientSideMessage) {
this.code = code;
this.isClientSideMessage = isClientSideMessage;
}
public boolean isClientSideMessage() {
return this.isClientSideMessage;
}
}

View file

@ -1,6 +1,6 @@
package mage.interfaces.plugin;
import mage.cards.MagePermanent;
import mage.cards.MageCard;
import mage.cards.action.ActionCallback;
import mage.view.CardView;
import mage.view.PermanentView;
@ -16,17 +16,16 @@ import java.util.UUID;
* Interface for card plugins
*
* @author nantuko
* @version 0.1 31.10.2010 #getMagePermanent, #sortPermanents
*/
public interface CardPlugin extends Plugin {
MagePermanent getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback,
boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender);
MagePermanent getMageCard(CardView permanent, Dimension dimension, UUID gameId, ActionCallback callback,
MageCard getMagePermanent(PermanentView permanent, Dimension dimension, UUID gameId, ActionCallback callback,
boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender);
int sortPermanents(Map<String, JComponent> ui, Map<UUID, MagePermanent> cards, boolean nonPermanentsOwnRow, boolean topPanel);
MageCard getMageCard(CardView permanent, Dimension dimension, UUID gameId, ActionCallback callback,
boolean canBeFoil, boolean loadImage, int renderMode, boolean needFullPermanentRender);
int sortPermanents(Map<String, JComponent> ui, Map<UUID, MageCard> cards, boolean nonPermanentsOwnRow, boolean topPanel);
/**
* Download various symbols (mana, tap, set).
@ -35,9 +34,21 @@ public interface CardPlugin extends Plugin {
*/
void downloadSymbols(String imagesDir);
void onAddCard(MagePermanent card, int count);
/**
* Uses for show/hide animation on the battlefield
*
* @param card
* @param count
*/
void onAddCard(MageCard card, int count);
void onRemoveCard(MagePermanent card, int count);
/**
* Uses for show/hide animation on the battlefield
*
* @param card
* @param count
*/
void onRemoveCard(MageCard card, int count);
JComponent getCardInfoPane();

View file

@ -116,6 +116,9 @@ public class SessionImpl implements Session {
}
private void showMessageToUser(String message) {
if (message.contains("free port for use")) {
message += " (try to close and restart a client app)";
}
client.showMessage("Remote task error. " + message);
}
@ -558,15 +561,6 @@ public class SessionImpl implements Session {
@Override
public void handleCallback(Callback callback) throws HandleCallbackException {
try {
// Object object = callback.getCallbackObject();
// if (((ClientCallback) object).getMethod().equals(ClientCallbackMethod.GAME_TARGET)) {
// Object data = ((ClientCallback) object).getData();
// if (data instanceof GameClientMessage) {
// GameClientMessage message = (GameClientMessage) ((ClientCallback) object).getData();
// logger.info("Client Session Event->" + ((ClientCallback) object).getMethod() + " (id:" + ((ClientCallback) object).getMessageId() + ") " + message.getMessage()
// );
// }
// }
client.processCallback((ClientCallback) callback.getCallbackObject());
} catch (Exception ex) {
logger.error("handleCallback error", ex);

View file

@ -1,51 +0,0 @@
package mage.utils;
import mage.ObjectColor;
import mage.view.CardView;
import java.util.List;
/**
* Utility class for {@link CardView}
*
* @version 0.1 02.11.2010
* @author nantuko
*/
public final class CardColorUtil {
private static final String regexBlack = ".*\\x7b.{0,2}B.{0,2}\\x7d.*";
private static final String regexBlue = ".*\\x7b.{0,2}U.{0,2}\\x7d.*";
private static final String regexRed = ".*\\x7b.{0,2}R.{0,2}\\x7d.*";
private static final String regexGreen = ".*\\x7b.{0,2}G.{0,2}\\x7d.*";
private static final String regexWhite = ".*\\x7b.{0,2}W.{0,2}\\x7d.*";
public static int getColorIdentitySortValue(List<String> manaCost, ObjectColor originalColor, List<String> rules) {
ObjectColor color = new ObjectColor(originalColor);
for (String rule : rules) {
rule = rule.replaceAll("(?i)<i.*?</i>", ""); // Ignoring reminder text in italic
if (rule.matches(regexBlack)) {
color.setBlack(true);
}
if (rule.matches(regexBlue)) {
color.setBlue(true);
}
if (rule.matches(regexGreen)) {
color.setGreen(true);
}
if (rule.matches(regexRed)) {
color.setRed(true);
}
if (rule.matches(regexWhite)) {
color.setWhite(true);
}
}
int hash = 3;
hash = 23 * hash + (color.isWhite() || manaCost.contains("{W}") ? 1 : 0);
hash = 23 * hash + (color.isBlue() || manaCost.contains("{U}") ? 1 : 0);
hash = 23 * hash + (color.isBlack() || manaCost.contains("{B}") ? 1 : 0);
hash = 23 * hash + (color.isRed() || manaCost.contains("{R}") ? 1 : 0);
hash = 23 * hash + (color.isGreen() || manaCost.contains("{G}") ? 1 : 0);
return hash;
}
}

View file

@ -10,6 +10,7 @@ import mage.abilities.SpellAbility;
import mage.abilities.costs.mana.ManaCosts;
import mage.abilities.effects.Effect;
import mage.abilities.effects.Effects;
import mage.abilities.icon.CardIcon;
import mage.abilities.keyword.AftermathAbility;
import mage.cards.*;
import mage.cards.mock.MockCard;
@ -118,6 +119,7 @@ public class CardView extends SimpleCardView {
protected boolean canAttack;
protected boolean canBlock;
protected boolean inViewerOnly;
protected List<CardIcon> cardIcons = new ArrayList<>(); // additional icons to render
protected Card originalCard = null;
@ -138,7 +140,7 @@ public class CardView extends SimpleCardView {
this(card, null, false);
this.id = simpleCardView.getId();
this.isPlayable = simpleCardView.isPlayable;
this.playableStats = simpleCardView.playableStats.copy();
this.isChoosable = simpleCardView.isChoosable;
this.isSelected = simpleCardView.isSelected;
}
@ -148,7 +150,7 @@ public class CardView extends SimpleCardView {
this.id = cardId;
}
public CardView(CardView cardView) {
public CardView(final CardView cardView) {
super(cardView);
// generetate new ID (TODO: why new ID?)
@ -222,6 +224,9 @@ public class CardView extends SimpleCardView {
this.canBlock = cardView.canBlock;
this.inViewerOnly = cardView.inViewerOnly;
this.originalCard = cardView.originalCard == null ? null : cardView.originalCard.copy();
if (cardView.cardIcons != null) {
cardView.cardIcons.forEach(icon -> this.cardIcons.add(icon.copy()));
}
}
/**
@ -408,6 +413,11 @@ public class CardView extends SimpleCardView {
controlledByOwner = false;
}
}
// card icons for permanents on battlefield
permanent.getAbilities(game).forEach(ability -> {
this.cardIcons.addAll(ability.getIcons());
});
} else {
if (card.isCopy()) {
this.mageObjectType = MageObjectType.COPY_CARD;
@ -1134,4 +1144,8 @@ public class CardView extends SimpleCardView {
public Card getOriginalCard() {
return this.originalCard;
}
public List<CardIcon> getCardIcons() {
return this.cardIcons;
}
}

View file

@ -2,6 +2,7 @@ package mage.view;
import mage.cards.Card;
import mage.game.command.Emblem;
import mage.players.PlayableObjectStats;
import java.io.Serializable;
import java.util.List;
@ -16,8 +17,7 @@ public class EmblemView implements CommandObjectView, Serializable {
protected String name;
protected String expansionSetCode;
protected List<String> rules;
protected boolean isPlayable = false;
protected int playableAmount = 0;
protected PlayableObjectStats playableStats = new PlayableObjectStats();
public EmblemView(Emblem emblem, Card sourceCard) {
this.id = emblem.getId();
@ -57,25 +57,19 @@ public class EmblemView implements CommandObjectView, Serializable {
return rules;
}
@Override
public boolean isPlayable() {
return isPlayable;
return this.playableStats.getPlayableAmount() > 0;
}
@Override
public void setPlayable(boolean isPlayable) {
this.isPlayable = isPlayable;
public void setPlayableStats(PlayableObjectStats playableStats) {
this.playableStats = playableStats;
}
@Override
public void setPlayableAmount(int playableAmount) {
this.playableAmount = playableAmount;
}
@Override
public int getPlayableAmount() {
return playableAmount;
public PlayableObjectStats getPlayableStats() {
return this.playableStats;
}
@Override

View file

@ -21,6 +21,7 @@ import mage.game.permanent.PermanentToken;
import mage.game.stack.Spell;
import mage.game.stack.StackAbility;
import mage.game.stack.StackObject;
import mage.players.PlayableObjectsList;
import mage.players.Player;
import mage.watchers.common.CastSpellLastTurnWatcher;
import org.apache.log4j.Logger;
@ -42,7 +43,7 @@ public class GameView implements Serializable {
private final int priorityTime;
private final List<PlayerView> players = new ArrayList<>();
private CardsView hand;
private Map<UUID, Integer> canPlayObjects;
private PlayableObjectsList canPlayObjects;
private Map<String, SimpleCardsView> opponentHands;
private Map<String, SimpleCardsView> watchedHands;
private final CardsView stack = new CardsView();
@ -313,11 +314,11 @@ public class GameView implements Serializable {
return isPlayer;
}
public Map<UUID, Integer> getCanPlayObjects() {
public PlayableObjectsList getCanPlayObjects() {
return canPlayObjects;
}
public void setCanPlayObjects(Map<UUID, Integer> canPlayObjects) {
public void setCanPlayObjects(PlayableObjectsList canPlayObjects) {
this.canPlayObjects = canPlayObjects;
}

View file

@ -2,6 +2,7 @@ package mage.view;
import mage.cards.Card;
import mage.game.command.Plane;
import mage.players.PlayableObjectStats;
import java.io.Serializable;
import java.util.List;
@ -16,9 +17,7 @@ public class PlaneView implements CommandObjectView, Serializable {
protected String name;
protected String expansionSetCode;
protected List<String> rules;
protected boolean isPlayable = false;
protected int playableAmount = 0;
protected PlayableObjectStats playableStats = new PlayableObjectStats();
public PlaneView(Plane plane, Card sourceCard) {
this.id = plane.getId();
@ -60,22 +59,17 @@ public class PlaneView implements CommandObjectView, Serializable {
@Override
public boolean isPlayable() {
return isPlayable;
return this.playableStats.getPlayableAmount() > 0;
}
@Override
public void setPlayable(boolean isPlayable) {
this.isPlayable = isPlayable;
public void setPlayableStats(PlayableObjectStats playableStats) {
this.playableStats = playableStats;
}
@Override
public void setPlayableAmount(int playableAmount) {
this.playableAmount = playableAmount;
}
@Override
public int getPlayableAmount() {
return playableAmount;
public PlayableObjectStats getPlayableStats() {
return this.playableStats;
}
@Override

View file

@ -1,5 +1,7 @@
package mage.view;
import mage.players.PlayableObjectStats;
/**
* @author JayDi85
*/
@ -7,11 +9,9 @@ public interface SelectableObjectView {
boolean isPlayable();
void setPlayable(boolean isPlayable);
void setPlayableStats(PlayableObjectStats playableStats);
void setPlayableAmount(int playableAmount);
int getPlayableAmount();
PlayableObjectStats getPlayableStats();
boolean isChoosable();

View file

@ -1,6 +1,7 @@
package mage.view;
import com.google.gson.annotations.Expose;
import mage.players.PlayableObjectStats;
import java.io.Serializable;
import java.util.UUID;
@ -18,10 +19,9 @@ public class SimpleCardView implements Serializable, SelectableObjectView {
protected boolean usesVariousArt;
protected boolean gameObject;
protected boolean isPlayable;
protected boolean isChoosable;
protected boolean isSelected;
protected int playableAmount; // playable abilities count on object
protected PlayableObjectStats playableStats = new PlayableObjectStats();
public SimpleCardView(final SimpleCardView view) {
this.id = view.id;
@ -32,10 +32,9 @@ public class SimpleCardView implements Serializable, SelectableObjectView {
this.usesVariousArt = view.usesVariousArt;
this.gameObject = view.gameObject;
this.isPlayable = view.isPlayable;
this.isChoosable = view.isChoosable;
this.isSelected = view.isSelected;
this.playableAmount = view.playableAmount;
this.playableStats = view.playableStats.copy();
}
public SimpleCardView(UUID id, String expansionSetCode, String cardNumber, boolean usesVariousArt, String tokenSetCode, String tokenDescriptor) {
@ -82,22 +81,17 @@ public class SimpleCardView implements Serializable, SelectableObjectView {
@Override
public boolean isPlayable() {
return isPlayable;
return this.playableStats.getPlayableAmount() > 0;
}
@Override
public void setPlayable(boolean isPlayable) {
this.isPlayable = isPlayable;
public void setPlayableStats(PlayableObjectStats playableStats) {
this.playableStats = playableStats;
}
@Override
public void setPlayableAmount(int playableAmount) {
this.playableAmount = playableAmount;
}
@Override
public int getPlayableAmount() {
return playableAmount;
public PlayableObjectStats getPlayableStats() {
return this.playableStats;
}
@Override