mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Prevent concurrent modification exception when moving token to a zone besides the graveyard
This commit is contained in:
@@ -251,4 +251,10 @@ public class FCollection<T> implements List<T>, Set<T>, FCollectionView<T>, Clon
|
|||||||
}
|
}
|
||||||
return subList;
|
return subList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<T> threadSafeIterator() {
|
||||||
|
//create a new linked list for iterating to make it thread safe and avoid concurrent modification exceptions
|
||||||
|
return new LinkedList<T>(list);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,5 @@ public interface FCollectionView<T> extends Iterable<T> {
|
|||||||
int lastIndexOf(Object o);
|
int lastIndexOf(Object o);
|
||||||
boolean contains(Object o);
|
boolean contains(Object o);
|
||||||
List<T> subList(int fromIndex, int toIndex);
|
List<T> subList(int fromIndex, int toIndex);
|
||||||
|
Iterable<T> threadSafeIterator();
|
||||||
}
|
}
|
||||||
@@ -675,23 +675,32 @@ public class GameAction {
|
|||||||
if (zt == ZoneType.Battlefield) {
|
if (zt == ZoneType.Battlefield) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (Card c : p.getCardsIn(zt)) {
|
Iterable<Card> cards = p.getCardsIn(zt).threadSafeIterator();
|
||||||
|
for (Card c : cards) {
|
||||||
// If a token is in a zone other than the battlefield, it ceases to exist.
|
// If a token is in a zone other than the battlefield, it ceases to exist.
|
||||||
checkAgain |= stateBasedAction704_5d(c);
|
checkAgain |= stateBasedAction704_5d(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<Card> noRegCreats = new ArrayList<Card>();
|
Iterable<Card> cards = game.getCardsIn(ZoneType.Battlefield).threadSafeIterator();
|
||||||
List<Card> desCreats = new ArrayList<Card>();
|
List<Card> noRegCreats = null;
|
||||||
for (Card c : game.getCardsIn(ZoneType.Battlefield)) {
|
List<Card> desCreats = null;
|
||||||
|
for (Card c : cards) {
|
||||||
if (c.isCreature()) {
|
if (c.isCreature()) {
|
||||||
// Rule 704.5f - Put into grave (no regeneration) for toughness <= 0
|
// Rule 704.5f - Put into grave (no regeneration) for toughness <= 0
|
||||||
if (c.getNetToughness() <= 0) {
|
if (c.getNetToughness() <= 0) {
|
||||||
|
if (noRegCreats == null) {
|
||||||
|
noRegCreats = new LinkedList<Card>();
|
||||||
|
}
|
||||||
noRegCreats.add(c);
|
noRegCreats.add(c);
|
||||||
checkAgain = true;
|
checkAgain = true;
|
||||||
} else if (c.hasKeyword("CARDNAME can't be destroyed by lethal damage unless lethal damage dealt by a single source is marked on it.")) {
|
}
|
||||||
|
else if (c.hasKeyword("CARDNAME can't be destroyed by lethal damage unless lethal damage dealt by a single source is marked on it.")) {
|
||||||
for (final Integer dmg : c.getReceivedDamageFromThisTurn().values()) {
|
for (final Integer dmg : c.getReceivedDamageFromThisTurn().values()) {
|
||||||
if (c.getNetToughness() <= dmg.intValue()) {
|
if (c.getNetToughness() <= dmg.intValue()) {
|
||||||
|
if (desCreats == null) {
|
||||||
|
desCreats = new LinkedList<Card>();
|
||||||
|
}
|
||||||
desCreats.add(c);
|
desCreats.add(c);
|
||||||
checkAgain = true;
|
checkAgain = true;
|
||||||
break;
|
break;
|
||||||
@@ -700,6 +709,9 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
// Rule 704.5g - Destroy due to lethal damage
|
// Rule 704.5g - Destroy due to lethal damage
|
||||||
else if (c.getNetToughness() <= c.getDamage()) {
|
else if (c.getNetToughness() <= c.getDamage()) {
|
||||||
|
if (desCreats == null) {
|
||||||
|
desCreats = new LinkedList<Card>();
|
||||||
|
}
|
||||||
desCreats.add(c);
|
desCreats.add(c);
|
||||||
checkAgain = true;
|
checkAgain = true;
|
||||||
}
|
}
|
||||||
@@ -721,11 +733,15 @@ public class GameAction {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Card c : noRegCreats) {
|
if (noRegCreats != null) {
|
||||||
sacrificeDestroy(c);
|
for (Card c : noRegCreats) {
|
||||||
|
sacrificeDestroy(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (Card c : desCreats) {
|
if (desCreats != null) {
|
||||||
destroy(c, null);
|
for (Card c : desCreats) {
|
||||||
|
destroy(c, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game.getTriggerHandler().runWaitingTriggers()) {
|
if (game.getTriggerHandler().runWaitingTriggers()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user