Fixed different ZCC in split card's parts (flashback fix, see 95075cf33e);

Improve moveToZone code and fixed some cards with wrong commands queue (e.g. directly removes card from zone and then calls moveToZone again);
This commit is contained in:
Oleg Agafonov 2020-06-04 23:47:50 +04:00
parent f010454cb2
commit e95ae2675b
21 changed files with 116 additions and 36 deletions

View file

@ -54,7 +54,6 @@ public class PutOnLibrarySourceEffect extends OneShotEffect {
} else if (sourceObject instanceof Card && game.getState().getZone(source.getSourceId()) == Zone.GRAVEYARD) {
for (Player player : game.getPlayers().values()) {
if (player.getGraveyard().contains(sourceObject.getId())) {
player.getGraveyard().remove(((Card) sourceObject));
((Card) sourceObject).moveToZone(Zone.LIBRARY, source.getSourceId(), game, onTop);
return true;
}

View file

@ -1,7 +1,5 @@
package mage.cards;
import java.util.List;
import java.util.UUID;
import mage.abilities.Abilities;
import mage.abilities.AbilitiesImpl;
import mage.abilities.Ability;
@ -9,6 +7,10 @@ import mage.abilities.SpellAbility;
import mage.constants.CardType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.ZoneChangeEvent;
import java.util.List;
import java.util.UUID;
/**
* @author TheElk801
@ -64,6 +66,22 @@ public abstract class AdventureCard extends CardImpl {
return false;
}
@Override
public boolean removeFromZone(Game game, Zone fromZone, UUID sourceId) {
// zone contains only one main card
return super.removeFromZone(game, fromZone, sourceId);
}
@Override
public void updateZoneChangeCounter(Game game, ZoneChangeEvent event) {
if (isCopy()) { // same as meld cards
super.updateZoneChangeCounter(game, event);
return;
}
super.updateZoneChangeCounter(game, event);
getSpellCard().updateZoneChangeCounter(game, event);
}
@Override
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
switch (ability.getSpellAbilityType()) {

View file

@ -523,7 +523,6 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
case EXILED:
if (game.getExile().getCard(getId(), game) != null) {
removed = game.getExile().removeCard(this, game);
}
break;
case STACK:
@ -533,15 +532,18 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
} else {
stackObject = game.getStack().getSpell(this.getId(), false);
}
if (stackObject == null && (this instanceof SplitCard)) { // handle if half of Split cast is on the stack
stackObject = game.getStack().getSpell(((SplitCard) this).getLeftHalfCard().getId(), false);
if (stackObject == null) {
stackObject = game.getStack().getSpell(((SplitCard) this).getRightHalfCard().getId(), false);
}
}
if (stackObject == null && (this instanceof AdventureCard)) {
stackObject = game.getStack().getSpell(((AdventureCard) this).getSpellCard().getId(), false);
}
if (stackObject == null) {
stackObject = game.getStack().getSpell(getId(), false);
}
@ -589,6 +591,8 @@ public abstract class CardImpl extends MageObjectImpl implements Card {
}
} else {
logger.warn("Couldn't find card in fromZone, card=" + getIdName() + ", fromZone=" + fromZone);
// possible reason: you to remove card from wrong zone or card already removed,
// e.g. you added copy card to wrong graveyard (see owner) or removed card from graveyard before moveToZone call
}
return removed;
}

View file

@ -15,7 +15,7 @@ public interface Cards extends Set<UUID>, Serializable {
Card get(UUID cardId, Game game);
void remove(Card card);
boolean remove(Card card);
void setOwner(UUID ownerId, Game game);

View file

@ -64,11 +64,11 @@ public class CardsImpl extends LinkedHashSet<UUID> implements Cards, Serializabl
}
@Override
public void remove(Card card) {
public boolean remove(Card card) {
if (card == null) {
return;
return false;
}
this.remove(card.getId());
return this.remove(card.getId());
}
@Override

View file

@ -1,4 +1,3 @@
package mage.cards;
import mage.abilities.Ability;
@ -13,7 +12,6 @@ import java.util.List;
import java.util.UUID;
/**
*
* @author emerald000
*/
public abstract class MeldCard extends CardImpl {
@ -142,6 +140,24 @@ public abstract class MeldCard extends CardImpl {
return value;
}
@Override
public boolean moveToZone(Zone toZone, UUID sourceId, Game game, boolean flag, List<UUID> appliedEffects) {
// TODO: missing override method for meld cards? See removeFromZone, updateZoneChangeCounter, etc
return super.moveToZone(toZone, sourceId, game, flag, appliedEffects);
}
@Override
public void setZone(Zone zone, Game game) {
// TODO: missing override method for meld cards? See removeFromZone, updateZoneChangeCounter, etc
super.setZone(zone, game);
}
@Override
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
// TODO: missing override method for meld cards? See removeFromZone, updateZoneChangeCounter, etc
return super.moveToExile(exileId, name, sourceId, game, appliedEffects);
}
@Override
public boolean removeFromZone(Game game, Zone fromZone, UUID sourceId) {
if (isCopy()) {
@ -170,7 +186,7 @@ public abstract class MeldCard extends CardImpl {
super.updateZoneChangeCounter(game, event);
return;
}
game.getState().updateZoneChangeCounter(objectId);
super.updateZoneChangeCounter(game, event);
if (topLastZoneChangeCounter == topHalfCard.getZoneChangeCounter(game)
&& halves.contains(topHalfCard.getId())) {
topHalfCard.updateZoneChangeCounter(game, event);

View file

@ -9,6 +9,7 @@ import mage.constants.CardType;
import mage.constants.SpellAbilityType;
import mage.constants.Zone;
import mage.game.Game;
import mage.game.events.ZoneChangeEvent;
import java.util.ArrayList;
import java.util.List;
@ -74,6 +75,13 @@ public abstract class SplitCard extends CardImpl {
return false;
}
@Override
public void setZone(Zone zone, Game game) {
super.setZone(zone, game);
game.setZone(getLeftHalfCard().getId(), zone);
game.setZone(getRightHalfCard().getId(), zone);
}
@Override
public boolean moveToExile(UUID exileId, String name, UUID sourceId, Game game, List<UUID> appliedEffects) {
if (super.moveToExile(exileId, name, sourceId, game, appliedEffects)) {
@ -85,6 +93,23 @@ public abstract class SplitCard extends CardImpl {
return false;
}
@Override
public boolean removeFromZone(Game game, Zone fromZone, UUID sourceId) {
// zone contains only one main card
return super.removeFromZone(game, fromZone, sourceId);
}
@Override
public void updateZoneChangeCounter(Game game, ZoneChangeEvent event) {
if (isCopy()) { // same as meld cards
super.updateZoneChangeCounter(game, event);
return;
}
super.updateZoneChangeCounter(game, event);
getLeftHalfCard().updateZoneChangeCounter(game, event);
getRightHalfCard().updateZoneChangeCounter(game, event);
}
@Override
public boolean cast(Game game, Zone fromZone, SpellAbility ability, UUID controllerId) {
switch (ability.getSpellAbilityType()) {
@ -99,13 +124,6 @@ public abstract class SplitCard extends CardImpl {
}
}
@Override
public void setZone(Zone zone, Game game) {
super.setZone(zone, game);
game.setZone(getLeftHalfCard().getId(), zone);
game.setZone(getRightHalfCard().getId(), zone);
}
@Override
public Abilities<Ability> getAbilities() {
Abilities<Ability> allAbilites = new AbilitiesImpl<>();
@ -168,7 +186,5 @@ public abstract class SplitCard extends CardImpl {
leftHalfCard.setOwnerId(ownerId);
rightHalfCard.getAbilities().setControllerId(ownerId);
rightHalfCard.setOwnerId(ownerId);
}
}

View file

@ -691,6 +691,8 @@ public abstract class PlayerImpl implements Player, Serializable {
return false;
}
library.remove(card.getId(), game);
// must return true all the time (some cards can be removed directly from library, see getLibrary().removeFromTop)
// TODO: replace removeFromTop logic to normal with moveToZone
return true;
}
@ -919,8 +921,7 @@ public abstract class PlayerImpl implements Player, Serializable {
@Override
public boolean removeFromGraveyard(Card card, Game game) {
this.graveyard.remove(card);
return true;
return this.graveyard.remove(card);
}
@Override