Refactor: added copyFrom info for all objects (original card used for copy, copy of copy and etc);

This commit is contained in:
Oleg Agafonov 2018-11-29 19:29:39 +04:00
parent 28ac95cb10
commit 59bda7f1d5
25 changed files with 269 additions and 220 deletions

View file

@ -64,20 +64,14 @@ public interface MageObject extends MageItem, Serializable {
void adjustTargets(Ability ability, Game game);
// memory object copy (not mtg)
MageObject copy();
/**
* Defines that MageObject is a copy of another object
*
* @param isCopy
*/
void setCopy(boolean isCopy);
// copied card info (mtg)
void setCopy(boolean isCopy, MageObject copiedFrom);
MageObject getCopyFrom();
/**
* Checks if current MageObject is a copy of another object
*
* @return
*/
boolean isCopy();
int getZoneChangeCounter(Game game);

View file

@ -1,11 +1,5 @@
package mage;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;
import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
@ -20,16 +14,14 @@ import mage.abilities.mana.ActivatedManaAbilityImpl;
import mage.abilities.text.TextPart;
import mage.abilities.text.TextPartSubType;
import mage.cards.FrameStyle;
import mage.constants.CardType;
import mage.constants.SubLayer;
import mage.constants.SubType;
import mage.constants.SubTypeSet;
import mage.constants.SuperType;
import mage.constants.*;
import mage.game.Game;
import mage.game.events.ZoneChangeEvent;
import mage.util.GameLog;
import mage.util.SubTypeList;
import java.util.*;
public abstract class MageObjectImpl implements MageObject {
protected UUID objectId;
@ -48,6 +40,7 @@ public abstract class MageObjectImpl implements MageObject {
protected MageInt power;
protected MageInt toughness;
protected boolean copy;
protected MageObject copyFrom; // copied card INFO (used to call original adjusters)
protected List<TextPart> textParts;
public MageObjectImpl() {
@ -82,6 +75,7 @@ public abstract class MageObjectImpl implements MageObject {
isAllCreatureTypes = object.isAllCreatureTypes;
supertype.addAll(object.supertype);
this.copy = object.copy;
this.copyFrom = (object.copyFrom != null ? object.copyFrom.copy() : null);
textParts = new ArrayList<>();
textParts.addAll(object.textParts);
}
@ -263,8 +257,14 @@ public abstract class MageObjectImpl implements MageObject {
}
@Override
public void setCopy(boolean isCopy) {
public void setCopy(boolean isCopy, MageObject copyFrom) {
this.copy = isCopy;
this.copyFrom = (copyFrom != null ? copyFrom.copy() : null);
}
@Override
public MageObject getCopyFrom() {
return this.copyFrom;
}
@Override
@ -322,7 +322,7 @@ public abstract class MageObjectImpl implements MageObject {
*/
@Override
public void removePTCDA() {
for (Iterator<Ability> iter = this.getAbilities().iterator(); iter.hasNext();) {
for (Iterator<Ability> iter = this.getAbilities().iterator(); iter.hasNext(); ) {
Ability ability = iter.next();
for (Effect effect : ability.getEffects()) {
if (effect instanceof ContinuousEffect && ((ContinuousEffect) effect).getSublayer() == SubLayer.CharacteristicDefining_7a) {

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common;
import mage.MageObject;
@ -16,7 +15,6 @@ import mage.util.functions.ApplyToPermanent;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class CopyEffect extends ContinuousEffectImpl {
@ -90,7 +88,13 @@ public class CopyEffect extends ContinuousEffectImpl {
}
protected boolean copyToPermanent(Permanent permanent, Game game, Ability source) {
permanent.setCopy(true);
if (copyFromObject.getCopyFrom() != null) {
// copy from temp blueprints (they are already copies)
permanent.setCopy(true, copyFromObject.getCopyFrom());
} else {
// copy object to object
permanent.setCopy(true, copyFromObject);
}
permanent.setName(copyFromObject.getName());
permanent.getColor(game).setColor(copyFromObject.getColor(game));
permanent.getManaCost().clear();

View file

@ -1,4 +1,3 @@
package mage.abilities.effects.common;
import mage.abilities.Ability;
@ -12,7 +11,6 @@ import mage.game.stack.Spell;
import mage.players.Player;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class ExileSpellEffect extends OneShotEffect implements MageSingleton {
@ -38,7 +36,7 @@ public class ExileSpellEffect extends OneShotEffect implements MageSingleton {
Player controller = game.getPlayer(source.getControllerId());
if (controller != null) {
Spell spell = game.getStack().getSpell(source.getId());
if (spell != null && !spell.isCopiedSpell()) {
if (spell != null && !spell.isCopy()) {
Card spellCard = spell.getCard();
if (spellCard != null) {
controller.moveCards(spellCard, Zone.EXILED, source, game);

View file

@ -1,7 +1,5 @@
package mage.abilities.keyword;
import java.util.UUID;
import mage.MageObjectReference;
import mage.abilities.Ability;
import mage.abilities.DelayedTriggeredAbility;
@ -21,6 +19,8 @@ import mage.game.events.ZoneChangeEvent;
import mage.game.stack.Spell;
import mage.players.Player;
import java.util.UUID;
/**
* This ability has no effect by default and will always return false on the
* call to apply. This is because of how the {@link ReboundEffect} works. It
@ -93,7 +93,7 @@ class ReboundCastFromHandReplacementEffect extends ReplacementEffectImpl {
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Spell sourceSpell = game.getStack().getSpell(source.getSourceId());
if (sourceSpell != null && sourceSpell.isCopiedSpell()) {
if (sourceSpell != null && sourceSpell.isCopy()) {
return false;
} else {
Card sourceCard = game.getCard(source.getSourceId());

View file

@ -1,9 +1,6 @@
package mage.cards;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import mage.MageObject;
import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
@ -13,8 +10,11 @@ import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.game.Game;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public abstract class SplitCard extends CardImpl {
@ -58,10 +58,10 @@ public abstract class SplitCard extends CardImpl {
}
@Override
public void setCopy(boolean isCopy) {
super.setCopy(isCopy);
leftHalfCard.setCopy(isCopy);
rightHalfCard.setCopy(isCopy);
public void setCopy(boolean isCopy, MageObject copiedFrom) {
super.setCopy(isCopy, copiedFrom);
leftHalfCard.setCopy(isCopy, copiedFrom);
rightHalfCard.setCopy(isCopy, copiedFrom);
}
@Override

View file

@ -1,8 +1,6 @@
package mage.designations;
/**
*
* @author LevelX2
*/
public class CitysBlessing extends Designation {
@ -10,4 +8,13 @@ public class CitysBlessing extends Designation {
public CitysBlessing() {
super(DesignationType.CITYS_BLESSING, "RIX");
}
private CitysBlessing(final CitysBlessing card) {
super(card);
}
@Override
public CitysBlessing copy() {
return new CitysBlessing(this);
}
}

View file

@ -1,14 +1,5 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package mage.designations;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.ObjectColor;
@ -28,8 +19,12 @@ import mage.game.events.ZoneChangeEvent;
import mage.util.GameLog;
import mage.util.SubTypeList;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
/**
*
* @author LevelX2
*/
public abstract class Designation implements MageObject {
@ -43,6 +38,8 @@ public abstract class Designation implements MageObject {
private DesignationType designationType;
private UUID id;
private FrameStyle frameStyle;
private boolean copy;
private MageObject copyFrom; // copied card INFO (used to call original adjusters)
private Abilities<Ability> abilites = new AbilitiesImpl<>();
private String expansionSetCodeForImage;
private final boolean unique; // can a designation be added multiple times (false) or only once to an object (true)
@ -65,6 +62,8 @@ public abstract class Designation implements MageObject {
this.name = designation.name;
this.designationType = designation.designationType;
this.frameStyle = designation.frameStyle;
this.copy = designation.copy;
this.copyFrom = (designation.copyFrom != null ? designation.copyFrom.copy() : null);
this.abilites = designation.abilites.copy();
this.unique = designation.unique;
}
@ -78,6 +77,22 @@ public abstract class Designation implements MageObject {
this.id = UUID.randomUUID();
}
@Override
public void setCopy(boolean isCopy, MageObject copyFrom) {
this.copy = isCopy;
this.copyFrom = (copyFrom != null ? copyFrom.copy() : null);
}
@Override
public boolean isCopy() {
return this.copy;
}
@Override
public MageObject getCopyFrom() {
return this.copyFrom;
}
@Override
public String getName() {
return name;
@ -198,20 +213,6 @@ public abstract class Designation implements MageObject {
public void adjustTargets(Ability ability, Game game) {
}
@Override
public void setCopy(boolean isCopy) {
}
@Override
public boolean isCopy() {
return false;
}
@Override
public Designation copy() {
return this;
}
@Override
public int getZoneChangeCounter(Game game) {
return 1; // Emblems can't move zones until now so return always 1
@ -232,7 +233,6 @@ public abstract class Designation implements MageObject {
}
/**
*
* @param game
* @param controllerId
*/

View file

@ -1,4 +1,3 @@
package mage.designations;
import mage.MageObject;
@ -15,7 +14,6 @@ import mage.game.permanent.Permanent;
import mage.target.targetpointer.FixedTarget;
/**
*
* @author LevelX2
*/
public class Monarch extends Designation {
@ -25,6 +23,15 @@ public class Monarch extends Designation {
addAbility(new MonarchDrawTriggeredAbility());
addAbility(new MonarchDealsCombatDamageToAPlayerTriggeredAbility());
}
private Monarch(final Monarch monarch) {
super(monarch);
}
@Override
public Monarch copy() {
return new Monarch(this);
}
}
// At the beginning of the monarch's end step, that player draws a card

View file

@ -44,12 +44,12 @@ public class FilterPlayer extends FilterImpl<Player> {
return object instanceof Player;
}
public boolean match(Player player, UUID sourceId, UUID playerId, Game game) {
if (!this.match(player, game)) {
public boolean match(Player checkPlayer, UUID sourceId, UUID sourceControllerId, Game game) {
if (!this.match(checkPlayer, game)) {
return false;
}
return Predicates.and(extraPredicates).apply(new ObjectSourcePlayer(player, sourceId, playerId), game);
return Predicates.and(extraPredicates).apply(new ObjectSourcePlayer(checkPlayer, sourceId, sourceControllerId), game);
}
@Override

View file

@ -12,8 +12,8 @@ public class ObjectSourcePlayer<T> extends ObjectPlayer<T> {
protected final UUID sourceId;
public ObjectSourcePlayer(T object, UUID sourceId, UUID playerId) {
super(object, playerId);
public ObjectSourcePlayer(T object, UUID sourceId, UUID sourceControllerId) {
super(object, sourceControllerId);
this.sourceId = sourceId;
}

View file

@ -1638,6 +1638,7 @@ public abstract class GameImpl implements Game, Serializable {
if (newBluePrint == null) {
newBluePrint = copyFromPermanent.copy();
newBluePrint.reset(this);
//getState().addCard(permanent);
if (copyFromPermanent.isMorphed() || copyFromPermanent.isManifested()) {
MorphAbility.setPermanentToFaceDownCreature(newBluePrint);
@ -1651,6 +1652,9 @@ public abstract class GameImpl implements Game, Serializable {
applier.apply(this, newBluePrint, source, copyToPermanentId);
}
// save original copy link (handle copy of copies too)
newBluePrint.setCopy(true, (copyFromPermanent.getCopyFrom() != null ? copyFromPermanent.getCopyFrom() : copyFromPermanent));
CopyEffect newEffect = new CopyEffect(duration, newBluePrint, copyToPermanentId);
newEffect.newId();
newEffect.setApplier(applier);

View file

@ -1,8 +1,5 @@
package mage.game;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import mage.MageObject;
import mage.abilities.*;
import mage.abilities.effects.ContinuousEffect;
@ -35,15 +32,17 @@ import mage.util.ThreadLocalStringBuilder;
import mage.watchers.Watcher;
import mage.watchers.Watchers;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
/**
*
* @author BetaSteward_at_googlemail.com
*
* <p>
* since at any time the game state may be copied and restored you cannot rely
* on any object maintaining it's instance it then becomes necessary to only
* refer to objects by their ids since these will always remain constant
* throughout its lifetime
*
*/
public class GameState implements Serializable, Copyable<GameState> {
@ -590,6 +589,7 @@ public class GameState implements Serializable, Copyable<GameState> {
// public void addMessage(String message) {
// this.messages.add(message);
// }
/**
* Returns a list of all players of the game ignoring range or if a player
* has lost or left the game.
@ -758,7 +758,7 @@ public class GameState implements Serializable, Copyable<GameState> {
}
for (Map.Entry<ZoneChangeData, List<GameEvent>> entry : eventsByKey.entrySet()) {
Set<Card> movedCards = new LinkedHashSet<>();
for (Iterator<GameEvent> it = entry.getValue().iterator(); it.hasNext();) {
for (Iterator<GameEvent> it = entry.getValue().iterator(); it.hasNext(); ) {
GameEvent event = it.next();
ZoneChangeEvent castEvent = (ZoneChangeEvent) event;
UUID targetId = castEvent.getTargetId();
@ -943,7 +943,7 @@ public class GameState implements Serializable, Copyable<GameState> {
/**
* Other abilities are used to implement some special kind of continuous
* effects that give abilities to non permanents.
*
* <p>
* Crucible of Worlds - You may play land cards from your graveyard. Past in
* Flames - Each instant and sorcery card in your graveyard gains flashback
* until end of turn. The flashback cost is equal to its mana cost. Varolz,
@ -984,7 +984,7 @@ public class GameState implements Serializable, Copyable<GameState> {
* @param attachedTo
* @param ability
* @param copyAbility copies non MageSingleton abilities before adding to
* state
* state
*/
public void addOtherAbility(Card attachedTo, Ability ability, boolean copyAbility) {
Ability newAbility;
@ -1134,7 +1134,7 @@ public class GameState implements Serializable, Copyable<GameState> {
Card copiedCard = cardToCopy.copy();
copiedCard.assignNewId();
copiedCard.setOwnerId(source.getControllerId());
copiedCard.setCopy(true);
copiedCard.setCopy(true, cardToCopy);
copiedCards.put(copiedCard.getId(), copiedCard);
addCard(copiedCard);
if (copiedCard.isSplitCard()) {

View file

@ -1,10 +1,7 @@
package mage.game.command;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.ObjectColor;
import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
@ -24,9 +21,15 @@ import mage.game.events.ZoneChangeEvent;
import mage.util.GameLog;
import mage.util.SubTypeList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
public class Commander implements CommandObject {
private final Card sourceObject;
private boolean copy;
private MageObject copyFrom; // copied card INFO (used to call original adjusters)
private final Abilities<Ability> abilities = new AbilitiesImpl<>();
public Commander(Card card) {
@ -40,8 +43,10 @@ public class Commander implements CommandObject {
}
}
private Commander(Commander copy) {
this.sourceObject = copy.sourceObject;
private Commander(final Commander commander) {
this.sourceObject = commander.sourceObject;
this.copy = commander.copy;
this.copyFrom = (commander.copyFrom != null ? commander.copyFrom.copy() : null);
}
@Override
@ -68,6 +73,22 @@ public class Commander implements CommandObject {
return new Commander(this);
}
@Override
public void setCopy(boolean isCopy, MageObject copyFrom) {
this.copy = isCopy;
this.copyFrom = (copyFrom != null ? copyFrom.copy() : null);
}
@Override
public boolean isCopy() {
return this.copy;
}
@Override
public MageObject getCopyFrom() {
return this.copyFrom;
}
@Override
public String getName() {
return sourceObject.getName();
@ -170,15 +191,6 @@ public class Commander implements CommandObject {
public void adjustTargets(Ability ability, Game game) {
}
@Override
public void setCopy(boolean isCopy) {
}
@Override
public boolean isCopy() {
return false;
}
@Override
public UUID getId() {
return sourceObject.getId();

View file

@ -1,8 +1,5 @@
package mage.game.command;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.ObjectColor;
@ -25,6 +22,10 @@ import mage.game.events.ZoneChangeEvent;
import mage.util.GameLog;
import mage.util.SubTypeList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
/**
* @author nantuko
*/
@ -38,6 +39,8 @@ public class Emblem implements CommandObject {
private UUID id;
private UUID controllerId;
private MageObject sourceObject;
private boolean copy;
private MageObject copyFrom; // copied card INFO (used to call original adjusters)
private FrameStyle frameStyle;
private Abilities<Ability> abilites = new AbilitiesImpl<>();
private String expansionSetCodeForImage = "";
@ -52,6 +55,8 @@ public class Emblem implements CommandObject {
this.frameStyle = emblem.frameStyle;
this.controllerId = emblem.controllerId;
this.sourceObject = emblem.sourceObject;
this.copy = emblem.copy;
this.copyFrom = (emblem.copyFrom != null ? emblem.copyFrom : null);
this.abilites = emblem.abilites.copy();
this.expansionSetCodeForImage = emblem.expansionSetCodeForImage;
}
@ -101,6 +106,22 @@ public class Emblem implements CommandObject {
this.abilites.setControllerId(controllerId);
}
@Override
public void setCopy(boolean isCopy, MageObject copyFrom) {
this.copy = isCopy;
this.copyFrom = (copyFrom != null ? copyFrom.copy() : null);
}
@Override
public boolean isCopy() {
return this.copy;
}
@Override
public MageObject getCopyFrom() {
return this.copyFrom;
}
@Override
public String getName() {
return name;
@ -204,15 +225,6 @@ public class Emblem implements CommandObject {
return this.id;
}
@Override
public void setCopy(boolean isCopy) {
}
@Override
public boolean isCopy() {
return false;
}
@Override
public Emblem copy() {
return new Emblem(this);

View file

@ -41,6 +41,8 @@ public class Plane implements CommandObject {
private UUID id;
private UUID controllerId;
private MageObject sourceObject;
private boolean copy;
private MageObject copyFrom; // copied card INFO (used to call original adjusters)
private FrameStyle frameStyle;
private Abilities<Ability> abilites = new AbilitiesImpl<>();
private String expansionSetCodeForImage = "";
@ -56,6 +58,8 @@ public class Plane implements CommandObject {
this.frameStyle = plane.frameStyle;
this.controllerId = plane.controllerId;
this.sourceObject = plane.sourceObject;
this.copy = plane.copy;
this.copyFrom = (plane.copyFrom != null ? plane.copyFrom.copy() : null);
this.abilites = plane.abilites.copy();
this.expansionSetCodeForImage = plane.expansionSetCodeForImage;
}
@ -105,6 +109,22 @@ public class Plane implements CommandObject {
this.abilites.setControllerId(controllerId);
}
@Override
public void setCopy(boolean isCopy, MageObject copyFrom) {
this.copy = isCopy;
this.copyFrom = (copyFrom != null ? copyFrom.copy() : null);
}
@Override
public boolean isCopy() {
return this.copy;
}
@Override
public MageObject getCopyFrom() {
return this.copyFrom;
}
@Override
public String getName() {
return name;
@ -208,15 +228,6 @@ public class Plane implements CommandObject {
return this.id;
}
@Override
public void setCopy(boolean isCopy) {
}
@Override
public boolean isCopy() {
return false;
}
@Override
public Plane copy() {
return new Plane(this);

View file

@ -1,10 +1,5 @@
package mage.game.stack;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.Mana;
@ -39,8 +34,12 @@ import mage.players.Player;
import mage.util.GameLog;
import mage.util.SubTypeList;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class Spell extends StackObjImpl implements Card {
@ -63,7 +62,8 @@ public class Spell extends StackObjImpl implements Card {
private final UUID id;
private UUID controllerId;
private boolean copiedSpell;
private boolean copy;
private MageObject copyFrom; // copied card INFO (used to call original adjusters)
private boolean faceDown;
private boolean countered;
private boolean resolving = false;
@ -118,7 +118,8 @@ public class Spell extends StackObjImpl implements Card {
this.frameStyle = spell.frameStyle;
this.controllerId = spell.controllerId;
this.copiedSpell = spell.copiedSpell;
this.copy = spell.copy;
this.copyFrom = (spell.copyFrom != null ? spell.copyFrom.copy() : null);
this.faceDown = spell.faceDown;
this.countered = spell.countered;
this.resolving = spell.resolving;
@ -155,7 +156,7 @@ public class Spell extends StackObjImpl implements Card {
public String getActivatedMessage(Game game) {
StringBuilder sb = new StringBuilder();
if (isCopiedSpell()) {
if (isCopy()) {
sb.append(" copies ");
} else {
sb.append(" casts ");
@ -362,7 +363,7 @@ public class Spell extends StackObjImpl implements Card {
@Override
public void counter(UUID sourceId, Game game, Zone zone, boolean owner, ZoneDetail zoneDetail) {
this.countered = true;
if (!isCopiedSpell()) {
if (!isCopy()) {
Player player = game.getPlayer(game.getControllerId(sourceId));
if (player == null) {
player = game.getPlayer(getControllerId());
@ -706,7 +707,7 @@ public class Spell extends StackObjImpl implements Card {
newAbility.newId();
copy.addSpellAbility(newAbility);
}
copy.setCopy(true);
copy.setCopy(true, this);
copy.setControllerId(newController);
return copy;
}
@ -740,7 +741,7 @@ public class Spell extends StackObjImpl implements Card {
// 706.10a If a copy of a spell is in a zone other than the stack, it ceases to exist.
// If a copy of a card is in any zone other than the stack or the battlefield, it ceases to exist.
// These are state-based actions. See rule 704.
if (this.isCopiedSpell() && zone != Zone.STACK) {
if (this.isCopy() && zone != Zone.STACK) {
return true;
}
return card.moveToZone(zone, sourceId, game, flag, appliedEffects);
@ -753,7 +754,7 @@ public class Spell extends StackObjImpl implements Card {
@Override
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
if (this.isCopiedSpell()) {
if (this.isCopy()) {
game.getStack().remove(this, game);
return true;
}
@ -835,26 +836,24 @@ public class Spell extends StackObjImpl implements Card {
// do nothing
}
public void setCopiedSpell(boolean isCopied) {
this.copiedSpell = isCopied;
}
public boolean isCopiedSpell() {
return this.copiedSpell;
}
public Zone getFromZone() {
return this.fromZone;
}
@Override
public void setCopy(boolean isCopy) {
setCopiedSpell(isCopy);
public void setCopy(boolean isCopy, MageObject copyFrom) {
this.copy = isCopy;
this.copyFrom = (copyFrom != null ? copyFrom.copy() : null);
}
@Override
public boolean isCopy() {
return isCopiedSpell();
return this.copy;
}
@Override
public MageObject getCopyFrom() {
return this.copyFrom;
}
@Override

View file

@ -1,9 +1,5 @@
package mage.game.stack;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
import mage.MageInt;
import mage.MageObject;
import mage.ObjectColor;
@ -32,8 +28,12 @@ import mage.util.GameLog;
import mage.util.SubTypeList;
import mage.watchers.Watcher;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.UUID;
/**
*
* @author BetaSteward_at_googlemail.com
*/
public class StackAbility extends StackObjImpl implements Ability {
@ -47,6 +47,8 @@ public class StackAbility extends StackObjImpl implements Ability {
private final Ability ability;
private UUID controllerId;
private boolean copy;
private MageObject copyFrom; // copied card INFO (used to call original adjusters)
private String name;
private String expansionSetCode;
private TargetAdjuster targetAdjuster = null;
@ -60,6 +62,8 @@ public class StackAbility extends StackObjImpl implements Ability {
public StackAbility(final StackAbility stackAbility) {
this.ability = stackAbility.ability.copy();
this.controllerId = stackAbility.controllerId;
this.copy = stackAbility.copy;
this.copyFrom = (stackAbility.copyFrom != null ? stackAbility.copyFrom.copy() : null);
this.name = stackAbility.name;
this.expansionSetCode = stackAbility.expansionSetCode;
this.targetAdjuster = stackAbility.targetAdjuster;
@ -104,6 +108,22 @@ public class StackAbility extends StackObjImpl implements Ability {
}
}
@Override
public void setCopy(boolean isCopy, MageObject copyFrom) {
this.copy = isCopy;
this.copyFrom = (copyFrom != null ? copyFrom.copy() : null);
}
@Override
public boolean isCopy() {
return this.copy;
}
@Override
public MageObject getCopyFrom() {
return this.copyFrom;
}
@Override
public String getName() {
return name;
@ -408,15 +428,6 @@ public class StackAbility extends StackObjImpl implements Ability {
throw new UnsupportedOperationException("Not supported.");
}
@Override
public void setCopy(boolean isCopy) {
}
@Override
public boolean isCopy() {
return false;
}
@Override
public boolean getRuleAtTheTop() {
return this.ability.getRuleAtTheTop();

View file

@ -1,9 +1,5 @@
package mage.players;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
import mage.ConditionalMana;
import mage.MageObject;
import mage.MageObjectReference;
@ -72,6 +68,11 @@ import mage.util.GameLog;
import mage.util.RandomUtil;
import org.apache.log4j.Logger;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Map.Entry;
public abstract class PlayerImpl implements Player, Serializable {
private static final Logger logger = Logger.getLogger(PlayerImpl.class);
@ -2573,7 +2574,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
@ -2607,10 +2608,10 @@ 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
*/
@ -2767,7 +2768,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
@ -3319,7 +3320,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);
}
@ -3467,8 +3468,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<UUID> appliedEffects
Ability source, Game game,
boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects
) {
Set<Card> cardList = new HashSet<>();
if (card != null) {
@ -3479,22 +3480,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<Card> 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<Card> cards, Zone toZone,
Ability source, Game game,
boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects
Ability source, Game game,
boolean tapped, boolean faceDown, boolean byOwner, List<UUID> appliedEffects
) {
if (cards.isEmpty()) {
return true;
@ -3580,8 +3581,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<Card> cards = new HashSet<>();
cards.add(card);
@ -3590,8 +3591,8 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public boolean moveCardsToExile(Set<Card> cards, Ability source,
Game game, boolean withName, UUID exileId,
String exileZoneName
Game game, boolean withName, UUID exileId,
String exileZoneName
) {
if (cards.isEmpty()) {
return true;
@ -3606,14 +3607,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());
@ -3638,7 +3639,7 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public Set<Card> moveCardsToGraveyardWithInfo(Set<Card> allCards, Ability source,
Game game, Zone fromZone
Game game, Zone fromZone
) {
UUID sourceId = source == null ? null : source.getSourceId();
Set<Card> movedCards = new LinkedHashSet<>();
@ -3646,7 +3647,7 @@ public abstract class PlayerImpl implements Player, Serializable {
// identify cards from one owner
Cards cards = new CardsImpl();
UUID ownerId = null;
for (Iterator<Card> it = allCards.iterator(); it.hasNext();) {
for (Iterator<Card> it = allCards.iterator(); it.hasNext(); ) {
Card card = it.next();
if (cards.isEmpty()) {
ownerId = card.getOwnerId();
@ -3707,7 +3708,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;
@ -3736,8 +3737,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;
@ -3771,7 +3772,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;
}
@ -3786,7 +3787,7 @@ public abstract class PlayerImpl implements Player, Serializable {
}
} else if (card instanceof Spell) {
final Spell spell = (Spell) card;
if (spell.isCopiedSpell()) {
if (spell.isCopy()) {
// Copied spell, only remove from stack
game.getStack().remove(spell, game);
}