forked from External/mage
Costs Tag Tracking part 2: Tag system and X values, reworked deep copy code (#11406)
* Implement Costs Tag Map system * Use Costs Tag Map system to store X value for spells, abilities, and resolving permanents * Store Bestow without target's tags Change functions for getting tags and storing the tags of a new permanent * Create and use deep copy function in CardUtil, add Copyable<T> to many classes * Fix Hall Of the Bandit Lord infinite loop * Add additional comments * Don't store null/empty costs tags maps (saves memory) * Fix two more Watchers with Ability variable * Add check for exact collection types during deep copy * Use generics instead of pure type erasure during deep copy * convert more code to using deep copy helper, everything use Object copier, add EnumMap * fix documentation * Don't need the separate null checks anymore (handled in deepCopyObject) * Minor cleanup
This commit is contained in:
parent
72e30f1574
commit
bea33c7493
29 changed files with 458 additions and 338 deletions
|
|
@ -2,6 +2,7 @@ package mage.game;
|
|||
|
||||
import mage.MageException;
|
||||
import mage.MageObject;
|
||||
import mage.MageObjectReference;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.common.AttachableToRestrictedAbility;
|
||||
import mage.abilities.common.CantHaveMoreThanAmountCountersSourceAbility;
|
||||
|
|
@ -184,48 +185,16 @@ public abstract class GameImpl implements Game {
|
|||
//this.tableEventSource = game.tableEventSource; // client-server part, not need on copy/simulations
|
||||
//this.playerQueryEventSource = game.playerQueryEventSource; // client-server part, not need on copy/simulations
|
||||
|
||||
for (Entry<UUID, Card> entry : game.gameCards.entrySet()) {
|
||||
this.gameCards.put(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
for (Entry<UUID, MeldCard> entry : game.meldCards.entrySet()) {
|
||||
this.meldCards.put(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
this.gameCards = CardUtil.deepCopyObject(game.gameCards);
|
||||
this.meldCards = CardUtil.deepCopyObject(game.meldCards);
|
||||
|
||||
// lki
|
||||
for (Entry<Zone, Map<UUID, MageObject>> entry : game.lki.entrySet()) {
|
||||
Map<UUID, MageObject> lkiMap = new HashMap<>();
|
||||
for (Entry<UUID, MageObject> entryMap : entry.getValue().entrySet()) {
|
||||
lkiMap.put(entryMap.getKey(), entryMap.getValue().copy());
|
||||
}
|
||||
this.lki.put(entry.getKey(), lkiMap);
|
||||
}
|
||||
// lkiCardState
|
||||
for (Entry<Zone, Map<UUID, CardState>> entry : game.lkiCardState.entrySet()) {
|
||||
Map<UUID, CardState> lkiMap = new HashMap<>();
|
||||
for (Entry<UUID, CardState> entryMap : entry.getValue().entrySet()) {
|
||||
lkiMap.put(entryMap.getKey(), entryMap.getValue().copy());
|
||||
}
|
||||
this.lkiCardState.put(entry.getKey(), lkiMap);
|
||||
}
|
||||
// lkiExtended
|
||||
for (Entry<UUID, Map<Integer, MageObject>> entry : game.lkiExtended.entrySet()) {
|
||||
Map<Integer, MageObject> lkiMap = new HashMap<>();
|
||||
for (Entry<Integer, MageObject> entryMap : entry.getValue().entrySet()) {
|
||||
lkiMap.put(entryMap.getKey(), entryMap.getValue().copy());
|
||||
}
|
||||
this.lkiExtended.put(entry.getKey(), lkiMap);
|
||||
}
|
||||
// lkiShortLiving
|
||||
for (Entry<Zone, Set<UUID>> entry : game.lkiShortLiving.entrySet()) {
|
||||
this.lkiShortLiving.put(entry.getKey(), new HashSet<>(entry.getValue()));
|
||||
}
|
||||
this.lki = CardUtil.deepCopyObject(game.lki);
|
||||
this.lkiCardState = CardUtil.deepCopyObject(game.lkiCardState);
|
||||
this.lkiExtended = CardUtil.deepCopyObject(game.lkiExtended);
|
||||
this.lkiShortLiving = CardUtil.deepCopyObject(game.lkiShortLiving);
|
||||
|
||||
for (Entry<UUID, Permanent> entry : game.permanentsEntering.entrySet()) {
|
||||
this.permanentsEntering.put(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
for (Entry<UUID, Counters> entry : game.enterWithCounters.entrySet()) {
|
||||
this.enterWithCounters.put(entry.getKey(), entry.getValue().copy());
|
||||
}
|
||||
this.permanentsEntering = CardUtil.deepCopyObject(game.permanentsEntering);
|
||||
this.enterWithCounters = CardUtil.deepCopyObject(game.enterWithCounters);
|
||||
|
||||
this.state = game.state.copy();
|
||||
// client-server part, not need on copy/simulations:
|
||||
|
|
@ -1451,6 +1420,10 @@ public abstract class GameImpl implements Game {
|
|||
player.endOfTurn(this);
|
||||
}
|
||||
state.resetWatchers();
|
||||
// Could be done any time as long as the stack is empty
|
||||
// Tags are stored in the game state as a spell resolves into a permanent
|
||||
// and must be kept while any abilities with that permanent as a source could resolve
|
||||
state.cleanupPermanentCostsTags(this);
|
||||
}
|
||||
|
||||
protected UUID pickChoosingPlayer() {
|
||||
|
|
@ -3560,6 +3533,15 @@ public abstract class GameImpl implements Game {
|
|||
return lki;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<MageObjectReference, Map<String, Object>> getPermanentCostsTags() {
|
||||
return state.getPermanentCostsTags();
|
||||
}
|
||||
@Override
|
||||
public void storePermanentCostsTags(MageObjectReference permanentMOR, Ability source){
|
||||
state.storePermanentCostsTags(permanentMOR, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cheat(UUID ownerId, List<Card> library, List<Card> hand, List<PermanentCard> battlefield, List<Card> graveyard, List<Card> command) {
|
||||
// fake test ability for triggers and events
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue