Completely refactor the GUI code.

All direct references to a gui have been replaced by a field, allowing dynamic GUI assignment throughout the code (necessary for eg. network play). Fixes almost all errors. Untested.
This commit is contained in:
elcnesh
2014-09-04 09:44:31 +00:00
parent 1a9b54cdd4
commit 89b3395cec
128 changed files with 3332 additions and 2899 deletions

View File

@@ -0,0 +1,14 @@
package forge;
import forge.interfaces.IGuiBase;
public class GuiBase {
private static IGuiBase guiInterface;
public static IGuiBase getInterface() {
return guiInterface;
}
public static void setInterface(IGuiBase i0) {
guiInterface = i0;
}
}

View File

@@ -36,7 +36,7 @@ import forge.game.Match;
import forge.game.phase.PhaseType;
import forge.game.player.IHasIcon;
import forge.game.player.RegisteredPlayer;
import forge.game.spellability.SpellAbility;
//import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.gui.BoxedProductCardListViewer;
import forge.gui.CardListViewer;
@@ -79,6 +79,7 @@ import forge.view.CombatView;
import forge.view.GameEntityView;
import forge.view.IGameView;
import forge.view.PlayerView;
import forge.view.SpellAbilityView;
public class GuiDesktop implements IGuiBase {
@@ -153,7 +154,7 @@ public class GuiDesktop implements IGuiBase {
@Override
public int showCardOptionDialog(final CardView card, String message, String title, FSkinProp skinIcon, String[] options, int defaultOption) {
if (card != null) {
FThreads.invokeInEdtAndWait(new Runnable() {
FThreads.invokeInEdtAndWait(GuiBase.getInterface(), new Runnable() {
@Override
public void run() {
GuiBase.getInterface().setCard(card);
@@ -213,7 +214,7 @@ public class GuiDesktop implements IGuiBase {
public void focusButton(final IButton button) {
// ensure we don't steal focus from an overlay
if (!SOverlayUtils.overlayHasFocus()) {
FThreads.invokeInEdtLater(new Runnable() {
FThreads.invokeInEdtLater(GuiBase.getInterface(), new Runnable() {
@Override
public void run() {
((FButton)button).requestFocusInWindow();
@@ -294,7 +295,7 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public SpellAbility getAbilityToPlay(List<SpellAbility> abilities, ITriggerEvent triggerEvent) {
public SpellAbilityView getAbilityToPlay(List<SpellAbilityView> abilities, ITriggerEvent triggerEvent) {
if (triggerEvent == null) {
if (abilities.isEmpty()) {
return null;
@@ -308,7 +309,7 @@ public class GuiDesktop implements IGuiBase {
if (abilities.isEmpty()) {
return null;
}
if (abilities.size() == 1 && !abilities.get(0).promptIfOnlyPossibleAbility()) {
if (abilities.size() == 1 && !abilities.get(0).isPromptIfOnlyPossibleAbility()) {
if (abilities.get(0).canPlay()) {
return abilities.get(0); //only return ability if it's playable, otherwise return null
}
@@ -321,7 +322,7 @@ public class GuiDesktop implements IGuiBase {
boolean enabled;
boolean hasEnabled = false;
int shortcut = KeyEvent.VK_1; //use number keys as shortcuts for abilities 1-9
for (final SpellAbility ab : abilities) {
for (final SpellAbilityView ab : abilities) {
enabled = ab.canPlay();
if (enabled) {
hasEnabled = true;
@@ -451,7 +452,7 @@ public class GuiDesktop implements IGuiBase {
}
@Override
public void refreshCardDetails(final Collection<CardView> cards) {
public void refreshCardDetails(final Iterable<CardView> cards) {
CMatchUI.SINGLETON_INSTANCE.refreshCardDetails(cards);
}

View File

@@ -199,7 +199,7 @@ public class ImageCache {
* Returns the Image corresponding to the key.
*/
private static BufferedImage getImage(final String key) {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
try {
return ImageCache._CACHE.get(key);
} catch (final ExecutionException ex) {

View File

@@ -19,6 +19,8 @@ package forge;
import forge.control.FControl;
import forge.model.FModel;
import forge.properties.ForgeConstants;
import forge.properties.ForgeProfileProperties;
import forge.view.FView;
/**
@@ -37,7 +39,7 @@ public final class Singletons {
public static FControl getControl() { return control; }
public static void initializeOnce(boolean withUi) {
FThreads.assertExecutedByEdt(false);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), false);
synchronized (Singletons.class) {
if (initialized) {
@@ -46,11 +48,14 @@ public final class Singletons {
initialized = true;
}
ForgeConstants.init(GuiBase.getInterface());
ForgeProfileProperties.init(GuiBase.getInterface());
if (withUi) {
view = FView.SINGLETON_INSTANCE;
}
FModel.initialize(view == null ? null : view.getSplash().getProgressBar());
FModel.initialize(GuiBase.getInterface(), view == null ? null : view.getSplash().getProgressBar());
if (withUi) {
control = FControl.instance;

View File

@@ -51,6 +51,7 @@ import forge.game.GameRules;
import forge.game.GameType;
import forge.game.Match;
import forge.game.player.Player;
//import forge.game.player.Player;
import forge.game.player.RegisteredPlayer;
import forge.gui.GuiDialog;
import forge.gui.SOverlayUtils;
@@ -66,6 +67,8 @@ import forge.menus.ForgeMenu;
import forge.model.FModel;
import forge.player.GamePlayerUtil;
import forge.player.LobbyPlayerHuman;
import forge.player.PlayerControllerHuman;
import forge.player.PlayerControllerLocal;
import forge.properties.ForgeConstants;
import forge.properties.ForgePreferences;
import forge.properties.ForgePreferences.FPref;
@@ -122,7 +125,7 @@ public enum FControl implements KeyEventDispatcher {
EXIT_FORGE
}
private final SoundSystem soundSystem = new SoundSystem();
private final SoundSystem soundSystem = new SoundSystem(GuiBase.getInterface());
/**
* <p>
@@ -190,10 +193,10 @@ public enum FControl implements KeyEventDispatcher {
public boolean canExitForge(boolean forRestart) {
String action = (forRestart ? "Restart" : "Exit");
String userPrompt = "Are you sure you wish to " + (forRestart ? "restart" : "exit") + " Forge?";
if (this.game != null) {
if (this.gameView != null) {
userPrompt = "A game is currently active. " + userPrompt;
}
if (!FOptionPane.showConfirmDialog(userPrompt, action + " Forge", action, "Cancel", this.game == null)) { //default Yes if no game active
if (!FOptionPane.showConfirmDialog(userPrompt, action + " Forge", action, "Cancel", this.gameView == null)) { //default Yes if no game active
return false;
}
if (!CDeckEditorUI.SINGLETON_INSTANCE.canSwitchAway(true)) {
@@ -385,11 +388,6 @@ public enum FControl implements KeyEventDispatcher {
private IGameView gameView;
private boolean gameHasHumanPlayer;
@Deprecated
public Game getObservedGame() {
return game;
}
public IGameView getGameView() {
return this.gameView;
}
@@ -443,22 +441,24 @@ public enum FControl implements KeyEventDispatcher {
}
public final void startGameWithUi(final Match match) {
if (this.game != null) {
if (this.gameView != null) {
this.setCurrentScreen(FScreen.MATCH_SCREEN);
SOverlayUtils.hideOverlay();
FOptionPane.showMessageDialog("Cannot start a new game while another game is already in progress.");
return; //TODO: See if it's possible to run multiple games at once without crashing
}
setPlayerName(match.getPlayers());
this.game = match.createGame();
final Game game = match.createGame();
final LobbyPlayer me = getGuiPlayer();
for (final Player p : this.game.getPlayers()) {
for (final Player p : game.getPlayers()) {
if (p.getLobbyPlayer().equals(me)) {
this.gameView = (IGameView) p.getController();
fcVisitor = new FControlGameEventHandler((PlayerControllerHuman) p.getController());
break;
}
}
inputQueue = new InputQueue(GuiBase.getInterface(), game);
attachToGame(this.gameView);
// It's important to run match in a different thread to allow GUI inputs to be invoked from inside game.
@@ -473,14 +473,15 @@ public enum FControl implements KeyEventDispatcher {
}
public final void endCurrentGame() {
if (this.game == null) { return; }
if (this.gameView == null) { return; }
Singletons.getView().getNavigationBar().closeTab(FScreen.MATCH_SCREEN);
this.game = null;
this.gameView = null;
}
private final FControlGameEventHandler fcVisitor = new FControlGameEventHandler();
private final FControlGamePlayback playbackControl = new FControlGamePlayback();
private FControlGameEventHandler fcVisitor;
private FControlGamePlayback playbackControl;// = new FControlGamePlayback();
private void attachToGame(final IGameView game0) {
if (game0.getGameType().equals(GameType.Quest)) {
QuestController qc = FModel.getQuest();
@@ -491,8 +492,6 @@ public enum FControl implements KeyEventDispatcher {
game0.subscribeToEvents(qc); // this one listens to player's mulligans ATM
}
inputQueue = new InputQueue();
game0.subscribeToEvents(Singletons.getControl().getSoundSystem());
//switch back to match screen music
@@ -531,6 +530,11 @@ public enum FControl implements KeyEventDispatcher {
// Add playback controls to match if needed
if (localPlayer != null) {
// Create dummy controller
final PlayerControllerHuman controller =
new PlayerControllerLocal(game, null, humanLobbyPlayer, GuiBase.getInterface());
playbackControl = new FControlGamePlayback(controller);
playbackControl.setGame(game);
game0.subscribeToEvents(playbackControl);
}
@@ -590,7 +594,7 @@ public enum FControl implements KeyEventDispatcher {
boolean isPlayerOneHuman = players.get(0).getPlayer() instanceof LobbyPlayerHuman;
boolean isPlayerTwoComputer = players.get(1).getPlayer() instanceof LobbyPlayerAi;
if (isPlayerOneHuman && isPlayerTwoComputer) {
GamePlayerUtil.setPlayerName();
GamePlayerUtil.setPlayerName(GuiBase.getInterface());
}
}
}
@@ -616,7 +620,7 @@ public enum FControl implements KeyEventDispatcher {
final Match mc = new Match(rules, players);
SOverlayUtils.startGameOverlay();
SOverlayUtils.showOverlay();
FThreads.invokeInEdtLater(new Runnable(){
FThreads.invokeInEdtLater(GuiBase.getInterface(), new Runnable(){
@Override
public void run() {
startGameWithUi(mc);
@@ -740,7 +744,7 @@ public enum FControl implements KeyEventDispatcher {
return player;
}
private final LobbyPlayer guiPlayer = new LobbyPlayerHuman("Human");
private final LobbyPlayer guiPlayer = new LobbyPlayerHuman("Human", GuiBase.getInterface());
public final LobbyPlayer getGuiPlayer() {
return guiPlayer;
}

View File

@@ -1,6 +1,7 @@
package forge.deckchooser;
import forge.FThreads;
import forge.GuiBase;
import forge.UiCommand;
import forge.deck.ColorDeckGenerator;
import forge.deck.Deck;
@@ -50,7 +51,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
//Show dialog to select a deck
public static Deck promptForDeck(String title, DeckType defaultDeckType, boolean forAi) {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
final FDeckChooser chooser = new FDeckChooser(forAi);
chooser.initialize(defaultDeckType);
chooser.populate();
@@ -130,7 +131,7 @@ public class FDeckChooser extends JPanel implements IDecksComboBoxListener {
"White", "Blue", "Black", "Red", "Green" };
ArrayList<DeckProxy> decks = new ArrayList<DeckProxy>();
for (int i = 0; i < colors.length; i++) {
decks.add(new ColorDeckGenerator(colors[i], i, lstDecks, isAi));
decks.add(new ColorDeckGenerator(GuiBase.getInterface(), colors[i], i, lstDecks, isAi));
}
lstDecks.setPool(decks);

View File

@@ -19,6 +19,7 @@ package forge.download;
import java.net.Proxy;
import forge.GuiBase;
import forge.UiCommand;
import forge.assets.FSkinProp;
import forge.gui.SOverlayUtils;
@@ -95,7 +96,7 @@ public class GuiDownloader extends DefaultBoundedRangeModel {
pnl.add(pnlDialog, "w 400px!, h 350px!, ax center, ay center");
SOverlayUtils.showOverlay();
service.initialize(txtAddress, txtPort, progressBar, btnStart, cmdClose, null, new Runnable() {
service.initialize(GuiBase.getInterface(), txtAddress, txtPort, progressBar, btnStart, cmdClose, null, new Runnable() {
@Override
public void run() {
fireStateChanged();

View File

@@ -17,6 +17,7 @@
*/
package forge.error;
import forge.GuiBase;
import forge.gui.WrapLayout;
import forge.toolbox.FHyperlink;
import forge.toolbox.FLabel;
@@ -92,7 +93,7 @@ public class BugReportDialog {
@Override
public void actionPerformed(final ActionEvent e) {
BugReporter.copyAndGoToForums(text.getText());
BugReporter.copyAndGoToForums(GuiBase.getInterface(), text.getText());
}
}
@@ -108,7 +109,7 @@ public class BugReportDialog {
@Override
public void actionPerformed(final ActionEvent e) {
BugReporter.saveToFile(area.getText());
BugReporter.saveToFile(GuiBase.getInterface(), area.getText());
}
}

View File

@@ -20,6 +20,7 @@ import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import forge.FThreads;
import forge.GuiBase;
import forge.Singletons;
import forge.item.InventoryItem;
import forge.screens.match.CMatchUI;
@@ -237,7 +238,7 @@ public class GuiChoose {
};
FutureTask<List<T>> future = new FutureTask<List<T>>(showChoice);
FThreads.invokeInEdtAndWait(future);
FThreads.invokeInEdtAndWait(GuiBase.getInterface(), future);
try {
return future.get();
} catch (Exception e) { // should be no exception here
@@ -296,7 +297,7 @@ public class GuiChoose {
};
FutureTask<List<T>> ft = new FutureTask<List<T>>(callable);
FThreads.invokeInEdtAndWait(ft);
FThreads.invokeInEdtAndWait(GuiBase.getInterface(), ft);
try {
return ft.get();
} catch (Exception e) { // we have waited enough

View File

@@ -8,6 +8,7 @@ import javax.swing.UIManager;
import org.apache.commons.lang3.StringUtils;
import forge.FThreads;
import forge.GuiBase;
import forge.screens.match.CMatchUI;
import forge.toolbox.FOptionPane;
import forge.view.CardView;
@@ -45,7 +46,7 @@ public class GuiDialog {
}};
FutureTask<Boolean> future = new FutureTask<Boolean>(confirmTask);
FThreads.invokeInEdtAndWait(future);
FThreads.invokeInEdtAndWait(GuiBase.getInterface(), future);
try {
return future.get().booleanValue();
}
@@ -68,7 +69,7 @@ public class GuiDialog {
}
public static void message(final String message, final String title) {
FThreads.invokeInEdtAndWait(new Runnable() {
FThreads.invokeInEdtAndWait(GuiBase.getInterface(), new Runnable() {
@Override
public void run() {
FOptionPane.showMessageDialog(message, title, null);

View File

@@ -22,6 +22,7 @@ import com.google.common.base.Function;
import com.google.common.collect.Lists;
import forge.FThreads;
import forge.GuiBase;
import forge.toolbox.FList;
import forge.toolbox.FMouseAdapter;
import forge.toolbox.FOptionPane;
@@ -75,7 +76,7 @@ public class ListChooser<T> {
private FOptionPane optionPane;
public ListChooser(final String title, final int minChoices, final int maxChoices, final Collection<T> list, final Function<T, String> display) {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
this.minChoices = minChoices;
this.maxChoices = maxChoices;
this.list = list.getClass().isInstance(List.class) ? (List<T>)list : Lists.newArrayList(list);

View File

@@ -1,9 +1,11 @@
package forge.gui.framework;
import forge.FThreads;
import forge.GuiBase;
import forge.view.FFrame;
import javax.swing.*;
import java.awt.*;
import java.util.Timer;
import java.util.TimerTask;
@@ -100,7 +102,7 @@ public class SDisplayUtil {
}
}
};
FThreads.invokeInEdtLater(showTabRoutine);
FThreads.invokeInEdtLater(GuiBase.getInterface(), showTabRoutine);
}
public static GraphicsDevice getGraphicsDevice(Point point) {

View File

@@ -1,5 +1,6 @@
package forge.screens.bazaar;
import forge.GuiBase;
import forge.UiCommand;
import forge.assets.FSkinProp;
import forge.gui.framework.FScreen;
@@ -42,7 +43,7 @@ public enum VBazaarUI implements IVTopLevelUI {
final FLabel lbl = new FLabel.ButtonBuilder().text(s + " ")
.fontAlign(SwingConstants.RIGHT).iconInBackground(true).selectable()
.fontSize(16).icon((SkinImage)bazaar.getStall(s).getIcon()).build();
.fontSize(16).icon((SkinImage)GuiBase.getInterface().getSkinIcon(bazaar.getStall(s).getIcon())).build();
pnlAllStalls.add(lbl, "h 80px!, w 90%!, gap 0 0 10px 10px");

View File

@@ -17,6 +17,7 @@
*/
package forge.screens.deckeditor.controllers;
import forge.GuiBase;
import forge.UiCommand;
import forge.assets.FSkinProp;
import forge.deck.DeckBase;
@@ -148,7 +149,7 @@ public final class CEditorQuestCardShop extends ACEditorBase<InventoryItem, Deck
return;
}
QuestSpellShop.buy(items, this.getCatalogManager(), this.getDeckManager(), true);
QuestSpellShop.buy(GuiBase.getInterface(), items, this.getCatalogManager(), this.getDeckManager(), true);
updateCreditsLabel();
}
@@ -159,7 +160,7 @@ public final class CEditorQuestCardShop extends ACEditorBase<InventoryItem, Deck
protected void onRemoveItems(Iterable<Entry<InventoryItem, Integer>> items, boolean toAlternate) {
if (showingFullCatalog || toAlternate) { return; }
QuestSpellShop.sell(items, this.getCatalogManager(), this.getDeckManager(), true);
QuestSpellShop.sell(GuiBase.getInterface(), items, this.getCatalogManager(), this.getDeckManager(), true);
updateCreditsLabel();
}

View File

@@ -1,5 +1,6 @@
package forge.screens.home.quest;
import forge.GuiBase;
import forge.UiCommand;
import forge.Singletons;
import forge.gui.framework.EDocID;
@@ -42,29 +43,29 @@ public enum CSubmenuChallenges implements ICDoc {
view.getBtnSpellShop().setCommand(
new UiCommand() { @Override
public void run() { QuestUtil.showSpellShop(); } });
public void run() { QuestUtil.showSpellShop(GuiBase.getInterface()); } });
view.getBtnBazaar().setCommand(
new UiCommand() { @Override
public void run() { QuestUtil.showBazaar(); } });
public void run() { QuestUtil.showBazaar(GuiBase.getInterface()); } });
view.getBtnUnlock().setCommand(
new UiCommand() { @Override
public void run() { QuestUtil.chooseAndUnlockEdition(); CSubmenuChallenges.this.update(); } });
public void run() { QuestUtil.chooseAndUnlockEdition(GuiBase.getInterface()); CSubmenuChallenges.this.update(); } });
view.getBtnTravel().setCommand(
new UiCommand() { @Override
public void run() { QuestUtil.travelWorld(); CSubmenuChallenges.this.update(); } });
public void run() { QuestUtil.travelWorld(GuiBase.getInterface()); CSubmenuChallenges.this.update(); } });
view.getBtnStart().addActionListener(
new ActionListener() { @Override
public void actionPerformed(final ActionEvent e) { QuestUtil.startGame(); } });
public void actionPerformed(final ActionEvent e) { QuestUtil.startGame(GuiBase.getInterface()); } });
((FLabel) view.getLblZep()).setCommand(
new UiCommand() {
@Override
public void run() {
if (!QuestUtil.checkActiveQuest("Launch a Zeppelin.")) {
if (!QuestUtil.checkActiveQuest(GuiBase.getInterface(), "Launch a Zeppelin.")) {
return;
}
FModel.getQuest().getAchievements().setCurrentChallenges(null);

View File

@@ -1,5 +1,6 @@
package forge.screens.home.quest;
import forge.GuiBase;
import forge.UiCommand;
import forge.gui.framework.EDocID;
import forge.gui.framework.ICDoc;
@@ -36,23 +37,23 @@ public enum CSubmenuDuels implements ICDoc {
view.getBtnSpellShop().setCommand(
new UiCommand() { @Override
public void run() { QuestUtil.showSpellShop(); } });
public void run() { QuestUtil.showSpellShop(GuiBase.getInterface()); } });
view.getBtnBazaar().setCommand(
new UiCommand() { @Override
public void run() { QuestUtil.showBazaar(); } });
public void run() { QuestUtil.showBazaar(GuiBase.getInterface()); } });
view.getBtnTravel().setCommand(
new UiCommand() { @Override
public void run() { QuestUtil.travelWorld(); CSubmenuDuels.this.update(); } });
public void run() { QuestUtil.travelWorld(GuiBase.getInterface()); CSubmenuDuels.this.update(); } });
view.getBtnUnlock().setCommand(
new UiCommand() { @Override
public void run() { QuestUtil.chooseAndUnlockEdition(); CSubmenuDuels.this.update(); } });
public void run() { QuestUtil.chooseAndUnlockEdition(GuiBase.getInterface()); CSubmenuDuels.this.update(); } });
view.getBtnStart().addActionListener(
new ActionListener() { @Override
public void actionPerformed(final ActionEvent e) { QuestUtil.startGame(); } });
public void actionPerformed(final ActionEvent e) { QuestUtil.startGame(GuiBase.getInterface()); } });
final QuestController quest = FModel.getQuest();
view.getCbPlant().addActionListener(new ActionListener() {
@@ -86,11 +87,11 @@ public enum CSubmenuDuels implements ICDoc {
view.getBtnRandomOpponent().setCommand(new UiCommand() {
@Override
public void run() {
if (QuestUtil.canStartGame()) {
if (QuestUtil.canStartGame(GuiBase.getInterface())) {
FModel.getQuest().getDuelsManager().randomizeOpponents();
final List<QuestEventDuel> duels = FModel.getQuest().getDuelsManager().generateDuels();
QuestUtil.setEvent(duels.get((int) (Math.random() * duels.size())));
QuestUtil.startGame();
QuestUtil.startGame(GuiBase.getInterface());
}
}
});

View File

@@ -1,5 +1,6 @@
package forge.screens.home.quest;
import forge.GuiBase;
import forge.UiCommand;
import forge.Singletons;
import forge.deck.DeckProxy;
@@ -56,7 +57,7 @@ public enum CSubmenuQuestDecks implements ICDoc {
VSubmenuQuestDecks.SINGLETON_INSTANCE.getBtnNewDeck().setCommand(new UiCommand() {
@Override
public void run() {
if (!QuestUtil.checkActiveQuest("Create a Deck.")) {
if (!QuestUtil.checkActiveQuest(GuiBase.getInterface(), "Create a Deck.")) {
return;
}
Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_QUEST);

View File

@@ -297,7 +297,7 @@ public enum CSubmenuQuestDraft implements ICDoc {
view.setMode(Mode.TOURNAMENT_ACTIVE);
}
QuestDraftUtils.update();
QuestDraftUtils.update(GuiBase.getInterface());
switch (view.getMode()) {
@@ -477,7 +477,7 @@ public enum CSubmenuQuestDraft implements ICDoc {
drafting = true;
BoosterDraft draft = draftEvent.enter();
BoosterDraft draft = draftEvent.enter(GuiBase.getInterface());
final CEditorQuestDraftingProcess draftController = new CEditorQuestDraftingProcess();
draftController.showGui(draft);
@@ -517,7 +517,7 @@ public enum CSubmenuQuestDraft implements ICDoc {
return;
}
QuestDraftUtils.startNextMatch();
QuestDraftUtils.startNextMatch(GuiBase.getInterface());
}

View File

@@ -1,6 +1,8 @@
package forge.screens.home.quest;
import forge.GuiBase;
import forge.UiCommand;
import forge.assets.FSkinProp;
import forge.model.FModel;
import forge.quest.QuestUtil;
import forge.quest.bazaar.IQuestBazaarItem;
@@ -75,7 +77,23 @@ public class ViewItem extends FPanel {
final QuestAssets qA = FModel.getQuest().getAssets();
IQuestBazaarItem bazaarItem = ViewItem.this.getItem();
ViewItem.this.lblIcon.setIcon((SkinImage)bazaarItem.getIcon(qA));
SkinImage i;
try {
final FSkinProp f = FSkinProp.valueOf(FSkinProp.class, bazaarItem.getIcon(qA));
i = (SkinImage) GuiBase.getInterface().getSkinIcon(f);
} catch (final IllegalArgumentException e) {
// Failed to parse FSkinProp
try {
i = (SkinImage) GuiBase.getInterface().getUnskinnedIcon(bazaarItem.getIcon(qA));
} catch (final Exception e1) {
// give up, icon unknown
e1.printStackTrace();
i = (SkinImage) GuiBase.getInterface().getSkinIcon(FSkinProp.ICO_UNKNOWN);
}
}
ViewItem.this.lblIcon.setIcon(i);
ViewItem.this.lblName.setText(bazaarItem.getPurchaseName());
ViewItem.this.lblPrice.setText("Cost: " + String.valueOf(bazaarItem.getBuyingPrice(qA)) + " credits");
String desc = bazaarItem.getPurchaseDescription(qA);

View File

@@ -114,11 +114,11 @@ public enum CSubmenuDraft implements ICDoc {
}
}
FModel.getGauntletMini().resetGauntletDraft();
FModel.getGauntletMini(GuiBase.getInterface()).resetGauntletDraft();
if (gauntlet) {
int rounds = FModel.getDecks().getDraft().get(humanDeck.getName()).getAiDecks().size();
FModel.getGauntletMini().launch(rounds, humanDeck.getDeck(), gameType);
FModel.getGauntletMini(GuiBase.getInterface()).launch(rounds, humanDeck.getDeck(), gameType);
return;
}
@@ -152,7 +152,7 @@ public enum CSubmenuDraft implements ICDoc {
final LimitedPoolType poolType = GuiChoose.oneOrNone("Choose Draft Format", LimitedPoolType.values());
if (poolType == null) { return; }
BoosterDraft draft = BoosterDraft.createDraft(poolType);
BoosterDraft draft = BoosterDraft.createDraft(GuiBase.getInterface(), poolType);
if (draft == null) { return; }
final CEditorDraftingProcess draftController = new CEditorDraftingProcess();

View File

@@ -1,5 +1,6 @@
package forge.screens.home.sanctioned;
import forge.GuiBase;
import forge.UiCommand;
import forge.Singletons;
import forge.deck.*;
@@ -16,6 +17,7 @@ import forge.screens.deckeditor.CDeckEditorUI;
import forge.screens.deckeditor.controllers.ACEditorBase;
import forge.screens.deckeditor.controllers.CEditorLimited;
import forge.toolbox.FOptionPane;
import javax.swing.*;
import java.awt.event.ActionEvent;
@@ -108,12 +110,12 @@ public enum CSubmenuSealed implements ICDoc {
}
int matches = FModel.getDecks().getSealed().get(human.getName()).getAiDecks().size();
FModel.getGauntletMini().launch(matches, human.getDeck(), gameType);
FModel.getGauntletMini(GuiBase.getInterface()).launch(matches, human.getDeck(), gameType);
}
@SuppressWarnings("unchecked")
private <T extends DeckBase> void setupSealed() {
final DeckGroup sealed = SealedCardPoolGenerator.generateSealedDeck(true);
final DeckGroup sealed = SealedCardPoolGenerator.generateSealedDeck(GuiBase.getInterface(), true);
if (sealed == null) { return; }
final ACEditorBase<? extends InventoryItem, T> editor = (ACEditorBase<? extends InventoryItem, T>) new CEditorLimited(

View File

@@ -142,7 +142,7 @@ public enum CSubmenuWinston implements ICDoc {
final LimitedPoolType poolType = GuiChoose.oneOrNone("Choose Draft Format", LimitedPoolType.values());
if (poolType == null) { return; }
WinstonDraft draft = WinstonDraft.createDraft(poolType);
WinstonDraft draft = WinstonDraft.createDraft(GuiBase.getInterface(), poolType);
if (draft == null) { return; }
final CEditorWinstonProcess draftController = new CEditorWinstonProcess();

View File

@@ -1,5 +1,6 @@
package forge.screens.home.settings;
import forge.GuiBase;
import forge.UiCommand;
import forge.download.GuiDownloadPicturesLQ;
import forge.download.GuiDownloadPrices;
@@ -37,7 +38,7 @@ public enum CSubmenuDownloaders implements ICDoc {
private final UiCommand cmdImportPictures = new UiCommand() { @Override
public void run() { new ImportDialog(null, null); } };
private final UiCommand cmdReportBug = new UiCommand() { @Override
public void run() { BugReporter.reportBug(null); }
public void run() { BugReporter.reportBug(GuiBase.getInterface(), null); }
};
/* (non-Javadoc)

View File

@@ -1,5 +1,6 @@
package forge.screens.home.settings;
import forge.GuiBase;
import forge.UiCommand;
import forge.Singletons;
import forge.ai.AiProfileUtil;
@@ -339,7 +340,7 @@ public enum CSubmenuPreferences implements ICDoc {
return new UiCommand() {
@Override
public void run() {
GamePlayerUtil.setPlayerName();
GamePlayerUtil.setPlayerName(GuiBase.getInterface());
setPlayerNameButtonText();
}
};

View File

@@ -34,6 +34,7 @@ import com.google.common.eventbus.EventBus;
import com.google.common.eventbus.Subscribe;
import forge.FThreads;
import forge.GuiBase;
import forge.ImageCache;
import forge.LobbyPlayer;
import forge.Singletons;
@@ -257,7 +258,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
}
final Object[] result = { null }; // how else can I extract a value from EDT thread?
FThreads.invokeInEdtAndWait(new Runnable() {
FThreads.invokeInEdtAndWait(GuiBase.getInterface(), new Runnable() {
@Override
public void run() {
VAssignDamage v = new VAssignDamage(attacker, blockers, damage, defender, overrideOrder);
@@ -285,7 +286,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
}
public void setCard(final CardView c, final boolean isInAltState) {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
CDetail.SINGLETON_INSTANCE.showCard(c, isInAltState);
CPicture.SINGLETON_INSTANCE.showCard(c, isInAltState);
}
@@ -335,7 +336,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
Set<CardView> highlightedCards = Sets.newHashSet();
// used to highlight cards in UI
public void setUsedToPay(CardView card, boolean value) {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
boolean hasChanged = value ? highlightedCards.add(card) : highlightedCards.remove(card);
if (hasChanged) { // since we are in UI thread, may redraw the card right now
@@ -417,7 +418,7 @@ public enum CMatchUI implements ICDoc, IMenuProvider {
// UI-related events should arrive here
public void fireEvent(UiEvent uiEvent) {
if (LOG_UIEVENTS) {
System.out.println("UI: " + uiEvent.toString() + " \t\t " + FThreads.debugGetStackTraceItem(4, true));
System.out.println("UI: " + uiEvent.toString() + " \t\t " + FThreads.debugGetStackTraceItem(GuiBase.getInterface(), 4, true));
}
uiEvents.post(uiEvent);
}

View File

@@ -27,6 +27,7 @@ import javax.swing.SwingConstants;
import net.miginfocom.swing.MigLayout;
import forge.assets.FSkinProp;
import forge.gauntlet.GauntletWinLoseController;
import forge.interfaces.IGuiBase;
import forge.toolbox.FLabel;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.SkinnedPanel;
@@ -45,9 +46,9 @@ public class GauntletWinLose extends ControlWinLose {
* @param view0 ViewWinLose object
* @param match
*/
public GauntletWinLose(final ViewWinLose view0, final IGameView game0) {
public GauntletWinLose(final ViewWinLose view0, final IGameView game0, final IGuiBase gui) {
super(view0, game0);
controller = new GauntletWinLoseController(view0, game0) {
controller = new GauntletWinLoseController(view0, game0, gui) {
@Override
protected void showOutcome(String message1, String message2, FSkinProp icon, List<String> lstEventNames, List<String> lstEventRecords, int len, int num) {
final JLabel lblTitle = new FLabel.Builder().text("Gauntlet Progress")

View File

@@ -21,6 +21,7 @@ import java.awt.Dimension;
import javax.swing.SwingConstants;
import forge.GuiBase;
import forge.limited.LimitedWinLoseController;
import forge.toolbox.FSkin;
import forge.toolbox.FSkin.Colors;
@@ -48,7 +49,7 @@ public class LimitedWinLose extends ControlWinLose {
*/
public LimitedWinLose(final ViewWinLose view0, final IGameView game0) {
super(view0, game0);
controller = new LimitedWinLoseController(view0, game0) {
controller = new LimitedWinLoseController(view0, game0, GuiBase.getInterface()) {
@Override
protected void showOutcome(Runnable runnable) {
runnable.run(); //just run on GUI thread

View File

@@ -102,10 +102,10 @@ public class QuestDraftWinLose extends ControlWinLose {
if (lastGame.isMatchOver()) {
this.actionOnQuitMatch();
QuestDraftUtils.matchInProgress = false;
QuestDraftUtils.update();
QuestDraftUtils.update(GuiBase.getInterface());
} else {
this.actionOnContinue();
QuestDraftUtils.update();
QuestDraftUtils.update(GuiBase.getInterface());
}
return false;
@@ -126,7 +126,7 @@ public class QuestDraftWinLose extends ControlWinLose {
public void actionPerformed(final ActionEvent e) {
GuiBase.getInterface().endCurrentGame();
QuestDraftUtils.matchInProgress = false;
QuestDraftUtils.continueMatches();
QuestDraftUtils.continueMatches(GuiBase.getInterface());
}
});
} else {
@@ -141,7 +141,7 @@ public class QuestDraftWinLose extends ControlWinLose {
if (FOptionPane.showOptionDialog("Quitting the match now will forfeit the tournament!\n\nReally quit?", "Really Quit Tournament?", FSkin.getImage(FSkinProp.ICO_WARNING).scale(2), new String[] { "Yes", "No" }, 1) == 0) {
GuiBase.getInterface().endCurrentGame();
QuestDraftUtils.matchInProgress = false;
QuestDraftUtils.continueMatches();
QuestDraftUtils.continueMatches(GuiBase.getInterface());
}
}
});

View File

@@ -21,6 +21,7 @@ import java.util.List;
import javax.swing.SwingConstants;
import forge.GuiBase;
import forge.assets.FSkinProp;
import forge.item.PaperCard;
import forge.model.FModel;
@@ -64,7 +65,7 @@ public class QuestWinLose extends ControlWinLose {
public QuestWinLose(final ViewWinLose view0, final IGameView game0) {
super(view0, game0);
view = view0;
controller = new QuestWinLoseController(game0) {
controller = new QuestWinLoseController(game0, GuiBase.getInterface()) {
@Override
protected void showRewards(Runnable runnable) {
runnable.run(); //just run on GUI thread

View File

@@ -14,6 +14,7 @@ import net.miginfocom.swing.MigLayout;
import org.apache.commons.lang3.StringUtils;
import forge.GuiBase;
import forge.LobbyPlayer;
import forge.UiCommand;
import forge.game.GameLogEntry;
@@ -68,14 +69,14 @@ public class ViewWinLose implements IWinLoseView<FButton> {
control = new QuestDraftWinLose(this, game0);
break;
case Draft:
if (!FModel.getGauntletMini().isGauntletDraft()) {
if (!FModel.getGauntletMini(GuiBase.getInterface()).isGauntletDraft()) {
break;
}
case Sealed:
control = new LimitedWinLose(this, game0);
break;
case Gauntlet:
control = new GauntletWinLose(this, game0);
control = new GauntletWinLose(this, game0, GuiBase.getInterface());
break;
default: // will catch it after switch
break;

View File

@@ -71,7 +71,7 @@ public enum CDock implements ICDoc {
SOverlayUtils.genericOverlay();
FView.SINGLETON_INSTANCE.getPnlContent().removeAll();
FThreads.invokeInEdtLater(new Runnable(){
FThreads.invokeInEdtLater(GuiBase.getInterface(), new Runnable(){
@Override public void run() {
SLayoutIO.loadLayout(null);
SOverlayUtils.hideOverlay();
@@ -101,7 +101,7 @@ public enum CDock implements ICDoc {
FView.SINGLETON_INSTANCE.getPnlContent().removeAll();
// let it redraw everything first
FThreads.invokeInEdtLater(new Runnable() {
FThreads.invokeInEdtLater(GuiBase.getInterface(), new Runnable() {
@Override
public void run() {
if (loadFile != null) {

View File

@@ -28,6 +28,7 @@ import javax.swing.JLayeredPane;
import javax.swing.SwingUtilities;
import forge.FThreads;
import forge.GuiBase;
import forge.Singletons;
import forge.UiCommand;
import forge.gui.framework.ICDoc;
@@ -79,7 +80,7 @@ public class CHand implements ICDoc {
}
public void update(final Observable a, final Object b) {
FThreads.invokeInEdtNowOrLater(updateRoutine);
FThreads.invokeInEdtNowOrLater(GuiBase.getInterface(), updateRoutine);
}
private final Runnable updateRoutine = new Runnable() {
@@ -87,7 +88,7 @@ public class CHand implements ICDoc {
};
public void updateHand() {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
final HandArea p = view.getHandArea();

View File

@@ -1,5 +1,6 @@
package forge.screens.match.controllers;
import forge.GuiBase;
import forge.UiCommand;
import forge.FThreads;
import forge.gui.framework.ICDoc;
@@ -66,7 +67,7 @@ public enum CLog implements ICDoc, Observer {
*/
@Override
public void update() {
FThreads.invokeInEdtNowOrLater(r);
FThreads.invokeInEdtNowOrLater(GuiBase.getInterface(), r);
}
}

View File

@@ -27,6 +27,7 @@ import java.awt.event.FocusListener;
import javax.swing.JButton;
import forge.FThreads;
import forge.GuiBase;
import forge.Singletons;
import forge.UiCommand;
import forge.gui.framework.ICDoc;
@@ -118,7 +119,7 @@ public enum CPrompt implements ICDoc {
*/
public void updateText() {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
final IGameView game = Singletons.getControl().getGameView();
final String text = String.format("T:%d G:%d/%d [%s]", game.getTurnNumber(), game.getNumPlayedGamesInMatch() + 1, game.getNumGamesInMatch(), game.getGameType());
view.getLblGames().setText(text);

View File

@@ -1,9 +1,16 @@
package forge.screens.match.menus;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.ButtonGroup;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import forge.Singletons;
import forge.assets.FSkinProp;
import forge.control.FControl;
import forge.match.MatchUtil;
import forge.menus.MenuUtil;
import forge.model.FModel;
import forge.properties.ForgePreferences;
@@ -11,13 +18,11 @@ import forge.properties.ForgePreferences.FPref;
import forge.screens.match.CMatchUI;
import forge.screens.match.VAutoYields;
import forge.screens.match.controllers.CDock;
import forge.toolbox.FSkin.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import forge.toolbox.FSkin.SkinIcon;
import forge.toolbox.FSkin.SkinnedCheckBoxMenuItem;
import forge.toolbox.FSkin.SkinnedMenu;
import forge.toolbox.FSkin.SkinnedMenuItem;
import forge.toolbox.FSkin.SkinnedRadioButtonMenuItem;
/**
* Returns a JMenu containing options associated with current game.
@@ -80,7 +85,7 @@ public final class GameMenu {
return new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
MatchUtil.undoLastAction();
Singletons.getControl().getGameView().tryUndoLastAction();
}
};
}

View File

@@ -1,6 +1,7 @@
package forge.toolbox;
import forge.FThreads;
import forge.GuiBase;
import forge.interfaces.IProgressBar;
import javax.swing.*;
@@ -36,7 +37,7 @@ public class FProgressBar extends JProgressBar implements IProgressBar {
* @param s0 &emsp; A description to prepend before statistics.
*/
public void setDescription(final String s0) {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
desc = s0;
setString(s0);
}
@@ -81,7 +82,7 @@ public class FProgressBar extends JProgressBar implements IProgressBar {
/** Resets the various values required for this class. Must be called from EDT. */
public void reset() {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
setIndeterminate(true);
setValue(0);
tempVal = 0;

View File

@@ -18,6 +18,7 @@
package forge.toolbox;
import forge.FThreads;
import forge.GuiBase;
import forge.Singletons;
import forge.assets.FSkinProp;
import forge.assets.ISkinImage;
@@ -981,7 +982,7 @@ public class FSkin {
public static void loadLight(final String skinName, final boolean onInit) {
if (onInit) {
// No need for this method to be loaded while on the EDT.
FThreads.assertExecutedByEdt(false);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), false);
if (allSkins == null) { //initialize
allSkins = new ArrayList<String>();
@@ -1053,7 +1054,7 @@ public class FSkin {
public static void loadFull(final boolean onInit) {
if (onInit) {
// No need for this method to be loaded while on the EDT.
FThreads.assertExecutedByEdt(false);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), false);
// Preferred skin name must be called via loadLight() method,
// which does some cleanup and init work.

View File

@@ -23,8 +23,6 @@ import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import forge.ImageCache;
import forge.card.CardCharacteristicName;
import forge.game.card.Card;
import forge.model.FModel;
import forge.properties.ForgePreferences;
import forge.toolbox.CardFaceSymbols;
@@ -37,36 +35,9 @@ import forge.view.CardView.CardStateView;
* @version $Id: FImageUtil.java 25265 2014-03-27 02:18:47Z drdev $
*
*/
public final class FImageUtil {
private FImageUtil() {}
public final class FImageUtil {
@Deprecated
public static BufferedImage getImage(Card card, CardCharacteristicName state) {
BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(state), true);
int foilIndex = card.getFoil();
if (image != null && foilIndex > 0) {
image = getImageWithFoilEffect(image, foilIndex);
}
return image;
}
/**
* Gets the image associated with a card.
* <p>
* Adds a random foil effect if enabled.
* <p>
* For double-sided cards, returns the front-side image.<br>
* For flip cards, returns the un-flipped image.
*/
@Deprecated
public static BufferedImage getImage(Card card) {
BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(), true);
int foilIndex = card.getFoil();
if (image != null && foilIndex > 0) {
image = getImageWithFoilEffect(image, foilIndex);
}
return image;
}
private FImageUtil() {}
/**
* Gets the image associated with a card.

View File

@@ -18,6 +18,7 @@
package forge.view;
import forge.FThreads;
import forge.GuiBase;
import forge.gui.SOverlayUtils;
import forge.screens.match.VMatchUI;
@@ -68,7 +69,7 @@ public class ButtonUtil {
// ensure we don't steal focus from an overlay
if (!SOverlayUtils.overlayHasFocus()) {
FThreads.invokeInEdtLater(new Runnable() { @Override public void run() { button.requestFocusInWindow(); } });
FThreads.invokeInEdtLater(GuiBase.getInterface(), new Runnable() { @Override public void run() { button.requestFocusInWindow(); } });
}
}

View File

@@ -21,7 +21,7 @@ import forge.util.Lang;
public class SimulateMatch {
public static void simulate(String[] args) {
FModel.initialize(null);
FModel.initialize(GuiBase.getInterface(), null);
System.out.println("Simulation mode");
if(args.length < 3 ) {

View File

@@ -30,6 +30,7 @@ import java.util.List;
import javax.swing.SwingUtilities;
import forge.FThreads;
import forge.GuiBase;
import forge.screens.match.CMatchUI;
import forge.toolbox.FScrollPane;
import forge.toolbox.FSkin.SkinnedPanel;
@@ -332,7 +333,7 @@ public abstract class CardPanelContainer extends SkinnedPanel {
* a {@link forge.view.arcane.CardPanel} object.
*/
public final void removeCardPanel(final CardPanel fromPanel) {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
if (CardPanelContainer.this.getMouseDragPanel() != null) {
CardPanel.getDragAnimationPanel().setVisible(false);
CardPanel.getDragAnimationPanel().repaint();
@@ -384,7 +385,7 @@ public abstract class CardPanelContainer extends SkinnedPanel {
* </p>
*/
public final void clear() {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
for (CardPanel p : CardPanelContainer.this.getCardPanels()) {
p.dispose();
}

View File

@@ -28,6 +28,7 @@ import java.util.List;
import com.google.common.collect.Lists;
import forge.FThreads;
import forge.GuiBase;
import forge.screens.match.CMatchUI;
import forge.screens.match.controllers.CPrompt;
import forge.toolbox.FScrollPane;
@@ -590,7 +591,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
* </p>
*/
public void setupPlayZone() {
FThreads.assertExecutedByEdt(true);
FThreads.assertExecutedByEdt(GuiBase.getInterface(), true);
recalculateCardPanels(model);
}

View File

@@ -3,6 +3,7 @@ package forge;
import forge.deck.CardPool;
import forge.limited.BoosterDraft;
import forge.limited.LimitedPoolType;
import org.testng.annotations.Test;
/**
@@ -19,7 +20,7 @@ public class BoosterDraft1Test {
*/
@Test(groups = { "UnitTest", "fast" }, timeOut = 1000, enabled = false)
public void boosterDraft1Test1() throws Exception {
final BoosterDraft draft = BoosterDraft.createDraft(LimitedPoolType.Full);
final BoosterDraft draft = BoosterDraft.createDraft(GuiBase.getInterface(), LimitedPoolType.Full);
if (draft == null) { return; }
while (draft.hasNextChoice()) {

View File

@@ -97,7 +97,7 @@ public class PlayerControllerForTests extends PlayerController {
public void playSpellAbilityNoStack(SpellAbility effectSA, boolean mayChoseNewTargets) {
//TODO: eventually (when the real code is refactored) this should be handled normally...
if (effectSA.getDescription().equals("At the beginning of your upkeep, if you have exactly 1 life, you win the game.")) {//test_104_2b_effect_may_state_that_player_wins_the_game
HumanPlay.playSpellAbilityNoStack(player, effectSA, !mayChoseNewTargets);
HumanPlay.playSpellAbilityNoStack(null, player, effectSA, !mayChoseNewTargets);
return;
}
SpellAbilityAi sai = SpellApiToAi.Converter.get(effectSA.getApi());
@@ -106,7 +106,7 @@ public class PlayerControllerForTests extends PlayerController {
(effectSA.getHostCard().getName().equals("Laboratory Maniac") && sai instanceof GameWinAi) ||
(effectSA.getHostCard().getName().equals("Nefarious Lich") && sai instanceof ChangeZoneAi)
) {//test_104_3f_if_a_player_would_win_and_lose_simultaneously_he_loses
HumanPlay.playSpellAbilityNoStack(player, effectSA, !mayChoseNewTargets);
HumanPlay.playSpellAbilityNoStack(null, player, effectSA, !mayChoseNewTargets);
return;
}
throw new IllegalStateException("Callers of this method currently assume that it performs extra functionality!");