mirror of
https://github.com/correl/mage.git
synced 2024-11-15 11:09:30 +00:00
moved copied cards to GameState
This commit is contained in:
parent
42d34e754f
commit
18a4a98f1a
6 changed files with 328 additions and 95 deletions
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package org.mage.test.cards.copy;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public class IsochronScepterTest extends CardTestPlayerBase {
|
||||
|
||||
|
||||
/**
|
||||
* Isochron Scepter
|
||||
* Artifact, 2 (2)
|
||||
* Imprint — When Isochron Scepter enters the battlefield, you may exile an
|
||||
* instant card with converted mana cost 2 or less from your hand.
|
||||
* {2}, {T}: You may copy the exiled card. If you do, you may cast the copy
|
||||
* without paying its mana cost.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testImprint() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||
addCard(Zone.HAND, playerA, "Isochron Scepter");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
|
||||
addTarget(playerA, "Lightning Bolt");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Isochron Scepter", 1);
|
||||
assertExileCount("Lightning Bolt", 1);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyCard() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||
addCard(Zone.HAND, playerA, "Isochron Scepter");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
|
||||
addTarget(playerA, "Lightning Bolt");
|
||||
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{2},{T}:");
|
||||
setChoice(playerA, "Yes");
|
||||
setChoice(playerA, "Yes");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Isochron Scepter", 1);
|
||||
assertExileCount("Lightning Bolt", 1);
|
||||
assertGraveyardCount(playerA, "Lightning Bolt", 0);
|
||||
assertLife(playerB, 17);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyCardButDontCast() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Forest", 4);
|
||||
addCard(Zone.HAND, playerA, "Isochron Scepter");
|
||||
addCard(Zone.HAND, playerA, "Lightning Bolt");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Isochron Scepter");
|
||||
addTarget(playerA, "Lightning Bolt");
|
||||
activateAbility(1, PhaseStep.POSTCOMBAT_MAIN, playerA, "{2},{T}:");
|
||||
setChoice(playerA, "Yes");
|
||||
setChoice(playerA, "No");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertPermanentCount(playerA, "Isochron Scepter", 1);
|
||||
assertExileCount("Lightning Bolt", 1);
|
||||
assertGraveyardCount(playerA, "Lightning Bolt", 0);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package org.mage.test.cards.copy;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public class ReversalOfFortuneTest extends CardTestPlayerBase {
|
||||
|
||||
|
||||
/**
|
||||
* Reversal of Fortune
|
||||
* Sorcery, 4RR (6)
|
||||
* Target opponent reveals his or her hand. You may copy an instant or sorcery
|
||||
* card in it. If you do, you may cast the copy without paying its mana cost.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCopyCard() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6);
|
||||
addCard(Zone.HAND, playerA, "Reversal of Fortune");
|
||||
addCard(Zone.HAND, playerB, "Lightning Bolt");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reversal of Fortune", playerB);
|
||||
addTarget(playerA, "Lightning Bolt");
|
||||
setChoice(playerA, "Yes");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Reversal of Fortune", 1);
|
||||
assertGraveyardCount(playerA, "Lightning Bolt", 0);
|
||||
assertGraveyardCount(playerB, "Lightning Bolt", 0);
|
||||
assertLife(playerB, 17);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCopyCardButDontCast() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6);
|
||||
addCard(Zone.HAND, playerA, "Reversal of Fortune");
|
||||
addCard(Zone.HAND, playerB, "Lightning Bolt");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Reversal of Fortune", playerB);
|
||||
addTarget(playerA, "Lightning Bolt");
|
||||
setChoice(playerA, "No");
|
||||
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
|
||||
assertGraveyardCount(playerA, "Reversal of Fortune", 1);
|
||||
assertGraveyardCount(playerA, "Lightning Bolt", 0);
|
||||
assertGraveyardCount(playerB, "Lightning Bolt", 0);
|
||||
assertLife(playerB, 20);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification, are
|
||||
* permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
* conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||
* provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* The views and conclusions contained in the software and documentation are those of the
|
||||
* authors and should not be interpreted as representing official policies, either expressed
|
||||
* or implied, of BetaSteward_at_googlemail.com.
|
||||
*/
|
||||
|
||||
package org.mage.test.cards.copy;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author BetaSteward
|
||||
*/
|
||||
public class SpelltwineTest extends CardTestPlayerBase {
|
||||
|
||||
|
||||
/**
|
||||
* Spelltwine
|
||||
* Sorcery, 5U (6)
|
||||
* Exile target instant or sorcery card from your graveyard and target instant
|
||||
* or sorcery card from an opponent's graveyard. Copy those cards. Cast the
|
||||
* copies if able without paying their mana costs. Exile Spelltwine.
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
public void testCopyCards() {
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Island", 6);
|
||||
addCard(Zone.HAND, playerA, "Spelltwine");
|
||||
addCard(Zone.GRAVEYARD, playerA, "Lightning Bolt");
|
||||
addCard(Zone.GRAVEYARD, playerB, "Shock");
|
||||
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Spelltwine");
|
||||
addTarget(playerA, "Lightning Bolt");
|
||||
addTarget(playerA, "Shock");
|
||||
|
||||
setStopAt(1, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
assertExileCount("Spelltwine", 1);
|
||||
assertExileCount("Lightning Bolt", 1);
|
||||
assertExileCount("Shock", 1);
|
||||
assertLife(playerB, 15);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -80,7 +80,6 @@ public interface Game extends MageItem, Serializable {
|
|||
|
||||
//game data methods
|
||||
void loadCards(Set<Card> cards, UUID ownerId);
|
||||
void unloadCard(Card card);
|
||||
Collection<Card> getCards();
|
||||
Object getCustomData();
|
||||
void setCustomData(Object data);
|
||||
|
|
|
@ -220,10 +220,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
this.freeMulligans = game.freeMulligans;
|
||||
this.attackOption = game.attackOption;
|
||||
this.state = game.state.copy();
|
||||
// Ai simulation modifies e.g. zoneChangeCounter so copy is needed if AI active
|
||||
for (Map.Entry<UUID, Card> entry: game.gameCards.entrySet()) {
|
||||
this.gameCards.put(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
this.gameCards = game.gameCards;
|
||||
this.simulation = game.simulation;
|
||||
this.gameOptions = game.gameOptions;
|
||||
this.lki.putAll(game.lki);
|
||||
|
@ -294,20 +291,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unloadCard(Card card) {
|
||||
gameCards.remove(card.getId());
|
||||
state.removeCard(card);
|
||||
if (card.isSplitCard()) {
|
||||
Card leftCard = ((SplitCard)card).getLeftHalfCard();
|
||||
gameCards.remove(leftCard.getId());
|
||||
state.removeCard(leftCard);
|
||||
Card rightCard = ((SplitCard)card).getRightHalfCard();
|
||||
gameCards.remove(rightCard.getId());
|
||||
state.removeCard(rightCard);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Card> getCards() {
|
||||
return gameCards.values();
|
||||
|
@ -428,7 +411,11 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
if (cardId == null) {
|
||||
return null;
|
||||
}
|
||||
return gameCards.get(cardId);
|
||||
Card card = gameCards.get(cardId);
|
||||
if (card == null) {
|
||||
return state.getCopiedCard(cardId);
|
||||
}
|
||||
return card;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1328,14 +1315,7 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
|
||||
@Override
|
||||
public Card copyCard(Card cardToCopy, Ability source, UUID newController) {
|
||||
Card copiedCard = cardToCopy.copy();
|
||||
copiedCard.assignNewId();
|
||||
copiedCard.setCopy(true);
|
||||
Set<Card> cards = new HashSet<>();
|
||||
cards.add(copiedCard);
|
||||
loadCards(cards, source.getControllerId());
|
||||
|
||||
return copiedCard;
|
||||
return state.copyCard(cardToCopy, source, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1437,30 +1417,13 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
}
|
||||
}
|
||||
|
||||
// 704.5e
|
||||
for (Player player: getPlayers().values()) {
|
||||
for (Card card: player.getHand().getCards(this)) {
|
||||
if (card.isCopy()) {
|
||||
player.getHand().remove(card);
|
||||
this.unloadCard(card);
|
||||
}
|
||||
}
|
||||
for (Card card: player.getGraveyard().getCards(this)) {
|
||||
if (card.isCopy()) {
|
||||
player.getGraveyard().remove(card);
|
||||
this.unloadCard(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 704.5e 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.
|
||||
// (Isochron Scepter) 12/1/2004: If you don't want to cast the copy, you can choose not to; the copy ceases to exist the next time state-based actions are checked.
|
||||
for (Card card: this.getState().getExile().getAllCards(this)) {
|
||||
if (card.isCopy()) {
|
||||
this.getState().getExile().removeCard(card, this);
|
||||
this.unloadCard(card);
|
||||
for (Card card: this.getState().getCopiedCards()) {
|
||||
Zone zone = state.getZone(card.getId());
|
||||
if (zone != Zone.BATTLEFIELD && zone != Zone.STACK)
|
||||
state.removeCopiedCard(card);
|
||||
}
|
||||
}
|
||||
// TODO Library + graveyard
|
||||
|
||||
|
||||
List<Permanent> planeswalkers = new ArrayList<>();
|
||||
List<Permanent> legendary = new ArrayList<>();
|
||||
|
@ -2277,14 +2240,11 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
switch (command.getKey()) {
|
||||
case HAND:
|
||||
if (command.getValue().equals("clear")) {
|
||||
removeCards(player.getHand());
|
||||
player.getHand().clear();
|
||||
}
|
||||
break;
|
||||
case LIBRARY:
|
||||
if (command.getValue().equals("clear")) {
|
||||
for (UUID card : player.getLibrary().getCardList()) {
|
||||
removeCard(card);
|
||||
}
|
||||
player.getLibrary().clear();
|
||||
}
|
||||
break;
|
||||
|
@ -2315,22 +2275,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
return lki;
|
||||
}
|
||||
|
||||
private void removeCards(Cards cards) {
|
||||
for (UUID card : cards) {
|
||||
removeCard(card);
|
||||
}
|
||||
cards.clear();
|
||||
}
|
||||
|
||||
private void removeCard(UUID cardId) {
|
||||
Card card = this.getCard(cardId);
|
||||
if(card != null && card.isSplitCard()) {
|
||||
gameCards.remove(((SplitCard)card).getLeftHalfCard().getId());
|
||||
gameCards.remove(((SplitCard)card).getRightHalfCard().getId());
|
||||
}
|
||||
gameCards.remove(cardId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cheat(UUID ownerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard) {
|
||||
Player player = getPlayer(ownerId);
|
||||
|
@ -2374,25 +2318,6 @@ public abstract class GameImpl implements Game, Serializable {
|
|||
loadCards(set, ownerId);
|
||||
}
|
||||
|
||||
public void replaceLibrary(List<Card> cardsDownToTop, UUID ownerId) {
|
||||
Player player = getPlayer(ownerId);
|
||||
if (player != null) {
|
||||
for (UUID card : player.getLibrary().getCardList()) {
|
||||
removeCard(card);
|
||||
}
|
||||
player.getLibrary().clear();
|
||||
Set<Card> cards = new HashSet<>();
|
||||
for (Card card : cardsDownToTop) {
|
||||
cards.add(card);
|
||||
}
|
||||
loadCards(cards, ownerId);
|
||||
|
||||
for (Card card : cards) {
|
||||
player.getLibrary().putOnTop(card, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean endTurn() {
|
||||
getTurn().endTurn(this, getActivePlayerId());
|
||||
|
|
|
@ -105,6 +105,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
private List<GameEvent> simultaneousEvents = new ArrayList<>();
|
||||
private Map<UUID, CardState> cardState = new HashMap<>();
|
||||
private Map<UUID, Integer> zoneChangeCounter = new HashMap<>();
|
||||
private Map<UUID, Card> copiedCards = new HashMap<>();
|
||||
|
||||
public GameState() {
|
||||
players = new Players();
|
||||
|
@ -161,6 +162,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
cardState.put(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
this.zoneChangeCounter.putAll(state.zoneChangeCounter);
|
||||
this.copiedCards.putAll(state.copiedCards);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -499,6 +501,7 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
this.simultaneousEvents = state.simultaneousEvents;
|
||||
this.cardState = state.cardState;
|
||||
this.zoneChangeCounter = state.zoneChangeCounter;
|
||||
this.copiedCards = state.copiedCards;
|
||||
}
|
||||
|
||||
public void addSimultaneousEvent(GameEvent event, Game game) {
|
||||
|
@ -540,13 +543,18 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
}
|
||||
}
|
||||
|
||||
public void removeCard(Card card) {
|
||||
public void removeCopiedCard(Card card) {
|
||||
if (copiedCards.containsKey(card.getId())) {
|
||||
copiedCards.remove(card.getId());
|
||||
cardState.remove(card.getId());
|
||||
zones.remove(card.getId());
|
||||
zoneChangeCounter.remove(card.getId());
|
||||
}
|
||||
// TODO Watchers?
|
||||
// TODO Abilities?
|
||||
if (card.isSplitCard()) {
|
||||
removeCard( ((SplitCard)card).getLeftHalfCard());
|
||||
removeCard( ((SplitCard)card).getRightHalfCard());
|
||||
removeCopiedCard( ((SplitCard)card).getLeftHalfCard());
|
||||
removeCopiedCard( ((SplitCard)card).getRightHalfCard());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -819,4 +827,29 @@ public class GameState implements Serializable, Copyable<GameState> {
|
|||
this.zoneChangeCounter.put(objectId, value);
|
||||
}
|
||||
|
||||
public Card getCopiedCard(UUID cardId) {
|
||||
return copiedCards.get(cardId);
|
||||
}
|
||||
|
||||
public Collection<Card> getCopiedCards() {
|
||||
return copiedCards.values();
|
||||
}
|
||||
|
||||
public Card copyCard(Card cardToCopy, Ability source, Game game) {
|
||||
Card copiedCard = cardToCopy.copy();
|
||||
copiedCard.assignNewId();
|
||||
copiedCard.setOwnerId(source.getControllerId());
|
||||
copiedCard.setCopy(true);
|
||||
copiedCards.put(copiedCard.getId(), copiedCard);
|
||||
addCard(copiedCard);
|
||||
if (copiedCard.isSplitCard()) {
|
||||
Card leftCard = ((SplitCard)copiedCard).getLeftHalfCard();
|
||||
copiedCards.put(leftCard.getId(), leftCard);
|
||||
addCard(leftCard);
|
||||
Card rightCard = ((SplitCard)copiedCard).getRightHalfCard();
|
||||
copiedCards.put(rightCard.getId(), rightCard);
|
||||
addCard(rightCard);
|
||||
}
|
||||
return copiedCard;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue