diff --git a/.gitattributes b/.gitattributes index 2ec5bc66e56..585e4386d1a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1064,6 +1064,7 @@ forge-gui-mobile/libs/gdx-sources.jar -text forge-gui-mobile/libs/gdx.jar -text forge-gui-mobile/pom.xml -text forge-gui-mobile/src/forge/Forge.java -text +forge-gui-mobile/src/forge/GuiMobile.java -text forge-gui-mobile/src/forge/assets/CardFaceSymbols.java -text forge-gui-mobile/src/forge/assets/FImage.java -text forge-gui-mobile/src/forge/assets/FSkin.java -text @@ -1129,37 +1130,8 @@ forge-gui-mobile/src/forge/screens/draft/DraftScreen.java -text forge-gui-mobile/src/forge/screens/guantlet/GuantletScreen.java -text forge-gui-mobile/src/forge/screens/home/HomeScreen.java -text forge-gui-mobile/src/forge/screens/match/FControl.java -text -forge-gui-mobile/src/forge/screens/match/FControlGameEventHandler.java -text -forge-gui-mobile/src/forge/screens/match/FControlGamePlayback.java -text +forge-gui-mobile/src/forge/screens/match/InputSelectCard.java -text forge-gui-mobile/src/forge/screens/match/MatchScreen.java -text -forge-gui-mobile/src/forge/screens/match/events/IUiEventVisitor.java -text -forge-gui-mobile/src/forge/screens/match/events/UiEvent.java -text -forge-gui-mobile/src/forge/screens/match/events/UiEventAttackerDeclared.java -text -forge-gui-mobile/src/forge/screens/match/events/UiEventBlockerAssigned.java -text -forge-gui-mobile/src/forge/screens/match/input/ButtonUtil.java -text -forge-gui-mobile/src/forge/screens/match/input/Input.java -text -forge-gui-mobile/src/forge/screens/match/input/InputAttack.java -text -forge-gui-mobile/src/forge/screens/match/input/InputBase.java -text -forge-gui-mobile/src/forge/screens/match/input/InputBlock.java -text -forge-gui-mobile/src/forge/screens/match/input/InputConfirm.java -text -forge-gui-mobile/src/forge/screens/match/input/InputConfirmMulligan.java -text -forge-gui-mobile/src/forge/screens/match/input/InputLockUI.java -text -forge-gui-mobile/src/forge/screens/match/input/InputPassPriority.java -text -forge-gui-mobile/src/forge/screens/match/input/InputPayMana.java -text -forge-gui-mobile/src/forge/screens/match/input/InputPayManaOfCostPayment.java -text -forge-gui-mobile/src/forge/screens/match/input/InputPayManaSimple.java -text -forge-gui-mobile/src/forge/screens/match/input/InputPayManaX.java -text -forge-gui-mobile/src/forge/screens/match/input/InputPlaybackControl.java -text -forge-gui-mobile/src/forge/screens/match/input/InputProliferate.java -text -forge-gui-mobile/src/forge/screens/match/input/InputProxy.java -text -forge-gui-mobile/src/forge/screens/match/input/InputQueue.java -text -forge-gui-mobile/src/forge/screens/match/input/InputSelectCardsForConvoke.java -text -forge-gui-mobile/src/forge/screens/match/input/InputSelectCardsFromList.java -text -forge-gui-mobile/src/forge/screens/match/input/InputSelectEntitiesFromList.java -text -forge-gui-mobile/src/forge/screens/match/input/InputSelectManyBase.java -text -forge-gui-mobile/src/forge/screens/match/input/InputSelectTargets.java -text -forge-gui-mobile/src/forge/screens/match/input/InputSynchronized.java -text -forge-gui-mobile/src/forge/screens/match/input/InputSyncronizedBase.java -text forge-gui-mobile/src/forge/screens/match/views/VAssignDamage.java -text forge-gui-mobile/src/forge/screens/match/views/VAvatar.java -text forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java -text diff --git a/forge-gui-mobile-dev/.project b/forge-gui-mobile-dev/.project index 4dd8ef11dcb..b5c1f308fec 100644 --- a/forge-gui-mobile-dev/.project +++ b/forge-gui-mobile-dev/.project @@ -20,13 +20,6 @@ org.eclipse.m2e.core.maven2Nature org.eclipse.jdt.core.javanature - - - assets - 2 - copy_PARENT/forge-gui/res - - copy_PARENT diff --git a/forge-gui-mobile/src/forge/Forge.java b/forge-gui-mobile/src/forge/Forge.java index c6718aded33..397b061e022 100644 --- a/forge-gui-mobile/src/forge/Forge.java +++ b/forge-gui-mobile/src/forge/Forge.java @@ -52,6 +52,7 @@ public class Forge implements ApplicationListener { } game = this; clipboard = clipboard0; + GuiBase.setInterface(new GuiMobile()); } @Override diff --git a/forge-gui-mobile/src/forge/GuiMobile.java b/forge-gui-mobile/src/forge/GuiMobile.java new file mode 100644 index 00000000000..80a281ea71d --- /dev/null +++ b/forge-gui-mobile/src/forge/GuiMobile.java @@ -0,0 +1,311 @@ +package forge; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang3.tuple.Pair; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.Texture; +import com.google.common.base.Function; + +import forge.assets.FSkin; +import forge.assets.FSkinProp; +import forge.assets.FTextureImage; +import forge.assets.ISkinImage; +import forge.deck.Deck; +import forge.deck.FDeckViewer; +import forge.error.BugReporter; +import forge.events.UiEvent; +import forge.game.Game; +import forge.game.GameEntity; +import forge.game.GameType; +import forge.game.card.Card; +import forge.game.combat.Combat; +import forge.game.event.GameEventTurnBegan; +import forge.game.phase.PhaseHandler; +import forge.game.phase.PhaseType; +import forge.game.player.LobbyPlayer; +import forge.game.player.Player; +import forge.game.player.RegisteredPlayer; +import forge.game.spellability.SpellAbility; +import forge.game.zone.ZoneType; +import forge.interfaces.IButton; +import forge.interfaces.IGuiBase; +import forge.item.PaperCard; +import forge.match.input.InputQueue; +import forge.screens.match.FControl; +import forge.screens.match.views.VPhaseIndicator.PhaseLabel; +import forge.screens.match.winlose.ViewWinLose; +import forge.toolbox.FOptionPane; +import forge.toolbox.GuiChoose; +import forge.util.ThreadUtil; + +public class GuiMobile implements IGuiBase { + @Override + public void invokeInEdtLater(Runnable proc) { + Gdx.app.postRunnable(proc); + } + + @Override + public void invokeInEdtAndWait(final Runnable proc) { + if (isGuiThread()) { + // Just run in the current thread. + proc.run(); + } + else { + //TODO + } + } + + @Override + public boolean isGuiThread() { + return !ThreadUtil.isGameThread(); + } + + @Override + public String getInstallRoot() { + switch (Gdx.app.getType()) { + case Desktop: + return "../forge-gui/"; + case Android: + break; + case Applet: + break; + case WebGL: + break; + case iOS: + break; + default: + break; + } + return ""; + } + + @Override + public String getAssetsDir() { + return "res/"; + } + + @Override + public boolean mayShowCard(Card card) { + return FControl.mayShowCard(card); + } + + @Override + public void reportBug(String details) { + BugReporter.reportBug(details); + } + + @Override + public void reportException(Throwable ex) { + BugReporter.reportException(ex); + } + + @Override + public void reportException(Throwable ex, String message) { + BugReporter.reportException(ex, message); + } + + @Override + public ISkinImage getUnskinnedIcon(String path) { + return new FTextureImage(new Texture(path)); + } + + @Override + public int showOptionDialog(String message, String title, FSkinProp icon, String[] options, int defaultOption) { + return FOptionPane.showOptionDialog(message, title, icon == null ? null : FSkin.getImages().get(icon), options, defaultOption); + } + + @Override + public T showInputDialog(String message, String title, FSkinProp icon, T initialInput, T[] inputOptions) { + return FOptionPane.showInputDialog(message, title, icon == null ? null : FSkin.getImages().get(icon), initialInput, inputOptions); + } + + @Override + public List getChoices(final String message, final int min, final int max, final Collection choices, final T selected, final Function display) { + return GuiChoose.getChoices(message, min, max, choices, selected, display); + } + + @Override + public List order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax, + final List sourceChoices, final List destChoices, final Card referenceCard, final boolean sideboardingMode) { + return GuiChoose.order(title, top, remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices, referenceCard, sideboardingMode); + } + + @Override + public void showCardList(final String title, final String message, final List list) { + Deck deck = new Deck(title + " - " + message); + deck.getMain().addAllFlat(list); + FDeckViewer.show(deck); + } + + @Override + public IButton getBtnOK() { + return FControl.getView().getPrompt().getBtnOk(); + } + + @Override + public IButton getBtnCancel() { + return FControl.getView().getPrompt().getBtnCancel(); + } + + @Override + public void focusButton(final IButton button) { + //not needed for mobile game + } + + @Override + public void flashIncorrectAction() { + //SDisplayUtil.remind(VPrompt.SINGLETON_INSTANCE); //TODO + } + + @Override + public void updatePhase() { + PhaseHandler pH = FControl.getGame().getPhaseHandler(); + Player p = pH.getPlayerTurn(); + PhaseType ph = pH.getPhase(); + + PhaseLabel lbl = FControl.getPlayerPanel(p).getPhaseIndicator().getLabel(ph); + + FControl.resetAllPhaseButtons(); + if (lbl != null) { + lbl.setActive(true); + } + } + + @Override + public void updateTurn(final GameEventTurnBegan event, final Game game) { + //VField nextField = FControl.getFieldViewFor(event.turnOwner); + //SDisplayUtil.showTab(nextField); + FControl.getView().getPrompt().updateText(game); + } + + @Override + public void updatePlayerControl() { + //TODO + } + + @Override + public void finishGame() { + new ViewWinLose(FControl.getGame()).setVisible(true); + } + + @Override + public void updateStack() { + FControl.getView().getStack().update(); + } + + @Override + public void startMatch(GameType gameType, List players) { + FControl.startMatch(gameType, players); + } + + @Override + public void setPanelSelection(Card c) { + //GuiUtils.setPanelSelection(c); //TODO + } + + @Override + public SpellAbility getAbilityToPlay(List abilities, Object triggerEvent) { + if (abilities.isEmpty()) { + return null; + } + if (abilities.size() == 1) { + return abilities.get(0); + } + return GuiChoose.oneOrNone("Choose ability to play", abilities); + } + + @Override + public void hear(LobbyPlayer player, String message) { + //FNetOverlay.SINGLETON_INSTANCE.addMessage(player.getName(), message); //TODO + } + + @Override + public int getAvatarCount() { + if (FSkin.isLoaded()) { + return FSkin.getAvatars().size(); + } + return 0; + } + + @Override + public void fireEvent(UiEvent e) { + FControl.fireEvent(e); + } + + @Override + public void setCard(Card card) { + FControl.setCard(card); + } + + @Override + public void showCombat(Combat combat) { + FControl.showCombat(combat); + } + + @Override + public void setUsedToPay(Card card, boolean b) { + FControl.setUsedToPay(card, b); + } + + @Override + public void setHighlighted(Player player, boolean b) { + FControl.setHighlighted(player, b); + } + + @Override + public void showPromptMessage(String message) { + FControl.showMessage(message); + } + + @Override + public boolean stopAtPhase(Player playerTurn, PhaseType phase) { + return FControl.stopAtPhase(playerTurn, phase); + } + + @Override + public InputQueue getInputQueue() { + return FControl.getInputQueue(); + } + + @Override + public Game getGame() { + return FControl.getGame(); + } + + @Override + public void updateZones(List> zonesToUpdate) { + FControl.updateZones(zonesToUpdate); + } + + @Override + public void updateCards(Set cardsToUpdate) { + FControl.updateCards(cardsToUpdate); + } + + @Override + public void updateManaPool(List manaPoolUpdate) { + FControl.updateManaPool(manaPoolUpdate); + } + + @Override + public void updateLives(List livesUpdate) { + FControl.updateLives(livesUpdate); + } + + @Override + public void endCurrentGame() { + FControl.endCurrentGame(); + } + + @Override + public Map getDamageToAssign(Card attacker, List blockers, + int damageDealt, GameEntity defender, boolean overrideOrder) { + return FControl.getDamageToAssign(attacker, blockers, + damageDealt, defender, overrideOrder); + } +} diff --git a/forge-gui-mobile/src/forge/assets/FImage.java b/forge-gui-mobile/src/forge/assets/FImage.java index d8fead1e944..34a09173618 100644 --- a/forge-gui-mobile/src/forge/assets/FImage.java +++ b/forge-gui-mobile/src/forge/assets/FImage.java @@ -2,7 +2,7 @@ package forge.assets; import forge.Forge.Graphics; -public interface FImage { +public interface FImage extends ISkinImage { float getWidth(); float getHeight(); void draw(Graphics g, float x, float y, float w, float h); diff --git a/forge-gui-mobile/src/forge/assets/FSkin.java b/forge-gui-mobile/src/forge/assets/FSkin.java index cb6c91b97ae..ac4260dea6b 100644 --- a/forge-gui-mobile/src/forge/assets/FSkin.java +++ b/forge-gui-mobile/src/forge/assets/FSkin.java @@ -7,7 +7,6 @@ import java.util.Map; import org.apache.commons.lang3.text.WordUtils; -import com.badlogic.gdx.Application.ApplicationType; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.graphics.Color; @@ -17,17 +16,13 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import forge.assets.FSkinImage.SourceFile; import forge.model.FModel; +import forge.properties.ForgeConstants; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; import forge.screens.SplashScreen; import forge.toolbox.FProgressBar; public class FSkin { - private static final String - FILE_SKINS_DIR = "skins/", - FILE_AVATAR_SPRITE = "sprite_avatars.png", - DEFAULT_DIR = FILE_SKINS_DIR + "default/"; - private static final Map images = new HashMap(); private static final Map avatars = new HashMap(); @@ -72,12 +67,12 @@ public class FSkin { // Non-default (preferred) skin name and dir. preferredName = skinName.toLowerCase().replace(' ', '_'); - preferredDir = FILE_SKINS_DIR + preferredName + "/"; + preferredDir = ForgeConstants.SKINS_DIR + preferredName + "/"; - FSkinTexture.BG_TEXTURE.load(preferredDir, DEFAULT_DIR); //load background texture early for splash screen + FSkinTexture.BG_TEXTURE.load(preferredDir, ForgeConstants.DEFAULT_SKINS_DIR); //load background texture early for splash screen if (splashScreen != null) { - final FileHandle f = Gdx.files.internal(preferredDir + "bg_splash.png"); + final FileHandle f = Gdx.files.local(preferredDir + "bg_splash.png"); if (!f.exists()) { if (!skinName.equals("default")) { FSkin.loadLight("default", splashScreen); @@ -138,12 +133,13 @@ public class FSkin { //FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("Processing image sprites: ", 5); // Grab and test various sprite files. - final FileHandle f1 = Gdx.files.internal(DEFAULT_DIR + SourceFile.ICONS.getFilename()); - final FileHandle f2 = Gdx.files.internal(preferredDir + SourceFile.ICONS.getFilename()); - final FileHandle f3 = Gdx.files.internal(DEFAULT_DIR + SourceFile.FOILS.getFilename()); - final FileHandle f4 = Gdx.files.internal(DEFAULT_DIR + FILE_AVATAR_SPRITE); - final FileHandle f5 = Gdx.files.internal(preferredDir + FILE_AVATAR_SPRITE); - final FileHandle f6 = Gdx.files.internal(DEFAULT_DIR + SourceFile.OLD_FOILS.getFilename()); + String defaultDir = ForgeConstants.DEFAULT_SKINS_DIR; + final FileHandle f1 = Gdx.files.local(defaultDir + SourceFile.ICONS.getFilename()); + final FileHandle f2 = Gdx.files.local(preferredDir + SourceFile.ICONS.getFilename()); + final FileHandle f3 = Gdx.files.local(defaultDir + SourceFile.FOILS.getFilename()); + final FileHandle f4 = Gdx.files.local(defaultDir + ForgeConstants.SPRITE_AVATARS_FILE); + final FileHandle f5 = Gdx.files.local(preferredDir + ForgeConstants.SPRITE_AVATARS_FILE); + final FileHandle f6 = Gdx.files.local(defaultDir + SourceFile.OLD_FOILS.getFilename()); try { textures.put(f1.path(), new Texture(f1)); @@ -168,9 +164,9 @@ public class FSkin { //load images for (FSkinImage image : FSkinImage.values()) { - image.load(preferredDir, DEFAULT_DIR, textures, preferredIcons); + image.load(preferredDir, ForgeConstants.DEFAULT_SKINS_DIR, textures, preferredIcons); } - FSkinTexture.BG_MATCH.load(preferredDir, DEFAULT_DIR); + FSkinTexture.BG_MATCH.load(preferredDir, ForgeConstants.DEFAULT_SKINS_DIR); //assemble avatar textures int counter = 0; @@ -302,13 +298,7 @@ public class FSkin { public static ArrayList getSkinDirectoryNames() { final ArrayList mySkins = new ArrayList(); - final FileHandle dir; - if (Gdx.app.getType() == ApplicationType.Desktop) { - dir = Gdx.files.internal("./bin/" + FILE_SKINS_DIR); //needed to iterate over directory for Desktop - } - else { - dir = Gdx.files.internal(FILE_SKINS_DIR); - } + final FileHandle dir = Gdx.files.local(ForgeConstants.SKINS_DIR); if (!dir.exists() || !dir.isDirectory()) { System.err.println("FSkin > can't find skins directory!"); } diff --git a/forge-gui-mobile/src/forge/screens/match/FControl.java b/forge-gui-mobile/src/forge/screens/match/FControl.java index 86309163375..cab765feb5a 100644 --- a/forge-gui-mobile/src/forge/screens/match/FControl.java +++ b/forge-gui-mobile/src/forge/screens/match/FControl.java @@ -22,6 +22,12 @@ import com.google.common.eventbus.Subscribe; import forge.FThreads; import forge.Forge; import forge.card.CardCharacteristicName; +import forge.control.FControlGameEventHandler; +import forge.control.FControlGamePlayback; +import forge.events.IUiEventVisitor; +import forge.events.UiEvent; +import forge.events.UiEventAttackerDeclared; +import forge.events.UiEventBlockerAssigned; import forge.game.Game; import forge.game.GameEntity; import forge.game.GameRules; @@ -41,16 +47,12 @@ import forge.game.player.RegisteredPlayer; import forge.game.trigger.TriggerType; import forge.game.zone.Zone; import forge.game.zone.ZoneType; +import forge.match.input.InputProxy; +import forge.match.input.InputQueue; import forge.model.FModel; import forge.net.FServer; import forge.properties.ForgePreferences; import forge.properties.ForgePreferences.FPref; -import forge.screens.match.events.IUiEventVisitor; -import forge.screens.match.events.UiEvent; -import forge.screens.match.events.UiEventAttackerDeclared; -import forge.screens.match.events.UiEventBlockerAssigned; -import forge.screens.match.input.InputProxy; -import forge.screens.match.input.InputQueue; import forge.screens.match.views.VAssignDamage; import forge.screens.match.views.VCardDisplayArea.CardAreaPanel; import forge.screens.match.views.VPhaseIndicator; diff --git a/forge-gui-mobile/src/forge/screens/match/FControlGameEventHandler.java b/forge-gui-mobile/src/forge/screens/match/FControlGameEventHandler.java deleted file mode 100644 index 7bd2a7def03..00000000000 --- a/forge-gui-mobile/src/forge/screens/match/FControlGameEventHandler.java +++ /dev/null @@ -1,388 +0,0 @@ -package forge.screens.match; - -import com.google.common.eventbus.Subscribe; - -import forge.FThreads; -import forge.game.Game; -import forge.game.card.Card; -import forge.game.event.*; -import forge.game.phase.PhaseHandler; -import forge.game.phase.PhaseType; -import forge.game.player.Player; -import forge.game.zone.PlayerZone; -import forge.game.zone.Zone; -import forge.game.zone.ZoneType; -import forge.net.FServer; -import forge.screens.match.views.VPhaseIndicator.PhaseLabel; -import forge.screens.match.winlose.ViewWinLose; -import forge.toolbox.GuiChoose; -import forge.util.Lang; -import forge.util.maps.MapOfLists; - -import org.apache.commons.lang3.tuple.Pair; - -import java.util.*; -import java.util.Map.Entry; -import java.util.concurrent.atomic.AtomicBoolean; - -public class FControlGameEventHandler extends IGameEventVisitor.Base { - public FControlGameEventHandler() { - } - - @Subscribe - public void receiveGameEvent(final GameEvent ev) { - ev.visit(this); - } - - private final AtomicBoolean phaseUpdPlanned = new AtomicBoolean(false); - @Override - public Void visit(final GameEventTurnPhase ev) { - if (phaseUpdPlanned.getAndSet(true)) return null; - - FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { - PhaseHandler pH = FControl.getGame().getPhaseHandler(); - Player p = pH.getPlayerTurn(); - PhaseType ph = pH.getPhase(); - - phaseUpdPlanned.set(false); - - PhaseLabel lbl = FControl.getPlayerPanel(p).getPhaseIndicator().getLabel(ph); - - FControl.resetAllPhaseButtons(); - if (lbl != null) { lbl.setActive(true); } - } }); - return null; - } - - /* (non-Javadoc) - * @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventPlayerPriority) - */ - private final AtomicBoolean combatUpdPlanned = new AtomicBoolean(false); - @Override - public Void visit(GameEventPlayerPriority event) { - if (combatUpdPlanned.getAndSet(true)) { return null; } - FThreads.invokeInEdtNowOrLater(new Runnable() { - @Override - public void run() { - combatUpdPlanned.set(false); - FControl.showCombat(FControl.getGame().getCombat()); - } - }); - return null; - } - - private final AtomicBoolean turnUpdPlanned = new AtomicBoolean(false); - @Override - public Void visit(final GameEventTurnBegan event) { - if (turnUpdPlanned.getAndSet(true)) { return null; } - - final Game game = FControl.getGame(); // to make sure control gets a correct game instance - FThreads.invokeInEdtNowOrLater(new Runnable() { - @Override - public void run() { - /*VField nextField = FControl.getFieldViewFor(event.turnOwner); - SDisplayUtil.showTab(nextField);*/ - - turnUpdPlanned.set(false); - FControl.getView().getPrompt().updateText(game); - } - }); - return null; - } - - @Override - public Void visit(GameEventAnteCardsSelected ev) { - // Require EDT here? - List options = new ArrayList(); - for (final Entry kv : ((GameEventAnteCardsSelected) ev).cards.entries()) { - options.add(" -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --"); - options.add(kv.getValue()); - } - GuiChoose.one("These cards were chosen to ante", options); - return null; - } - - @Override - public Void visit(GameEventPlayerControl ev) { - if (FControl.getGame().isGameOver()) { - return null; - } - - FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { - /*FControl.initHandViews(FServer.getLobby().getGuiPlayer()); - SLayoutIO.loadLayout(null); - VMatchUI.SINGLETON_INSTANCE.populate(); - for (VHand h : VMatchUI.SINGLETON_INSTANCE.getHands()) { - h.getLayoutControl().updateHand(); - }*/ - } }); - return null; - } - - private final Runnable unlockGameThreadOnGameOver = new Runnable() { - @Override - public void run() { - FControl.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete - } - }; - - @Override - public Void visit(GameEventGameOutcome ev) { - FThreads.invokeInEdtNowOrLater(unlockGameThreadOnGameOver); - return null; - } - - @Override - public Void visit(GameEventGameFinished ev) { - FThreads.invokeInEdtNowOrLater(new Runnable() { - @Override - public void run() { - new ViewWinLose(FControl.getGame()).setVisible(true); - } - }); - return null; - } - - private final AtomicBoolean stackUpdPlanned = new AtomicBoolean(false); - private final Runnable updStack = new Runnable() { - @Override - public void run() { - stackUpdPlanned.set(false); - FControl.getView().getStack().update(); - } - }; - - @Override - public Void visit(GameEventSpellAbilityCast event) { - if (!stackUpdPlanned.getAndSet(true)) { - FThreads.invokeInEdtNowOrLater(updStack); - } - return null; - } - @Override - public Void visit(GameEventSpellResolved event) { - if (!stackUpdPlanned.getAndSet(true)) { - FThreads.invokeInEdtNowOrLater(updStack); - } - return null; - } - @Override - public Void visit(GameEventSpellRemovedFromStack event) { - if (!stackUpdPlanned.getAndSet(true)) { - FThreads.invokeInEdtNowOrLater(updStack); - } - return null; - } - - private final List> zonesToUpdate = new Vector>(); - private final Runnable updZones = new Runnable() { - @Override public void run() { - synchronized (zonesToUpdate) { - FControl.updateZones(zonesToUpdate); - zonesToUpdate.clear(); - } - } - }; - - @Override - public Void visit(GameEventZone event) { - if (event.player != null) { - // anything except stack will get here - updateZone(Pair.of(event.player, event.zoneType)); - } - return null; - } - - @Override - public Void visit(GameEventCardAttachment event) { - // TODO Auto-generated method stub - Game game = event.equipment.getGame(); - PlayerZone zEq = (PlayerZone)game.getZoneOf(event.equipment); - if (event.oldEntiy instanceof Card) { - updateZone(game.getZoneOf((Card)event.oldEntiy)); - } - if (event.newTarget instanceof Card) { - updateZone(game.getZoneOf((Card)event.newTarget)); - } - return updateZone(zEq); - } - - private Void updateZone(Zone z) { - return updateZone(Pair.of(z.getPlayer(), z.getZoneType())); - } - - private Void updateZone(Pair kv) { - boolean needUpdate = false; - synchronized (zonesToUpdate) { - needUpdate = zonesToUpdate.isEmpty(); - if (!zonesToUpdate.contains(kv)) { - zonesToUpdate.add(kv); - } - } - if (needUpdate) { - FThreads.invokeInEdtNowOrLater(updZones); - } - return null; - } - - private final Set cardsToUpdate = new HashSet(); - private final Runnable updCards = new Runnable() { - @Override - public void run() { - synchronized (cardsToUpdate) { - FControl.updateCards(cardsToUpdate); - cardsToUpdate.clear(); - } - } - }; - - @Override - public Void visit(GameEventCardTapped event) { - return updateSingleCard(event.card); - } - - @Override - public Void visit(GameEventCardPhased event) { - return updateSingleCard(event.card); - } - - @Override - public Void visit(GameEventCardDamaged event) { - return updateSingleCard(event.card); - } - - @Override - public Void visit(GameEventCardCounters event) { - return updateSingleCard(event.card); - } - - @Override - public Void visit(GameEventBlockersDeclared event) { // This is to draw icons on blockers declared by AI - for (MapOfLists kv : event.blockers.values()) { - for (Collection blockers : kv.values()) { - updateManyCards(blockers); - } - } - return super.visit(event); - } - - @Override - public Void visit(GameEventAttackersDeclared event) { - // Skip redraw for GUI player? - if (event.player.getLobbyPlayer() == FServer.getLobby().getGuiPlayer()) { - return null; - } - - // Update all attackers. - // Although they might have been updated when they were apped, there could be someone with vigilance, not redrawn yet. - updateManyCards(event.attackersMap.values()); - - return super.visit(event); - } - - @Override - public Void visit(GameEventCombatEnded event) { - // This should remove sword/shield icons from combatants by the time game moves to M2 - updateManyCards(event.attackers); - updateManyCards(event.blockers); - return null; - } - - private Void updateSingleCard(Card c) { - boolean needUpdate = false; - synchronized (cardsToUpdate) { - needUpdate = cardsToUpdate.isEmpty(); - if (!cardsToUpdate.contains(c)) { - cardsToUpdate.add(c); - } - } - if (needUpdate) { - FThreads.invokeInEdtNowOrLater(updCards); - } - return null; - } - - private Void updateManyCards(Collection cc) { - boolean needUpdate = false; - synchronized (cardsToUpdate) { - needUpdate = cardsToUpdate.isEmpty(); - cardsToUpdate.addAll(cc); - } - if (needUpdate) { - FThreads.invokeInEdtNowOrLater(updCards); - } - return null; - } - - /* (non-Javadoc) - * @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventCardStatsChanged) - */ - @Override - public Void visit(GameEventCardStatsChanged event) { - // TODO Smart partial updates - return updateManyCards(event.cards); - } - - // Update manapool - private final List manaPoolUpdate = new Vector(); - private final Runnable updManaPool = new Runnable() { - @Override public void run() { - synchronized (manaPoolUpdate) { - FControl.updateManaPool(manaPoolUpdate); - manaPoolUpdate.clear(); - } - } - }; - - @Override - public Void visit(GameEventManaPool event) { - boolean invokeUpdate = false; - synchronized (manaPoolUpdate) { - if (!manaPoolUpdate.contains(event.player)) { - invokeUpdate = manaPoolUpdate.isEmpty(); - manaPoolUpdate.add(event.player); - } - } - if (invokeUpdate) - FThreads.invokeInEdtNowOrLater(updManaPool); - return null; - } - - // Update lives counters - private final List livesUpdate = new Vector(); - private final Runnable updLives = new Runnable() { - @Override public void run() { - synchronized (livesUpdate) { - FControl.updateLives(livesUpdate); - livesUpdate.clear(); - } - } - }; - @Override - public Void visit(GameEventPlayerLivesChanged event) { - boolean invokeUpdate = false; - synchronized (livesUpdate) { - if (!livesUpdate.contains(event.player)) { - invokeUpdate = livesUpdate.isEmpty(); - livesUpdate.add(event.player); - } - } - if (invokeUpdate) - FThreads.invokeInEdtNowOrLater(updLives); - return null; - } - - @Override - public Void visit(GameEventPlayerPoisoned event) { - boolean invokeUpdate = false; - synchronized (livesUpdate) { - if (!livesUpdate.contains(event.receiver)) { - invokeUpdate = livesUpdate.isEmpty(); - livesUpdate.add(event.receiver); - } - } - if (invokeUpdate) - FThreads.invokeInEdtNowOrLater(updLives); - return null; - } -} \ No newline at end of file diff --git a/forge-gui-mobile/src/forge/screens/match/FControlGamePlayback.java b/forge-gui-mobile/src/forge/screens/match/FControlGamePlayback.java deleted file mode 100644 index 6da9d9079af..00000000000 --- a/forge-gui-mobile/src/forge/screens/match/FControlGamePlayback.java +++ /dev/null @@ -1,176 +0,0 @@ -package forge.screens.match; - -import com.google.common.eventbus.Subscribe; - -import forge.FThreads; -import forge.game.event.*; -import forge.screens.match.input.InputPlaybackControl; - -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.atomic.AtomicBoolean; - -public class FControlGamePlayback extends IGameEventVisitor.Base { - private final InputPlaybackControl inputPlayback = new InputPlaybackControl(this); - private final AtomicBoolean paused = new AtomicBoolean(false); - - private final CyclicBarrier gameThreadPauser = new CyclicBarrier(2); - - public FControlGamePlayback() { - } - - @Subscribe - public void receiveGameEvent(final GameEvent ev) { ev.visit(this); } - - private int phasesDelay = 200; - private int combatDelay = 400; - private int castDelay = 400; - private int resolveDelay = 400; - - private boolean fasterPlayback = false; - - private void pauseForEvent(int delay) { - try { - Thread.sleep(fasterPlayback ? delay / 10 : delay); - } catch (InterruptedException e) { - // TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log. - e.printStackTrace(); - } - } - - @Override - public Void visit(GameEventBlockersDeclared event) { - pauseForEvent(combatDelay); - return super.visit(event); - } - - /* (non-Javadoc) - * @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventTurnPhase) - */ - @Override - public Void visit(GameEventTurnPhase ev) { - boolean isUiToStop = FControl.stopAtPhase(ev.playerTurn, ev.phase); - - switch(ev.phase) { - case COMBAT_END: - case COMBAT_DECLARE_ATTACKERS: - case COMBAT_DECLARE_BLOCKERS: - if (FControl.getGame().getPhaseHandler().inCombat()) { - pauseForEvent(combatDelay); - } - break; - default: - if (isUiToStop) { - pauseForEvent(phasesDelay); - } - break; - } - - return null; - } - - /* (non-Javadoc) - * @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventDuelFinished) - */ - @Override - public Void visit(GameEventGameFinished event) { - FControl.getInputQueue().removeInput(inputPlayback); - return null; - } - - @Override - public Void visit(GameEventGameStarted event) { - FControl.getInputQueue().setInput(inputPlayback); - return null; - } - - @Override - public Void visit(GameEventLandPlayed event) { - pauseForEvent(resolveDelay); - return super.visit(event); - } - - @Override - public Void visit(final GameEventSpellResolved event) { - FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { FControl.setCard(event.spell.getHostCard()); } }); - pauseForEvent(resolveDelay); - return null; - } - - /* (non-Javadoc) - * @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventSpellAbilityCast) - */ - @Override - public Void visit(final GameEventSpellAbilityCast event) { - FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { FControl.setCard(event.sa.getHostCard()); } }); - pauseForEvent(castDelay); - return null; - } - - /* (non-Javadoc) - * @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventPlayerPriority) - */ - @Override - public Void visit(GameEventPlayerPriority event) { - if (paused.get()) { - try { - inputPlayback.onGamePaused(); - gameThreadPauser.await(); - gameThreadPauser.reset(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (BrokenBarrierException e) { - e.printStackTrace(); - } - } - return null; - } - - public void onGameStopRequested() { - paused.set(false); - if (gameThreadPauser.getNumberWaiting() != 0) { - releaseGameThread(); - } - } - - private void releaseGameThread() { - // just need to run another thread through the barrier... not edt preferrably :) - - FControl.getGame().getAction().invoke(new Runnable() { - @Override - public void run() { - try { - gameThreadPauser.await(); - } catch (InterruptedException e) { - // TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log. - e.printStackTrace(); - } catch (BrokenBarrierException e) { - // TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log. - e.printStackTrace(); - } - } - }); - } - - public void resume() { - paused.set(false); - releaseGameThread(); - } - - public void pause() { - paused.set(true); - } - - public void singleStep() { - releaseGameThread(); - } - - /** - * TODO: Write javadoc for this method. - * @param isFast - */ - public void setSpeed(boolean isFast) { - fasterPlayback = isFast; - } - -} \ No newline at end of file diff --git a/forge-gui-mobile/src/forge/screens/match/InputSelectCard.java b/forge-gui-mobile/src/forge/screens/match/InputSelectCard.java new file mode 100644 index 00000000000..b3f3c120b5d --- /dev/null +++ b/forge-gui-mobile/src/forge/screens/match/InputSelectCard.java @@ -0,0 +1,41 @@ +package forge.screens.match; + +import java.util.ArrayList; +import java.util.List; + +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; +import forge.match.input.Input; +import forge.match.input.InputPassPriority; +import forge.toolbox.FCardZoom; +import forge.toolbox.FCardZoom.ZoomController; + +public class InputSelectCard { + private InputSelectCard() { + } + + public static void selectCard(Card card, List orderedCards) { + Input currentInput = FControl.getInputQueue().getInput(); + if (currentInput == null) { return; } + + List orderedCardOptions = new ArrayList(orderedCards); //copy list to allow it being modified + + if (currentInput instanceof InputPassPriority) { + FCardZoom.show("Select a spell/ability", card, orderedCardOptions, new ZoomController() { + @Override + public List getOptions(final Card card) { + return card.getAllPossibleAbilities(FControl.getCurrentPlayer(), true); + } + + @Override + public boolean selectOption(final Card card, final SpellAbility option) { + FControl.getInputProxy().selectAbility(option); + return true; //TODO: Avoid hiding card zoom when selecting mana abilities + } + }); + } + else { + FControl.getInputProxy().selectCard(card, null); + } + } +} diff --git a/forge-gui-mobile/src/forge/screens/match/events/IUiEventVisitor.java b/forge-gui-mobile/src/forge/screens/match/events/IUiEventVisitor.java deleted file mode 100644 index 099b57092b7..00000000000 --- a/forge-gui-mobile/src/forge/screens/match/events/IUiEventVisitor.java +++ /dev/null @@ -1,6 +0,0 @@ -package forge.screens.match.events; - -public interface IUiEventVisitor { - T visit(UiEventBlockerAssigned event); - T visit(UiEventAttackerDeclared event); -} \ No newline at end of file diff --git a/forge-gui-mobile/src/forge/screens/match/events/UiEvent.java b/forge-gui-mobile/src/forge/screens/match/events/UiEvent.java deleted file mode 100644 index 4f9fe1571bf..00000000000 --- a/forge-gui-mobile/src/forge/screens/match/events/UiEvent.java +++ /dev/null @@ -1,7 +0,0 @@ -package forge.screens.match.events; - - -public abstract class UiEvent { - - public abstract T visit(IUiEventVisitor visitor); -} \ No newline at end of file diff --git a/forge-gui-mobile/src/forge/screens/match/events/UiEventAttackerDeclared.java b/forge-gui-mobile/src/forge/screens/match/events/UiEventAttackerDeclared.java deleted file mode 100644 index 1c5f755d332..00000000000 --- a/forge-gui-mobile/src/forge/screens/match/events/UiEventAttackerDeclared.java +++ /dev/null @@ -1,32 +0,0 @@ -package forge.screens.match.events; - -import forge.game.GameEntity; -import forge.game.card.Card; - -/** - * TODO: Write javadoc for this type. - * - */ -public class UiEventAttackerDeclared extends UiEvent { - - public final Card attacker; - public final GameEntity defender; - - public UiEventAttackerDeclared(Card card, GameEntity currentDefender) { - attacker = card; - defender = currentDefender; - } - - @Override - public T visit(IUiEventVisitor visitor) { - return visitor.visit(this); - } - - /* (non-Javadoc) - * @see java.lang.Object#toString() - */ - @Override - public String toString() { - return attacker.toString() + ( defender == null ? " removed from combat" : " declared to attack " + defender.getName() ); - } -} diff --git a/forge-gui-mobile/src/forge/screens/match/events/UiEventBlockerAssigned.java b/forge-gui-mobile/src/forge/screens/match/events/UiEventBlockerAssigned.java deleted file mode 100644 index fdd68954614..00000000000 --- a/forge-gui-mobile/src/forge/screens/match/events/UiEventBlockerAssigned.java +++ /dev/null @@ -1,21 +0,0 @@ -package forge.screens.match.events; - -import forge.game.card.Card; - -public class UiEventBlockerAssigned extends UiEvent { - - public final Card blocker; - public final Card attackerBeingBlocked; - - public UiEventBlockerAssigned(Card card, Card currentAttacker) { - blocker = card; - attackerBeingBlocked = currentAttacker; - } - - @Override - public T visit(IUiEventVisitor visitor) { - return visitor.visit(this); - } - - -} \ No newline at end of file diff --git a/forge-gui-mobile/src/forge/screens/match/input/ButtonUtil.java b/forge-gui-mobile/src/forge/screens/match/input/ButtonUtil.java deleted file mode 100644 index d8a4164530a..00000000000 --- a/forge-gui-mobile/src/forge/screens/match/input/ButtonUtil.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Forge: Play Magic: the Gathering. - * Copyright (C) 2011 Forge Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package forge.screens.match.input; - -import forge.screens.match.FControl; -import forge.toolbox.FButton; - -/** - * Manages match UI OK/Cancel button enabling and focus - */ -public class ButtonUtil { - public static void setButtonText(String okLabel, String cancelLabel) { - getOk().setText(okLabel); - getCancel().setText(cancelLabel); - } - - public static void reset() { - disableAll(); - getOk().setText("OK"); - getCancel().setText("Cancel"); - } - - public static void enableAll() { - getOk().setEnabled(true); - getCancel().setEnabled(true); - } - - public static void disableAll() { - getOk().setEnabled(false); - getCancel().setEnabled(false); - } - - public static void enableOnlyOk() { - getOk().setEnabled(true); - getCancel().setEnabled(false); - } - - public static void enableOnlyCancel() { - getOk().setEnabled(false); - getCancel().setEnabled(true); - } - - private static FButton getOk() { - return FControl.getView().getPrompt().getBtnOk(); - } - - private static FButton getCancel() { - return FControl.getView().getPrompt().getBtnCancel(); - } -} diff --git a/forge-gui-mobile/src/forge/screens/match/input/Input.java b/forge-gui-mobile/src/forge/screens/match/input/Input.java deleted file mode 100644 index fd3c5f40f17..00000000000 --- a/forge-gui-mobile/src/forge/screens/match/input/Input.java +++ /dev/null @@ -1,24 +0,0 @@ -package forge.screens.match.input; - -import java.util.List; - -import forge.game.card.Card; -import forge.game.player.Player; -import forge.game.spellability.SpellAbility; - -public interface Input { - - // showMessage() is always the first method called - void showMessageInitial(); - - void selectCard(final Card card, final List orderedCardOptions); - - void selectAbility(final SpellAbility ab); - - void selectPlayer(final Player player); - - void selectButtonOK(); - - void selectButtonCancel(); - -} \ No newline at end of file diff --git a/forge-gui-mobile/src/forge/screens/match/input/InputAttack.java b/forge-gui-mobile/src/forge/screens/match/input/InputAttack.java deleted file mode 100644 index ed365434a2c..00000000000 --- a/forge-gui-mobile/src/forge/screens/match/input/InputAttack.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Forge: Play Magic: the Gathering. - * Copyright (C) 2011 Forge Team - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package forge.screens.match.input; - -import com.google.common.collect.Iterables; - -import forge.game.GameEntity; -import forge.game.ability.AbilityUtils; -import forge.game.card.Card; -import forge.game.card.CardPredicates; -import forge.game.combat.AttackingBand; -import forge.game.combat.Combat; -import forge.game.combat.CombatUtil; -import forge.game.player.Player; -import forge.game.zone.ZoneType; -import forge.screens.match.FControl; -import forge.screens.match.events.UiEventAttackerDeclared; -import forge.toolbox.FCardZoom; -import forge.toolbox.FCardZoom.ZoomController; - -import java.util.ArrayList; -import java.util.List; - -/** - *

- * InputAttack class. - *

- * - * @author Forge - * @version $Id: InputAttack.java 24769 2014-02-09 13:56:04Z Hellfish $ - */ -public class InputAttack extends InputSyncronizedBase { - /** Constant serialVersionUID=7849903731842214245L. */ - private static final long serialVersionUID = 7849903731842214245L; - - private final Combat combat; - private final List defenders; - private GameEntity currentDefender; - private final Player playerAttacks; - private final Player playerDeclares; - private AttackingBand activeBand = null; - - public InputAttack(Player attacks, Player declares, Combat combat) { - this.playerAttacks = attacks; - this.playerDeclares = declares; - this.combat = combat; - this.defenders = combat.getDefenders(); - } - - /** {@inheritDoc} */ - @Override - public final void showMessage() { - // TODO still seems to have some issues with multiple planeswalkers - - ButtonUtil.enableOnlyOk(); - - setCurrentDefender(defenders.isEmpty() ? null : defenders.get(0)); - - if ( null == currentDefender ) { - System.err.println("InputAttack has no potential defenders!"); - return; // should even throw here! - } - - List possibleAttackers = playerAttacks.getCardsIn(ZoneType.Battlefield); - for (Card c : Iterables.filter(possibleAttackers, CardPredicates.Presets.CREATURES)) { - if (c.hasKeyword("CARDNAME attacks each turn if able.")) { - for(GameEntity def : defenders ) { - if( CombatUtil.canAttack(c, def, combat) ) { - combat.addAttacker(c, currentDefender); - FControl.fireEvent(new UiEventAttackerDeclared(c, currentDefender)); - break; - } - } - } else if (c.hasStartOfKeyword("CARDNAME attacks specific player each combat if able")) { - final int i = c.getKeywordPosition("CARDNAME attacks specific player each combat if able"); - final String defined = c.getKeyword().get(i).split(":")[1]; - final Player player = AbilityUtils.getDefinedPlayers(c, defined, null).get(0); - if (player != null && CombatUtil.canAttack(c, player, combat)) { - combat.addAttacker(c, player); - FControl.fireEvent(new UiEventAttackerDeclared(c, player)); - } - } - } - } - - private void showCombat() { - // redraw sword icons - FControl.showCombat(combat); - } - - /** {@inheritDoc} */ - @Override - protected final void onOk() { - // TODO Add check to see if each must attack creature is attacking - // Propaganda costs could have been paid here. - setCurrentDefender(null); // remove highlights - activateBand(null); - stop(); - } - - @Override - protected final void onPlayerSelected(Player selected) { - if (defenders.contains(selected)) { - setCurrentDefender(selected); - } - else { - flashIncorrectAction(); // cannot attack that player - } - } - - public enum Option { - DECLARE_AS_ATTACKER("Declare as Attacker"), - REMOVE_FROM_COMBAT("Remove from Combat"), - ATTACK_THIS_DEFENDER("Attack this Defender"), - ACTIVATE_BAND("Activate Band"), - JOIN_BAND("Join Band"); - - private String text; - - private Option(String text0) { - text = text0; - } - - public String toString() { - return text; - } - } - - /** {@inheritDoc} */ - @Override - protected final void onCardSelected(final Card card, final List orderedCardOptions) { - FCardZoom.show(FControl.getView().getPrompt().getMessage(), - card, orderedCardOptions, new ZoomController