diff --git a/forge-game/src/main/java/forge/game/phase/PhaseType.java b/forge-game/src/main/java/forge/game/phase/PhaseType.java index 15fda8e63d1..565f772f156 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseType.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseType.java @@ -44,7 +44,16 @@ public enum PhaseType { nameForScripts = name_for_scripts; } - + + public final boolean phaseforUpdateField() { + boolean result = + ((ALL_PHASES.indexOf(this) >= ALL_PHASES.indexOf(UNTAP) + && ALL_PHASES.indexOf(this) < ALL_PHASES.indexOf(COMBAT_FIRST_STRIKE_DAMAGE)) + || (ALL_PHASES.indexOf(this) >= ALL_PHASES.indexOf(MAIN2) + && ALL_PHASES.indexOf(this) < ALL_PHASES.indexOf(CLEANUP))); + return result; + } + public final boolean isAfter(final PhaseType phase) { return ALL_PHASES.indexOf(this) > ALL_PHASES.indexOf(phase); } diff --git a/forge-gui-mobile/src/forge/screens/match/MatchController.java b/forge-gui-mobile/src/forge/screens/match/MatchController.java index a2567da0eb6..433d75e8723 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchController.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchController.java @@ -125,8 +125,13 @@ public class MatchController extends AbstractGuiGame { @Override public void refreshField() { - for (final VPlayerPanel pnl : view.getPlayerPanels().values()) - pnl.getField().update(); + if(getGameView() == null) + return; + if(getGameView().getPhase() == null) + return; + if (getGameView().getPhase().phaseforUpdateField()) + for (final VPlayerPanel pnl : view.getPlayerPanels().values()) + pnl.getField().update(); } public boolean hotSeatMode() { diff --git a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java index a8c55e66404..bd61f09d006 100644 --- a/forge-gui-mobile/src/forge/screens/match/MatchScreen.java +++ b/forge-gui-mobile/src/forge/screens/match/MatchScreen.java @@ -378,9 +378,10 @@ public class MatchScreen extends FScreen { } //player if (is4Player() || is3Player()) { + int numplayers = is3Player() ? 3 : 4; for (final PlayerView p : game.getPlayers()) { if (combat.getAttackersOf(p).contains(attacker)) - TargetingOverlay.drawArrow(g, attacker, p); + TargetingOverlay.drawArrow(g, attacker, p, numplayers); } } } diff --git a/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java b/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java index b8113c3d0f9..3c28401be23 100644 --- a/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java +++ b/forge-gui-mobile/src/forge/screens/match/TargetingOverlay.java @@ -79,9 +79,9 @@ public class TargetingOverlay { CardAreaPanel.get(endCard).getTargetingArrowOrigin(), connects); } - public static void drawArrow(Graphics g, CardView startCard, PlayerView targetPlayer) { + public static void drawArrow(Graphics g, CardView startCard, PlayerView targetPlayer, int numplayers) { drawArrow(g, CardAreaPanel.get(startCard).getTargetingArrowOrigin(), - MatchController.getView().getPlayerPanel(targetPlayer).getAvatar().getTargetingArrowOrigin(), + MatchController.getView().getPlayerPanel(targetPlayer).getAvatar().getTargetingArrowOrigin(numplayers), ArcConnection.FoesAttacking); } public static void drawArrow(Graphics g, Vector2 start, CardView targetCard, ArcConnection connects) { diff --git a/forge-gui-mobile/src/forge/screens/match/views/VAvatar.java b/forge-gui-mobile/src/forge/screens/match/views/VAvatar.java index e8b112f01e3..57d1baaad5b 100644 --- a/forge-gui-mobile/src/forge/screens/match/views/VAvatar.java +++ b/forge-gui-mobile/src/forge/screens/match/views/VAvatar.java @@ -45,10 +45,15 @@ public class VAvatar extends FDisplayObject { } public Vector2 getTargetingArrowOrigin() { + return getTargetingArrowOrigin(2); + } + public Vector2 getTargetingArrowOrigin(int numplayers) { Vector2 origin = new Vector2(screenPos.x, screenPos.y); - origin.x += WIDTH * 0.75f; - if (origin.y < MatchController.getView().getHeight() / 2) { + float modx = numplayers > 2 ? 0.25f : 0.75f; + + origin.x += WIDTH * modx; + if (origin.y < MatchController.getView().getHeight() / numplayers) { origin.y += HEIGHT * 0.75f; //target bottom right corner if on top half of screen } else { diff --git a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java index 7532c244769..d48cbcca2ce 100644 --- a/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java +++ b/forge-gui/src/main/java/forge/control/FControlGameEventHandler.java @@ -96,10 +96,6 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { needPlayerControlUpdate = false; matchController.updatePlayerControl(); } - if (refreshFieldUpdate) { - refreshFieldUpdate = false; - matchController.refreshField(); - } synchronized (zonesUpdate) { if (!zonesUpdate.isEmpty()) { // Copy to prevent concurrency issues @@ -107,6 +103,10 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { zonesUpdate.clear(); } } + if (refreshFieldUpdate) { + refreshFieldUpdate = false; + matchController.refreshField(); + } if (gameOver) { gameOver = false; humanController.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete @@ -338,6 +338,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base { @Override public Void visit(final GameEventCardChangeZone event) { + if(event.to.getZoneType() == ZoneType.Battlefield) + refreshFieldUpdate = true; //pfps the change to the zones have already been performed with add and remove calls // this is only for playing a sound // updateZone(event.from); diff --git a/forge-gui/src/main/java/forge/match/AbstractGuiGame.java b/forge-gui/src/main/java/forge/match/AbstractGuiGame.java index 2e435e89a3a..bd8bff93ddf 100644 --- a/forge-gui/src/main/java/forge/match/AbstractGuiGame.java +++ b/forge-gui/src/main/java/forge/match/AbstractGuiGame.java @@ -9,6 +9,7 @@ import java.util.Set; import java.util.Timer; import java.util.TimerTask; +import forge.GuiBase; import forge.util.Localizer; import org.apache.commons.lang3.StringUtils; @@ -59,6 +60,15 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { player = TrackableTypes.PlayerViewType.lookup(player); //ensure we use the correct player if (hasLocalPlayers() && !isLocalPlayer(player)) { //add check if gameControllers is not empty + if(GuiBase.getInterface().isLibgdxPort()){//spectator is registered as localplayer bug on ai vs ai (after . + if (spectator != null){ //human vs ai game), then it loses "control" when you watch ai vs ai, + currentPlayer = null; //again, and vice versa, This is to prevent throwing error, lose control, + updateCurrentPlayer(null); //workaround fix on mayviewcards below is needed or it will bug the UI.. + gameControllers.clear(); + return; + } + } + throw new IllegalArgumentException(); } @@ -168,8 +178,22 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { if (!hasLocalPlayers()) { return true; //if not in game, card can be shown } - if (getGameController().mayLookAtAllCards()) { - return true; + if(GuiBase.getInterface().isLibgdxPort()){ + if(spectator!=null) { //workaround fix!! this is needed on above code or it will + gameControllers.remove(spectator); //bug the UI! remove spectator here since its must not be here... + return true; + } + try{ + if (getGameController().mayLookAtAllCards()) { // when it bugged here, the game thinks the spectator (null) + return true; // is the humancontroller here (maybe because there is an existing game thread???) + } + } catch (NullPointerException e){ + return true; // return true so it will work as normal + } + } else { + if (getGameController().mayLookAtAllCards()) { + return true; + } } return c.canBeShownToAny(getLocalPlayers()); } @@ -271,6 +295,7 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards { if (showConfirmDialog(Localizer.getInstance().getMessage("lblCloseGameSpectator"), Localizer.getInstance().getMessage("lblCloseGame"), Localizer.getInstance().getMessage("lblClose"), Localizer.getInstance().getMessage("lblCancel"))) { IGameController controller = spectator; spectator = null; //ensure we don't prompt again, including when calling nextGameDecision below + controller.selectButtonOk(); //pause controller.nextGameDecision(NextGameDecision.QUIT); } return false; //let logic above handle closing current screen diff --git a/forge-gui/src/main/java/forge/match/HostedMatch.java b/forge-gui/src/main/java/forge/match/HostedMatch.java index 84a4c43a494..4c71ebea9ce 100644 --- a/forge-gui/src/main/java/forge/match/HostedMatch.java +++ b/forge-gui/src/main/java/forge/match/HostedMatch.java @@ -216,13 +216,7 @@ public class HostedMatch { final IGuiGame gui = GuiBase.getInterface().getNewGuiGame(); gui.setGameView(null); //clear the view so when the game restarts again, it updates correctly gui.setGameView(gameView); - - final PlayerControllerHuman humanController = new WatchLocalGame(game, new LobbyPlayerHuman("Spectator"), gui); - game.subscribeToEvents(new FControlGameEventHandler(humanController)); - humanControllers.add(humanController); - gui.setSpectator(humanController); - - gui.openView(null); + registerSpectator(gui, new WatchLocalGame(game, new LobbyPlayerHuman("Spectator"), gui)); } //prompt user for player one name if needed @@ -276,9 +270,12 @@ public class HostedMatch { public void registerSpectator(final IGuiGame gui) { final PlayerControllerHuman humanController = new WatchLocalGame(game, null, gui); + registerSpectator(gui, humanController); + } + + public void registerSpectator(final IGuiGame gui, final PlayerControllerHuman humanController) { gui.setSpectator(humanController); gui.openView(null); - game.subscribeToEvents(new FControlGameEventHandler(humanController)); humanControllers.add(humanController); }