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:
elcnesh
2015-04-02 14:35:42 +00:00
parent b7a47736bf
commit dc4559c577
10 changed files with 67 additions and 35 deletions

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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()) {

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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"; }
};
}

View File

@@ -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);

View File

@@ -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;
}
}
});

View File

@@ -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";

View File

@@ -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;
}