mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Attempt to combat game memory leaks after game finishes.
- Make PLAY_LAND_SURROGATE a game field rather than static - Remove games from cache more aggressively - Remove targeting overlay from global view after game ends
This commit is contained in:
@@ -1097,9 +1097,9 @@ public class AiController {
|
||||
if (landsWannaPlay != null && !landsWannaPlay.isEmpty() && player.canPlayLand(null)) {
|
||||
Card land = chooseBestLandToPlay(landsWannaPlay);
|
||||
if (ComputerUtil.damageFromETB(player, land) < player.getLife() || !player.canLoseLife()) {
|
||||
Ability.PLAY_LAND_SURROGATE.setHostCard(land);
|
||||
game.PLAY_LAND_SURROGATE.setHostCard(land);
|
||||
final List<SpellAbility> abilities = new ArrayList<SpellAbility>();
|
||||
abilities.add(Ability.PLAY_LAND_SURROGATE);
|
||||
abilities.add(game.PLAY_LAND_SURROGATE);
|
||||
return abilities;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,10 +397,9 @@ public class PlayerControllerAi extends PlayerController {
|
||||
@Override
|
||||
public void playChosenSpellAbility(SpellAbility sa) {
|
||||
// System.out.println("Playing sa: " + sa);
|
||||
if (sa == Ability.PLAY_LAND_SURROGATE) {
|
||||
if (sa == sa.getHostCard().getGame().PLAY_LAND_SURROGATE) {
|
||||
player.playLand(sa.getHostCard(), false);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
ComputerUtil.handlePlayingSpellAbility(player, sa, game);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ import forge.game.GameObject;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.Ability;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetChoices;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
@@ -152,7 +151,7 @@ public class GameSimulator {
|
||||
}
|
||||
}
|
||||
|
||||
if (sa == Ability.PLAY_LAND_SURROGATE) {
|
||||
if (sa == origSa.getHostCard().getGame().PLAY_LAND_SURROGATE) {
|
||||
aiPlayer.playLand(sa.getHostCard(), false);
|
||||
} else {
|
||||
if (debugPrint && !sa.getAllTargetChoices().isEmpty()) {
|
||||
|
||||
@@ -44,6 +44,7 @@ import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.event.Event;
|
||||
import forge.game.event.GameEventGameOutcome;
|
||||
import forge.game.phase.Phase;
|
||||
@@ -107,6 +108,19 @@ public class Game {
|
||||
private final GameView view;
|
||||
private final Tracker tracker = new Tracker();
|
||||
|
||||
public final Ability PLAY_LAND_SURROGATE = new Ability(null, (Cost) null) {
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
return true; //if this ability is added anywhere, it can be assumed that land can be played
|
||||
}
|
||||
@Override
|
||||
public void resolve() {
|
||||
throw new RuntimeException("This ability is intended to indicate \"land to play\" choice only");
|
||||
}
|
||||
@Override
|
||||
public String toUnsuppressedString() { return "Play land"; }
|
||||
};
|
||||
|
||||
private final GameEntityCache<Player, PlayerView> playerCache = new GameEntityCache<>();
|
||||
public Player getPlayer(PlayerView playerView) {
|
||||
return playerCache.get(playerView);
|
||||
@@ -140,7 +154,7 @@ public class Game {
|
||||
rules = rules0;
|
||||
match = match0;
|
||||
|
||||
spabCache.put(Ability.PLAY_LAND_SURROGATE.getId(), Ability.PLAY_LAND_SURROGATE);
|
||||
spabCache.put(PLAY_LAND_SURROGATE.getId(), PLAY_LAND_SURROGATE);
|
||||
|
||||
int highestTeam = -1;
|
||||
for (RegisteredPlayer psc : players0) {
|
||||
|
||||
@@ -6427,8 +6427,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
}
|
||||
|
||||
if (getState(CardStateName.Original).getType().isLand() && player.canPlayLand(this)) {
|
||||
Ability.PLAY_LAND_SURROGATE.setHostCard(this);
|
||||
abilities.add(Ability.PLAY_LAND_SURROGATE);
|
||||
game.PLAY_LAND_SURROGATE.setHostCard(this);
|
||||
abilities.add(game.PLAY_LAND_SURROGATE);
|
||||
}
|
||||
|
||||
return abilities;
|
||||
|
||||
@@ -76,16 +76,4 @@ public abstract class Ability extends SpellAbility {
|
||||
return this.getHostCard().isInPlay() && !this.getHostCard().isFaceDown();
|
||||
}
|
||||
|
||||
public static final Ability PLAY_LAND_SURROGATE = new Ability(null, (Cost) null) {
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
return true; //if this ability is added anywhere, it can be assumed that land can be played
|
||||
}
|
||||
@Override
|
||||
public void resolve() {
|
||||
throw new RuntimeException("This ability is intended to indicate \"land to play\" choice only");
|
||||
}
|
||||
@Override
|
||||
public String toUnsuppressedString() { return "Play land"; }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -813,6 +813,7 @@ public final class CMatchUI
|
||||
|
||||
@Override
|
||||
public void afterGameEnd() {
|
||||
Singletons.getView().getLpnDocument().remove(targetingOverlay.getPanel());
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public void run() {
|
||||
Singletons.getView().getNavigationBar().closeTab(screen);
|
||||
|
||||
@@ -215,7 +215,7 @@ public class HostedMatch {
|
||||
// It's important to run match in a different thread to allow GUI inputs to be invoked from inside game.
|
||||
// Game is set on pause while gui player takes decisions
|
||||
game.getAction().invoke(new Runnable() {
|
||||
@Override public void run() {
|
||||
@Override public final void run() {
|
||||
if (humanCount == 0) {
|
||||
// Create FControlGamePlayback in game thread to allow pausing
|
||||
playbackControl = new FControlGamePlayback(humanControllers.get(0));
|
||||
@@ -235,6 +235,9 @@ public class HostedMatch {
|
||||
addNextGameDecision(null, NextGameDecision.CONTINUE);
|
||||
}
|
||||
}
|
||||
if (match.isMatchOver()) {
|
||||
isMatchOver = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ import java.util.List;
|
||||
import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.Ability;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.model.FModel;
|
||||
import forge.player.GamePlayerUtil;
|
||||
@@ -161,7 +160,7 @@ public class InputPassPriority extends InputSyncronizedBase {
|
||||
if (sa.isSpell()) {
|
||||
return "cast spell";
|
||||
}
|
||||
if (sa == Ability.PLAY_LAND_SURROGATE) {
|
||||
if (sa == card.getGame().PLAY_LAND_SURROGATE) {
|
||||
return "play land";
|
||||
}
|
||||
return "activate ability";
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
package forge.player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
@@ -12,14 +18,43 @@ import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.ApiType;
|
||||
import forge.game.ability.effects.CharmEffect;
|
||||
import forge.game.ability.effects.FlipCoinEffect;
|
||||
import forge.game.card.*;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardFactoryUtil;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardPredicates;
|
||||
import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.cost.*;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.cost.Cost;
|
||||
import forge.game.cost.CostAddMana;
|
||||
import forge.game.cost.CostDamage;
|
||||
import forge.game.cost.CostDiscard;
|
||||
import forge.game.cost.CostDraw;
|
||||
import forge.game.cost.CostExile;
|
||||
import forge.game.cost.CostFlipCoin;
|
||||
import forge.game.cost.CostGainControl;
|
||||
import forge.game.cost.CostGainLife;
|
||||
import forge.game.cost.CostMill;
|
||||
import forge.game.cost.CostPart;
|
||||
import forge.game.cost.CostPartMana;
|
||||
import forge.game.cost.CostPartWithList;
|
||||
import forge.game.cost.CostPayLife;
|
||||
import forge.game.cost.CostPayment;
|
||||
import forge.game.cost.CostPutCardToLib;
|
||||
import forge.game.cost.CostPutCounter;
|
||||
import forge.game.cost.CostRemoveAnyCounter;
|
||||
import forge.game.cost.CostRemoveCounter;
|
||||
import forge.game.cost.CostReturn;
|
||||
import forge.game.cost.CostReveal;
|
||||
import forge.game.cost.CostSacrifice;
|
||||
import forge.game.cost.CostTapType;
|
||||
import forge.game.cost.PaymentDecision;
|
||||
import forge.game.mana.ManaCostAdjustment;
|
||||
import forge.game.mana.ManaCostBeingPaid;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.spellability.Ability;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -31,12 +66,6 @@ import forge.util.FCollectionView;
|
||||
import forge.util.Lang;
|
||||
import forge.util.gui.SGuiChoose;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class HumanPlay {
|
||||
|
||||
@@ -54,7 +83,7 @@ public class HumanPlay {
|
||||
public final static void playSpellAbility(final PlayerControllerHuman controller, final Player p, SpellAbility sa) {
|
||||
FThreads.assertExecutedByEdt(false);
|
||||
|
||||
if (sa == Ability.PLAY_LAND_SURROGATE) {
|
||||
if (sa == controller.getGame().PLAY_LAND_SURROGATE) {
|
||||
p.playLand(sa.getHostCard(), false);
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user