mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
Prevent crash when starting game without name configured
Avoid unnecessary duplication of event handling when two human players Avoid duplicate copies of views when two human players
This commit is contained in:
@@ -63,10 +63,12 @@ import forge.view.LocalGameView;
|
|||||||
import forge.view.PlayerView;
|
import forge.view.PlayerView;
|
||||||
|
|
||||||
public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
||||||
|
|
||||||
private final LocalGameView gameView;
|
private final LocalGameView gameView;
|
||||||
public FControlGameEventHandler(final LocalGameView gameView0) {
|
private final boolean isMainHandler;
|
||||||
|
|
||||||
|
public FControlGameEventHandler(final LocalGameView gameView0, final boolean isMainHandler0) {
|
||||||
gameView = gameView0;
|
gameView = gameView0;
|
||||||
|
isMainHandler = isMainHandler0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe
|
@Subscribe
|
||||||
@@ -77,7 +79,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
private final AtomicBoolean phaseUpdPlanned = new AtomicBoolean(false);
|
private final AtomicBoolean phaseUpdPlanned = new AtomicBoolean(false);
|
||||||
@Override
|
@Override
|
||||||
public Void visit(final GameEventTurnPhase ev) {
|
public Void visit(final GameEventTurnPhase ev) {
|
||||||
if (phaseUpdPlanned.getAndSet(true)) return null;
|
if (!isMainHandler || phaseUpdPlanned.getAndSet(true)) { return null; }
|
||||||
|
|
||||||
FThreads.invokeInEdtNowOrLater(gameView.getGui(), new Runnable() {
|
FThreads.invokeInEdtNowOrLater(gameView.getGui(), new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
@@ -95,7 +97,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
private final AtomicBoolean combatUpdPlanned = new AtomicBoolean(false);
|
private final AtomicBoolean combatUpdPlanned = new AtomicBoolean(false);
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventPlayerPriority event) {
|
public Void visit(GameEventPlayerPriority event) {
|
||||||
if (combatUpdPlanned.getAndSet(true)) { return null; }
|
if (!isMainHandler || combatUpdPlanned.getAndSet(true)) { return null; }
|
||||||
|
|
||||||
FThreads.invokeInEdtNowOrLater(gameView.getGui(), new Runnable() {
|
FThreads.invokeInEdtNowOrLater(gameView.getGui(), new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -109,6 +112,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
private final AtomicBoolean turnUpdPlanned = new AtomicBoolean(false);
|
private final AtomicBoolean turnUpdPlanned = new AtomicBoolean(false);
|
||||||
@Override
|
@Override
|
||||||
public Void visit(final GameEventTurnBegan event) {
|
public Void visit(final GameEventTurnBegan event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
if (FModel.getPreferences().getPrefBoolean(FPref.UI_STACK_CREATURES) && event.turnOwner != null) {
|
if (FModel.getPreferences().getPrefBoolean(FPref.UI_STACK_CREATURES) && event.turnOwner != null) {
|
||||||
// anything except stack will get here
|
// anything except stack will get here
|
||||||
updateZone(Pair.of(gameView.getPlayerView(event.turnOwner), ZoneType.Battlefield));
|
updateZone(Pair.of(gameView.getPlayerView(event.turnOwner), ZoneType.Battlefield));
|
||||||
@@ -128,6 +133,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventAnteCardsSelected ev) {
|
public Void visit(GameEventAnteCardsSelected ev) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
final List<CardView> options = Lists.newArrayList();
|
final List<CardView> options = Lists.newArrayList();
|
||||||
for (final Entry<Player, Card> kv : ev.cards.entries()) {
|
for (final Entry<Player, Card> kv : ev.cards.entries()) {
|
||||||
final CardView fakeCard = new CardView(true); //use fake card so real cards appear with proper formatting
|
final CardView fakeCard = new CardView(true); //use fake card so real cards appear with proper formatting
|
||||||
@@ -176,12 +183,10 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
InputBase.cancelAwaitNextInput(); //ensure "Waiting for opponent..." doesn't appear behind WinLo
|
InputBase.cancelAwaitNextInput(); //ensure "Waiting for opponent..." doesn't appear behind WinLo
|
||||||
MatchUtil.getController().showPromptMessage(localPlayer, ""); //clear prompt behind WinLose overlay
|
MatchUtil.getController().showPromptMessage(localPlayer, ""); //clear prompt behind WinLose overlay
|
||||||
ButtonUtil.update(localPlayer, "", "", false, false, false);
|
ButtonUtil.update(localPlayer, "", "", false, false, false);
|
||||||
|
if (isMainHandler) {
|
||||||
//only finish game once, and only if player is Gui player or Gui player isn't playing
|
|
||||||
if (localPlayer.getLobbyPlayer() == GamePlayerUtil.getGuiPlayer() || MatchUtil.getHumanCount() == 0) {
|
|
||||||
MatchUtil.getController().finishGame();
|
MatchUtil.getController().finishGame();
|
||||||
|
gameView.updateAchievements();
|
||||||
}
|
}
|
||||||
gameView.updateAchievements();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return null;
|
return null;
|
||||||
@@ -198,6 +203,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventSpellAbilityCast event) {
|
public Void visit(GameEventSpellAbilityCast event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
if (!stackUpdPlanned.getAndSet(true)) {
|
if (!stackUpdPlanned.getAndSet(true)) {
|
||||||
FThreads.invokeInEdtNowOrLater(gameView.getGui(), updStack);
|
FThreads.invokeInEdtNowOrLater(gameView.getGui(), updStack);
|
||||||
}
|
}
|
||||||
@@ -205,6 +212,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventSpellResolved event) {
|
public Void visit(GameEventSpellResolved event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
if (!stackUpdPlanned.getAndSet(true)) {
|
if (!stackUpdPlanned.getAndSet(true)) {
|
||||||
FThreads.invokeInEdtNowOrLater(gameView.getGui(), updStack);
|
FThreads.invokeInEdtNowOrLater(gameView.getGui(), updStack);
|
||||||
}
|
}
|
||||||
@@ -212,6 +221,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventSpellRemovedFromStack event) {
|
public Void visit(GameEventSpellRemovedFromStack event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
if (!stackUpdPlanned.getAndSet(true)) {
|
if (!stackUpdPlanned.getAndSet(true)) {
|
||||||
FThreads.invokeInEdtNowOrLater(gameView.getGui(), updStack);
|
FThreads.invokeInEdtNowOrLater(gameView.getGui(), updStack);
|
||||||
}
|
}
|
||||||
@@ -231,6 +242,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventZone event) {
|
public Void visit(GameEventZone event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
if (event.player != null) {
|
if (event.player != null) {
|
||||||
// anything except stack will get here
|
// anything except stack will get here
|
||||||
updateZone(Pair.of(gameView.getPlayerView(event.player), event.zoneType));
|
updateZone(Pair.of(gameView.getPlayerView(event.player), event.zoneType));
|
||||||
@@ -240,6 +253,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventCardAttachment event) {
|
public Void visit(GameEventCardAttachment event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
final Game game = event.equipment.getGame();
|
final Game game = event.equipment.getGame();
|
||||||
final PlayerZone zEq = (PlayerZone)game.getZoneOf(event.equipment);
|
final PlayerZone zEq = (PlayerZone)game.getZoneOf(event.equipment);
|
||||||
if (event.oldEntiy instanceof Card) {
|
if (event.oldEntiy instanceof Card) {
|
||||||
@@ -283,26 +298,36 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(final GameEventCardTapped event) {
|
public Void visit(final GameEventCardTapped event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
return updateSingleCard(gameView.getCardView(event.card));
|
return updateSingleCard(gameView.getCardView(event.card));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(final GameEventCardPhased event) {
|
public Void visit(final GameEventCardPhased event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
return updateSingleCard(gameView.getCardView(event.card));
|
return updateSingleCard(gameView.getCardView(event.card));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(final GameEventCardDamaged event) {
|
public Void visit(final GameEventCardDamaged event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
return updateSingleCard(gameView.getCardView(event.card));
|
return updateSingleCard(gameView.getCardView(event.card));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(final GameEventCardCounters event) {
|
public Void visit(final GameEventCardCounters event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
return updateSingleCard(gameView.getCardView(event.card));
|
return updateSingleCard(gameView.getCardView(event.card));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(final GameEventBlockersDeclared event) { // This is to draw icons on blockers declared by AI
|
public Void visit(final GameEventBlockersDeclared event) { // This is to draw icons on blockers declared by AI
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
for (MapOfLists<Card, Card> kv : event.blockers.values()) {
|
for (MapOfLists<Card, Card> kv : event.blockers.values()) {
|
||||||
for (Collection<Card> blockers : kv.values()) {
|
for (Collection<Card> blockers : kv.values()) {
|
||||||
updateManyCards(gameView.getCardViews(blockers));
|
updateManyCards(gameView.getCardViews(blockers));
|
||||||
@@ -313,13 +338,15 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventAttackersDeclared event) {
|
public Void visit(GameEventAttackersDeclared event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
// Skip redraw for GUI player?
|
// Skip redraw for GUI player?
|
||||||
if (event.player.getLobbyPlayer() == GamePlayerUtil.getGuiPlayer()) {
|
if (event.player.getLobbyPlayer() == GamePlayerUtil.getGuiPlayer()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update all attackers.
|
// Update all attackers.
|
||||||
// Although they might have been updated when they were apped, there could be someone with vigilance, not redrawn yet.
|
// Although they might have been updated when they were tapped, there could be someone with vigilance, not redrawn yet.
|
||||||
updateManyCards(gameView.getCardViews(event.attackersMap.values()));
|
updateManyCards(gameView.getCardViews(event.attackersMap.values()));
|
||||||
|
|
||||||
return super.visit(event);
|
return super.visit(event);
|
||||||
@@ -327,6 +354,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventCombatEnded event) {
|
public Void visit(GameEventCombatEnded event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
// This should remove sword/shield icons from combatants by the time game moves to M2
|
// This should remove sword/shield icons from combatants by the time game moves to M2
|
||||||
updateManyCards(gameView.getCardViews(event.attackers));
|
updateManyCards(gameView.getCardViews(event.attackers));
|
||||||
updateManyCards(gameView.getCardViews(event.blockers));
|
updateManyCards(gameView.getCardViews(event.blockers));
|
||||||
@@ -361,6 +390,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventCardChangeZone event) {
|
public Void visit(GameEventCardChangeZone event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
if (event.from != null) {
|
if (event.from != null) {
|
||||||
updateZone(event.from);
|
updateZone(event.from);
|
||||||
}
|
}
|
||||||
@@ -375,6 +406,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventCardStatsChanged event) {
|
public Void visit(GameEventCardStatsChanged event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
final Iterable<CardView> cardViews = gameView.getCardViews(event.cards);
|
final Iterable<CardView> cardViews = gameView.getCardViews(event.cards);
|
||||||
MatchUtil.getController().refreshCardDetails(cardViews);
|
MatchUtil.getController().refreshCardDetails(cardViews);
|
||||||
return updateManyCards(cardViews);
|
return updateManyCards(cardViews);
|
||||||
@@ -382,6 +415,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventPlayerStatsChanged event) {
|
public Void visit(GameEventPlayerStatsChanged event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
for (final Player p : event.players) {
|
for (final Player p : event.players) {
|
||||||
MatchUtil.getController().refreshCardDetails(gameView.getCardViews(p.getAllCards()));
|
MatchUtil.getController().refreshCardDetails(gameView.getCardViews(p.getAllCards()));
|
||||||
}
|
}
|
||||||
@@ -390,6 +425,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventShuffle event) {
|
public Void visit(GameEventShuffle event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
updateZone(event.player.getZone(ZoneType.Library));
|
updateZone(event.player.getZone(ZoneType.Library));
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -407,6 +444,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventManaPool event) {
|
public Void visit(GameEventManaPool event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
boolean invokeUpdate = false;
|
boolean invokeUpdate = false;
|
||||||
synchronized (manaPoolUpdate) {
|
synchronized (manaPoolUpdate) {
|
||||||
if (!manaPoolUpdate.contains(event.player)) {
|
if (!manaPoolUpdate.contains(event.player)) {
|
||||||
@@ -432,6 +471,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
};
|
};
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventPlayerLivesChanged event) {
|
public Void visit(GameEventPlayerLivesChanged event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
boolean invokeUpdate = false;
|
boolean invokeUpdate = false;
|
||||||
synchronized (livesUpdate) {
|
synchronized (livesUpdate) {
|
||||||
if (!livesUpdate.contains(event.player)) {
|
if (!livesUpdate.contains(event.player)) {
|
||||||
@@ -447,6 +488,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void visit(GameEventPlayerPoisoned event) {
|
public Void visit(GameEventPlayerPoisoned event) {
|
||||||
|
if (!isMainHandler) { return null; }
|
||||||
|
|
||||||
boolean invokeUpdate = false;
|
boolean invokeUpdate = false;
|
||||||
synchronized (livesUpdate) {
|
synchronized (livesUpdate) {
|
||||||
if (!livesUpdate.contains(event.receiver)) {
|
if (!livesUpdate.contains(event.receiver)) {
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ import forge.game.card.CounterType;
|
|||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.RegisteredPlayer;
|
import forge.game.player.RegisteredPlayer;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.spellability.SpellAbilityStackInstance;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.match.input.InputPlaybackControl;
|
import forge.match.input.InputPlaybackControl;
|
||||||
@@ -49,7 +51,6 @@ import forge.model.FModel;
|
|||||||
import forge.player.GamePlayerUtil;
|
import forge.player.GamePlayerUtil;
|
||||||
import forge.player.LobbyPlayerHuman;
|
import forge.player.LobbyPlayerHuman;
|
||||||
import forge.player.PlayerControllerHuman;
|
import forge.player.PlayerControllerHuman;
|
||||||
import forge.properties.ForgePreferences;
|
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.quest.QuestController;
|
import forge.quest.QuestController;
|
||||||
import forge.sound.MusicPlaylist;
|
import forge.sound.MusicPlaylist;
|
||||||
@@ -57,16 +58,29 @@ import forge.sound.SoundSystem;
|
|||||||
import forge.util.GuiDisplayUtil;
|
import forge.util.GuiDisplayUtil;
|
||||||
import forge.util.NameGenerator;
|
import forge.util.NameGenerator;
|
||||||
import forge.util.gui.SOptionPane;
|
import forge.util.gui.SOptionPane;
|
||||||
|
import forge.view.Cache;
|
||||||
import forge.view.CardView;
|
import forge.view.CardView;
|
||||||
import forge.view.GameEntityView;
|
import forge.view.GameEntityView;
|
||||||
import forge.view.LocalGameView;
|
import forge.view.LocalGameView;
|
||||||
import forge.view.PlayerView;
|
import forge.view.PlayerView;
|
||||||
|
import forge.view.SpellAbilityView;
|
||||||
|
import forge.view.StackItemView;
|
||||||
import forge.view.WatchLocalGame;
|
import forge.view.WatchLocalGame;
|
||||||
|
|
||||||
public class MatchUtil {
|
public class MatchUtil {
|
||||||
private static IMatchController controller;
|
private static IMatchController controller;
|
||||||
private static Game game;
|
private static Game game;
|
||||||
private static List<LocalGameView> gameViews = new ArrayList<LocalGameView>();
|
private static List<LocalGameView> gameViews = new ArrayList<LocalGameView>();
|
||||||
|
|
||||||
|
/** Cache of players. */
|
||||||
|
public static final Cache<Player, PlayerView> players = new Cache<>();
|
||||||
|
/** Cache of cards. */
|
||||||
|
public static final Cache<Card, CardView> cards = new Cache<>();
|
||||||
|
/** Cache of spellabilities. */
|
||||||
|
public static final Cache<SpellAbility, SpellAbilityView> spabs = new Cache<>();
|
||||||
|
/** Cache of stack items. */
|
||||||
|
public static final Cache<SpellAbilityStackInstance, StackItemView> stackItems = new Cache<>();
|
||||||
|
|
||||||
private static int humanCount;
|
private static int humanCount;
|
||||||
private static final EventBus uiEvents;
|
private static final EventBus uiEvents;
|
||||||
private static FControlGamePlayback playbackControl;
|
private static FControlGamePlayback playbackControl;
|
||||||
@@ -122,16 +136,6 @@ public class MatchUtil {
|
|||||||
public static void startGame(final Match match) {
|
public static void startGame(final Match match) {
|
||||||
if (!controller.resetForNewGame()) { return; }
|
if (!controller.resetForNewGame()) { return; }
|
||||||
|
|
||||||
//prompt user for player one name if needed
|
|
||||||
final ForgePreferences prefs = FModel.getPreferences();
|
|
||||||
if (StringUtils.isBlank(prefs.getPref(FPref.PLAYER_NAME))) {
|
|
||||||
boolean isPlayerOneHuman = match.getPlayers().get(0).getPlayer() instanceof LobbyPlayerHuman;
|
|
||||||
boolean isPlayerTwoComputer = match.getPlayers().get(1).getPlayer() instanceof LobbyPlayerAi;
|
|
||||||
if (isPlayerOneHuman && isPlayerTwoComputer) {
|
|
||||||
GamePlayerUtil.setPlayerName(GuiBase.getInterface());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundSystem.instance.setBackgroundMusic(MusicPlaylist.MATCH);
|
SoundSystem.instance.setBackgroundMusic(MusicPlaylist.MATCH);
|
||||||
|
|
||||||
game = match.createGame();
|
game = match.createGame();
|
||||||
@@ -147,7 +151,7 @@ public class MatchUtil {
|
|||||||
|
|
||||||
game.subscribeToEvents(SoundSystem.instance);
|
game.subscribeToEvents(SoundSystem.instance);
|
||||||
|
|
||||||
final String[] indices = prefs.getPref(FPref.UI_AVATARS).split(",");
|
final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");
|
||||||
|
|
||||||
// Instantiate all required field slots (user at 0)
|
// Instantiate all required field slots (user at 0)
|
||||||
final List<Player> sortedPlayers = new ArrayList<Player>(game.getRegisteredPlayers());
|
final List<Player> sortedPlayers = new ArrayList<Player>(game.getRegisteredPlayers());
|
||||||
@@ -175,7 +179,7 @@ public class MatchUtil {
|
|||||||
if (p.getController() instanceof PlayerControllerHuman) {
|
if (p.getController() instanceof PlayerControllerHuman) {
|
||||||
final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController();
|
final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController();
|
||||||
LocalGameView gameView = controller.getGameView();
|
LocalGameView gameView = controller.getGameView();
|
||||||
game.subscribeToEvents(new FControlGameEventHandler(gameView));
|
game.subscribeToEvents(new FControlGameEventHandler(gameView, humanCount == 0));
|
||||||
gameViews.add(gameView);
|
gameViews.add(gameView);
|
||||||
humanCount++;
|
humanCount++;
|
||||||
}
|
}
|
||||||
@@ -184,7 +188,7 @@ public class MatchUtil {
|
|||||||
if (humanCount == 0) { //watch game but do not participate
|
if (humanCount == 0) { //watch game but do not participate
|
||||||
LocalGameView gameView = new WatchLocalGame(GuiBase.getInterface(), game);
|
LocalGameView gameView = new WatchLocalGame(GuiBase.getInterface(), game);
|
||||||
gameView.setLocalPlayer(sortedPlayers.get(0));
|
gameView.setLocalPlayer(sortedPlayers.get(0));
|
||||||
game.subscribeToEvents(new FControlGameEventHandler(gameView));
|
game.subscribeToEvents(new FControlGameEventHandler(gameView, true));
|
||||||
gameViews.add(gameView);
|
gameViews.add(gameView);
|
||||||
}
|
}
|
||||||
else if (humanCount == sortedPlayers.size() && controller.hotSeatMode()) {
|
else if (humanCount == sortedPlayers.size() && controller.hotSeatMode()) {
|
||||||
@@ -207,6 +211,14 @@ public class MatchUtil {
|
|||||||
game.getAction().invoke(new Runnable() {
|
game.getAction().invoke(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
//prompt user for player one name if needed
|
||||||
|
if (StringUtils.isBlank(FModel.getPreferences().getPref(FPref.PLAYER_NAME))) {
|
||||||
|
boolean isPlayerOneHuman = match.getPlayers().get(0).getPlayer() instanceof LobbyPlayerHuman;
|
||||||
|
boolean isPlayerTwoComputer = match.getPlayers().get(1).getPlayer() instanceof LobbyPlayerAi;
|
||||||
|
if (isPlayerOneHuman && isPlayerTwoComputer) {
|
||||||
|
GamePlayerUtil.setPlayerName(GuiBase.getInterface());
|
||||||
|
}
|
||||||
|
}
|
||||||
match.startGame(game);
|
match.startGame(game);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import forge.ai.AiProfileUtil;
|
|||||||
import forge.ai.LobbyPlayerAi;
|
import forge.ai.LobbyPlayerAi;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.interfaces.IGuiBase;
|
import forge.interfaces.IGuiBase;
|
||||||
|
import forge.match.MatchUtil;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.util.GuiDisplayUtil;
|
import forge.util.GuiDisplayUtil;
|
||||||
@@ -73,18 +74,30 @@ public final class GamePlayerUtil {
|
|||||||
|
|
||||||
public static void setPlayerName(final IGuiBase gui) {
|
public static void setPlayerName(final IGuiBase gui) {
|
||||||
String oldPlayerName = FModel.getPreferences().getPref(FPref.PLAYER_NAME);
|
String oldPlayerName = FModel.getPreferences().getPref(FPref.PLAYER_NAME);
|
||||||
String newPlayerName = null;
|
|
||||||
|
|
||||||
|
String newPlayerName;
|
||||||
if (StringUtils.isBlank(oldPlayerName)) {
|
if (StringUtils.isBlank(oldPlayerName)) {
|
||||||
newPlayerName = getVerifiedPlayerName(getPlayerNameUsingFirstTimePrompt(gui), oldPlayerName);
|
newPlayerName = getVerifiedPlayerName(getPlayerNameUsingFirstTimePrompt(gui), oldPlayerName);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
newPlayerName = getVerifiedPlayerName(getPlayerNameUsingStandardPrompt(gui, oldPlayerName), oldPlayerName);
|
newPlayerName = getVerifiedPlayerName(getPlayerNameUsingStandardPrompt(gui, oldPlayerName), oldPlayerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//update name for player in active game if needed
|
||||||
|
if (MatchUtil.getGame() != null) {
|
||||||
|
for (Player player : MatchUtil.getGame().getPlayers()) {
|
||||||
|
if (player.getLobbyPlayer() == MatchUtil.getGuiPlayer()) {
|
||||||
|
player.setName(newPlayerName);
|
||||||
|
player.getLobbyPlayer().setName(newPlayerName);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FModel.getPreferences().setPref(FPref.PLAYER_NAME, newPlayerName);
|
FModel.getPreferences().setPref(FPref.PLAYER_NAME, newPlayerName);
|
||||||
FModel.getPreferences().save();
|
FModel.getPreferences().save();
|
||||||
|
|
||||||
if (StringUtils.isBlank(oldPlayerName) && newPlayerName != "Human") {
|
if (StringUtils.isBlank(oldPlayerName) && !newPlayerName.equals("Human")) {
|
||||||
showThankYouPrompt(gui, newPlayerName);
|
showThankYouPrompt(gui, newPlayerName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -93,7 +93,6 @@ import forge.match.input.InputConfirmMulligan;
|
|||||||
import forge.match.input.InputPassPriority;
|
import forge.match.input.InputPassPriority;
|
||||||
import forge.match.input.InputPayMana;
|
import forge.match.input.InputPayMana;
|
||||||
import forge.match.input.InputProliferate;
|
import forge.match.input.InputProliferate;
|
||||||
import forge.match.input.InputProxy;
|
|
||||||
import forge.match.input.InputSelectCardsForConvoke;
|
import forge.match.input.InputSelectCardsForConvoke;
|
||||||
import forge.match.input.InputSelectCardsFromList;
|
import forge.match.input.InputSelectCardsFromList;
|
||||||
import forge.match.input.InputSelectEntitiesFromList;
|
import forge.match.input.InputSelectEntitiesFromList;
|
||||||
@@ -153,10 +152,6 @@ public class PlayerControllerHuman extends PlayerController {
|
|||||||
return gameView.getGui();
|
return gameView.getGui();
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputProxy getInputProxy() {
|
|
||||||
return gameView.getInputProxy();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalGameView getGameView() {
|
public LocalGameView getGameView() {
|
||||||
return gameView;
|
return gameView;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import forge.game.spellability.SpellAbility;
|
|||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
import forge.game.spellability.SpellAbilityStackInstance;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.interfaces.IGuiBase;
|
import forge.interfaces.IGuiBase;
|
||||||
|
import forge.match.MatchUtil;
|
||||||
import forge.match.input.InputProxy;
|
import forge.match.input.InputProxy;
|
||||||
import forge.match.input.InputQueue;
|
import forge.match.input.InputQueue;
|
||||||
|
|
||||||
@@ -69,15 +70,6 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
localPlayerView = getPlayerView(localPlayer);
|
localPlayerView = getPlayerView(localPlayer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Cache of players. */
|
|
||||||
private final Cache<Player, PlayerView> players = new Cache<>();
|
|
||||||
/** Cache of cards. */
|
|
||||||
private final Cache<Card, CardView> cards = new Cache<>();
|
|
||||||
/** Cache of spellabilities. */
|
|
||||||
private final Cache<SpellAbility, SpellAbilityView> spabs = new Cache<>();
|
|
||||||
/** Cache of stack items. */
|
|
||||||
private final Cache<SpellAbilityStackInstance, StackItemView> stackItems = new Cache<>();
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see forge.view.IGameView#isCommander()
|
* @see forge.view.IGameView#isCommander()
|
||||||
*/
|
*/
|
||||||
@@ -261,7 +253,7 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
final List<SpellAbilityStackInstance> stack = Lists.newArrayList(game.getStack());
|
final List<SpellAbilityStackInstance> stack = Lists.newArrayList(game.getStack());
|
||||||
final List<StackItemView> items = Collections.unmodifiableList(getStack(stack));
|
final List<StackItemView> items = Collections.unmodifiableList(getStack(stack));
|
||||||
// clear the cache
|
// clear the cache
|
||||||
stackItems.retainAllKeys(stack);
|
MatchUtil.stackItems.retainAllKeys(stack);
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,19 +270,17 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private List<StackItemView> getStack(final Iterable<SpellAbilityStackInstance> stack) {
|
private List<StackItemView> getStack(final Iterable<SpellAbilityStackInstance> stack) {
|
||||||
synchronized (this) {
|
MatchUtil.stackItems.retainAllKeys(Lists.newArrayList(stack));
|
||||||
stackItems.retainAllKeys(Lists.newArrayList(stack));
|
final List<StackItemView> items = Lists.newLinkedList();
|
||||||
final List<StackItemView> items = Lists.newLinkedList();
|
for (final SpellAbilityStackInstance si : stack) {
|
||||||
for (final SpellAbilityStackInstance si : stack) {
|
final int id = si.getId();
|
||||||
final int id = si.getId();
|
if (MatchUtil.stackItems.containsKey(id)) {
|
||||||
if (stackItems.containsKey(id)) {
|
items.add(MatchUtil.stackItems.get(id));
|
||||||
items.add(stackItems.get(id));
|
} else {
|
||||||
} else {
|
items.add(getStackItemView(si));
|
||||||
items.add(getStackItemView(si));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return items;
|
|
||||||
}
|
}
|
||||||
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackItemView getStackItemView(final SpellAbilityStackInstance si) {
|
public StackItemView getStackItemView(final SpellAbilityStackInstance si) {
|
||||||
@@ -304,7 +294,7 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
si.getStackDescription(), getCardView(si.getSourceCard()),
|
si.getStackDescription(), getCardView(si.getSourceCard()),
|
||||||
getPlayerView(si.getActivator()), getCardViews(si.getTargetChoices().getTargetCards()),
|
getPlayerView(si.getActivator()), getCardViews(si.getTargetChoices().getTargetCards()),
|
||||||
getPlayerViews(si.getTargetChoices().getTargetPlayers()), si.isAbility(), si.isOptionalTrigger());
|
getPlayerViews(si.getTargetChoices().getTargetPlayers()), si.isAbility(), si.isOptionalTrigger());
|
||||||
stackItems.put(si, newItem);
|
MatchUtil.stackItems.put(si, newItem);
|
||||||
return newItem;
|
return newItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -312,7 +302,7 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
if (view == null) {
|
if (view == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return stackItems.getKey(view.getId());
|
return MatchUtil.stackItems.getKey(view.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public final GameEntityView getGameEntityView(final GameEntity e) {
|
public final GameEntityView getGameEntityView(final GameEntity e) {
|
||||||
@@ -360,13 +350,13 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final PlayerView view;
|
PlayerView view = MatchUtil.players.get(p.getId());
|
||||||
if (players.containsKey(p.getId())) {
|
if (view != null) {
|
||||||
view = players.get(p.getId());
|
|
||||||
getPlayerView(p, view);
|
getPlayerView(p, view);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
view = new PlayerView(p.getLobbyPlayer(), p.getId());
|
view = new PlayerView(p.getLobbyPlayer(), p.getId());
|
||||||
players.put(p, view);
|
MatchUtil.players.put(p, view);
|
||||||
getPlayerView(p, view);
|
getPlayerView(p, view);
|
||||||
view.setOpponents(getPlayerViews(p.getOpponents()));
|
view.setOpponents(getPlayerViews(p.getOpponents()));
|
||||||
}
|
}
|
||||||
@@ -377,14 +367,14 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
if (p == null) {
|
if (p == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return players.get(p.getId());
|
return MatchUtil.players.get(p.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player getPlayer(final PlayerView p) {
|
public Player getPlayer(final PlayerView p) {
|
||||||
if (p == null) {
|
if (p == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return players.getKey(p.getId());
|
return MatchUtil.players.getKey(p.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getPlayerView(final Player p, final PlayerView view) {
|
private void getPlayerView(final Player p, final PlayerView view) {
|
||||||
@@ -423,19 +413,19 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
final boolean isDisplayable = cUi == c;
|
final boolean isDisplayable = cUi == c;
|
||||||
final boolean mayShow = mayShowCard(c);
|
final boolean mayShow = mayShowCard(c);
|
||||||
|
|
||||||
CardView view = cards.get(c.getId());
|
CardView view = MatchUtil.cards.get(c.getId());
|
||||||
final boolean isNewView;
|
final boolean isNewView;
|
||||||
if (view != null) {
|
if (view != null) {
|
||||||
// Update to ensure the Card reference in the cache
|
// Update to ensure the Card reference in the cache
|
||||||
// is not an outdated Card.
|
// is not an outdated Card.
|
||||||
if (view.getId() > 0) {
|
if (view.getId() > 0) {
|
||||||
cards.updateKey(view.getId(), c);
|
MatchUtil.cards.updateKey(view.getId(), c);
|
||||||
}
|
}
|
||||||
isNewView = false;
|
isNewView = false;
|
||||||
} else if (isDisplayable && mayShow) {
|
} else if (isDisplayable && mayShow) {
|
||||||
view = new CardView(isDisplayable);
|
view = new CardView(isDisplayable);
|
||||||
view.setId(c.getId());
|
view.setId(c.getId());
|
||||||
cards.put(c, view);
|
MatchUtil.cards.put(c, view);
|
||||||
isNewView = true;
|
isNewView = true;
|
||||||
} else {
|
} else {
|
||||||
return CardView.EMPTY;
|
return CardView.EMPTY;
|
||||||
@@ -471,7 +461,7 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
return ViewUtil.transformIfNotNull(cardViews, new Function<CardView, CardView>() {
|
return ViewUtil.transformIfNotNull(cardViews, new Function<CardView, CardView>() {
|
||||||
@Override
|
@Override
|
||||||
public CardView apply(final CardView input) {
|
public CardView apply(final CardView input) {
|
||||||
return cards.getCurrentValue(input);
|
return MatchUtil.cards.getCurrentValue(input);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -481,7 +471,7 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
final CardView view = cards.get(c.getId());
|
final CardView view = MatchUtil.cards.get(c.getId());
|
||||||
if (mayShowCard(c)) {
|
if (mayShowCard(c)) {
|
||||||
return view;
|
return view;
|
||||||
} else if (view.isUiDisplayable()) {
|
} else if (view.isUiDisplayable()) {
|
||||||
@@ -506,7 +496,7 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
if (c == null) {
|
if (c == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return cards.getKey(c.getId());
|
return MatchUtil.cards.getKey(c.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Function<CardView, Card> FN_GET_CARD = new Function<CardView, Card>() {
|
private final Function<CardView, Card> FN_GET_CARD = new Function<CardView, Card>() {
|
||||||
@@ -521,30 +511,28 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void writeCardToView(final Card c, final CardView view) {
|
private void writeCardToView(final Card c, final CardView view) {
|
||||||
synchronized (c) {
|
// First, write the values independent of other views.
|
||||||
// First, write the values independent of other views.
|
ViewUtil.writeNonDependentCardViewProperties(c, view, mayShowCardFace(c));
|
||||||
ViewUtil.writeNonDependentCardViewProperties(c, view, mayShowCardFace(c));
|
// Next, write the values that depend on other views.
|
||||||
// Next, write the values that depend on other views.
|
final Combat combat = game.getCombat();
|
||||||
final Combat combat = game.getCombat();
|
view.setOwner(getPlayerViewFast(c.getOwner()));
|
||||||
view.setOwner(getPlayerViewFast(c.getOwner()));
|
view.setController(getPlayerViewFast(c.getController()));
|
||||||
view.setController(getPlayerViewFast(c.getController()));
|
view.setAttacking(combat != null && combat.isAttacking(c));
|
||||||
view.setAttacking(combat != null && combat.isAttacking(c));
|
view.setBlocking(combat != null && combat.isBlocking(c));
|
||||||
view.setBlocking(combat != null && combat.isBlocking(c));
|
view.setChosenPlayer(getPlayerViewFast(c.getChosenPlayer()));
|
||||||
view.setChosenPlayer(getPlayerViewFast(c.getChosenPlayer()));
|
view.setEquipping(getCardViewFast(Iterables.getFirst(c.getEquipping(), null)));
|
||||||
view.setEquipping(getCardViewFast(Iterables.getFirst(c.getEquipping(), null)));
|
view.setEquippedBy(getCardViewsFast(c.getEquippedBy()));
|
||||||
view.setEquippedBy(getCardViewsFast(c.getEquippedBy()));
|
view.setEnchantingCard(getCardViewFast(c.getEnchantingCard()));
|
||||||
view.setEnchantingCard(getCardViewFast(c.getEnchantingCard()));
|
view.setEnchantingPlayer(getPlayerViewFast(c.getEnchantingPlayer()));
|
||||||
view.setEnchantingPlayer(getPlayerViewFast(c.getEnchantingPlayer()));
|
view.setEnchantedBy(getCardViewsFast(c.getEnchantedBy()));
|
||||||
view.setEnchantedBy(getCardViewsFast(c.getEnchantedBy()));
|
view.setFortifiedBy(getCardViewsFast(c.getFortifiedBy()));
|
||||||
view.setFortifiedBy(getCardViewsFast(c.getFortifiedBy()));
|
view.setGainControlTargets(getCardViewsFast(c.getGainControlTargets()));
|
||||||
view.setGainControlTargets(getCardViewsFast(c.getGainControlTargets()));
|
view.setCloneOrigin(getCardViewFast(c.getCloneOrigin()));
|
||||||
view.setCloneOrigin(getCardViewFast(c.getCloneOrigin()));
|
view.setImprinted(getCardViewsFast(c.getImprinted()));
|
||||||
view.setImprinted(getCardViewsFast(c.getImprinted()));
|
view.setHauntedBy(getCardViewsFast(c.getHauntedBy()));
|
||||||
view.setHauntedBy(getCardViewsFast(c.getHauntedBy()));
|
view.setHaunting(getCardViewFast(c.getHaunting()));
|
||||||
view.setHaunting(getCardViewFast(c.getHaunting()));
|
view.setMustBlock(c.getMustBlockCards() == null ? Collections.<CardView>emptySet() : getCardViewsFast(c.getMustBlockCards()));
|
||||||
view.setMustBlock(c.getMustBlockCards() == null ? Collections.<CardView>emptySet() : getCardViewsFast(c.getMustBlockCards()));
|
view.setPairedWith(getCardViewFast(c.getPairedWith()));
|
||||||
view.setPairedWith(getCardViewFast(c.getPairedWith()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public SpellAbilityView getSpellAbilityView(final SpellAbility sa) {
|
public SpellAbilityView getSpellAbilityView(final SpellAbility sa) {
|
||||||
@@ -553,13 +541,13 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final SpellAbilityView view;
|
final SpellAbilityView view;
|
||||||
if (spabs.containsKey(sa.getId())) {
|
if (MatchUtil.spabs.containsKey(sa.getId())) {
|
||||||
view = spabs.get(sa.getId());
|
view = MatchUtil.spabs.get(sa.getId());
|
||||||
writeSpellAbilityToView(sa, view);
|
writeSpellAbilityToView(sa, view);
|
||||||
} else {
|
} else {
|
||||||
view = new SpellAbilityView(sa.getId());
|
view = new SpellAbilityView(sa.getId());
|
||||||
writeSpellAbilityToView(sa, view);
|
writeSpellAbilityToView(sa, view);
|
||||||
spabs.put(sa, view);
|
MatchUtil.spabs.put(sa, view);
|
||||||
}
|
}
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
@@ -582,7 +570,7 @@ public abstract class LocalGameView implements IGameView {
|
|||||||
return getSpellAbility(spabView.getId());
|
return getSpellAbility(spabView.getId());
|
||||||
}
|
}
|
||||||
public SpellAbility getSpellAbility(final int id) {
|
public SpellAbility getSpellAbility(final int id) {
|
||||||
return id >= 0 ? spabs.getKey(id) : null;
|
return id >= 0 ? MatchUtil.spabs.getKey(id) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Function<SpellAbilityView, SpellAbility> FN_GET_SPAB = new Function<SpellAbilityView, SpellAbility>() {
|
private final Function<SpellAbilityView, SpellAbility> FN_GET_SPAB = new Function<SpellAbilityView, SpellAbility>() {
|
||||||
|
|||||||
Reference in New Issue
Block a user