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
|
|
@ -1,11 +1,9 @@
|
|||
package mage.watchers;
|
||||
|
||||
import mage.cards.Cards;
|
||||
import mage.constants.WatcherScope;
|
||||
import mage.game.Game;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.players.PlayerList;
|
||||
import mage.util.Copyable;
|
||||
import mage.util.CardUtil;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
|
@ -114,96 +112,7 @@ public abstract class Watcher implements Serializable {
|
|||
for (Field field : allFields) {
|
||||
if (!Modifier.isStatic(field.getModifiers())) {
|
||||
field.setAccessible(true);
|
||||
|
||||
if (field.getType() == Set.class) {
|
||||
// Set<UUID, xxx>
|
||||
((Set) field.get(watcher)).clear();
|
||||
((Set) field.get(watcher)).addAll((Set) field.get(this));
|
||||
} else if (field.getType() == Map.class || field.getType() == HashMap.class) {
|
||||
// Map<UUID, xxx>
|
||||
ParameterizedType parameterizedType = (ParameterizedType) field.getGenericType();
|
||||
Type valueType = parameterizedType.getActualTypeArguments()[1];
|
||||
if (valueType.getTypeName().contains("SortedSet")) {
|
||||
// Map<UUID, SortedSet<Object>>
|
||||
Map<Object, Set<Object>> source = (Map<Object, Set<Object>>) field.get(this);
|
||||
Map<Object, Set<Object>> target = (Map<Object, Set<Object>>) field.get(watcher);
|
||||
target.clear();
|
||||
for (Map.Entry<Object, Set<Object>> e : source.entrySet()) {
|
||||
Set<Object> set = new TreeSet<>();
|
||||
set.addAll(e.getValue());
|
||||
target.put(e.getKey(), set);
|
||||
}
|
||||
} else if (valueType.getTypeName().contains("Set")) {
|
||||
// Map<UUID, Set<Object>>
|
||||
Map<Object, Set<Object>> source = (Map<Object, Set<Object>>) field.get(this);
|
||||
Map<Object, Set<Object>> target = (Map<Object, Set<Object>>) field.get(watcher);
|
||||
target.clear();
|
||||
for (Map.Entry<Object, Set<Object>> e : source.entrySet()) {
|
||||
Set<Object> set = new HashSet<>();
|
||||
set.addAll(e.getValue());
|
||||
target.put(e.getKey(), set);
|
||||
}
|
||||
} else if (valueType.getTypeName().contains("PlayerList")) {
|
||||
// Map<UUID, PlayerList>
|
||||
Map<Object, PlayerList> source = (Map<Object, PlayerList>) field.get(this);
|
||||
Map<Object, PlayerList> target = (Map<Object, PlayerList>) field.get(watcher);
|
||||
target.clear();
|
||||
for (Map.Entry<Object, PlayerList> e : source.entrySet()) {
|
||||
PlayerList list = e.getValue().copy();
|
||||
target.put(e.getKey(), list);
|
||||
}
|
||||
} else if (valueType.getTypeName().endsWith("Cards")) {
|
||||
// Map<UUID, Cards>
|
||||
Map<Object, Cards> source = (Map<Object, Cards>) field.get(this);
|
||||
Map<Object, Cards> target = (Map<Object, Cards>) field.get(watcher);
|
||||
target.clear();
|
||||
for (Map.Entry<Object, Cards> e : source.entrySet()) {
|
||||
Cards list = e.getValue().copy();
|
||||
target.put(e.getKey(), list);
|
||||
}
|
||||
} else if (valueType instanceof Class && Arrays.stream(((Class) valueType).getInterfaces()).anyMatch(c -> c.equals(Copyable.class))) {
|
||||
// Map<UUID, Copyable>
|
||||
Map<Object, Copyable> source = (Map<Object, Copyable>) field.get(this);
|
||||
Map<Object, Copyable> target = (Map<Object, Copyable>) field.get(watcher);
|
||||
target.clear();
|
||||
for (Map.Entry<Object, Copyable> e : source.entrySet()) {
|
||||
Copyable object = (Copyable) e.getValue().copy();
|
||||
target.put(e.getKey(), object);
|
||||
}
|
||||
} else if (valueType.getTypeName().contains("List")) {
|
||||
// Map<UUID, List<Object>>
|
||||
Map<Object, List<Object>> source = (Map<Object, List<Object>>) field.get(this);
|
||||
Map<Object, List<Object>> target = (Map<Object, List<Object>>) field.get(watcher);
|
||||
target.clear();
|
||||
for (Map.Entry<Object, List<Object>> e : source.entrySet()) {
|
||||
List<Object> list = new ArrayList<>();
|
||||
list.addAll(e.getValue());
|
||||
target.put(e.getKey(), list);
|
||||
}
|
||||
} else if (valueType.getTypeName().contains("Map")) {
|
||||
// Map<UUID, Map<UUID, Object>>
|
||||
Map<Object, Map<Object, Object>> source = (Map<Object, Map<Object, Object>>) field.get(this);
|
||||
Map<Object, Map<Object, Object>> target = (Map<Object, Map<Object, Object>>) field.get(watcher);
|
||||
target.clear();
|
||||
for (Map.Entry<Object, Map<Object, Object>> e : source.entrySet()) {
|
||||
Map<Object, Object> map = new HashMap<>();
|
||||
map.putAll(e.getValue());
|
||||
target.put(e.getKey(), map);
|
||||
}
|
||||
} else {
|
||||
// Map<UUID, Object>
|
||||
// TODO: add additional tests to find unsupported watcher data
|
||||
|
||||
((Map) field.get(watcher)).putAll((Map) field.get(this));
|
||||
}
|
||||
} else if (field.getType() == List.class) {
|
||||
// List<Object>
|
||||
((List) field.get(watcher)).clear();
|
||||
((List) field.get(watcher)).addAll((List) field.get(this));
|
||||
} else {
|
||||
// Object
|
||||
field.set(watcher, field.get(this));
|
||||
}
|
||||
field.set(watcher, CardUtil.deepCopyObject(field.get(this)));
|
||||
}
|
||||
}
|
||||
return watcher;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue