From 7615f333e159dcdb7c40ccbceb6d2ec1161f99be Mon Sep 17 00:00:00 2001 From: "Jamin W. Collins" Date: Tue, 6 Mar 2018 17:39:39 -0700 Subject: [PATCH] disclose and enforce DEV_MODE state in network play Signed-off-by: Jamin W. Collins --- .../java/forge/screens/home/PlayerPanel.java | 44 +++++++++++ .../main/java/forge/screens/home/VLobby.java | 13 +++- .../home/settings/CSubmenuPreferences.java | 6 ++ .../src/main/java/forge/match/GameLobby.java | 4 + .../src/main/java/forge/match/LobbySlot.java | 15 +++- .../net/event/UpdateLobbyPlayerEvent.java | 76 ++++++++++++++----- .../java/forge/net/server/FServerManager.java | 4 + 7 files changed, 142 insertions(+), 20 deletions(-) diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java b/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java index 50a4ae31fcd..2a54a8b6efd 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java @@ -98,6 +98,10 @@ public class PlayerPanel extends FPanel { private final FLabel vgdSelectorBtn = new FLabel.ButtonBuilder().text("Select a Vanguard avatar").build(); private final FLabel vgdLabel; + private FCheckBox chkDevMode; + + private boolean allowNetworking; + private final VLobby lobby; public PlayerPanel(final VLobby lobby, final boolean allowNetworking, final int index, final LobbySlot slot, final boolean mayEdit, final boolean mayControl) { super(); @@ -106,6 +110,7 @@ public class PlayerPanel extends FPanel { this.index = index; this.mayEdit = mayEdit; this.mayControl = mayControl; + this.allowNetworking = allowNetworking; this.deckLabel = lobby.newLabel("Deck:"); this.scmLabel = lobby.newLabel("Scheme deck:"); @@ -179,6 +184,11 @@ public class PlayerPanel extends FPanel { } }); + if (isNetworkHost()) { + createDevModeButton(); + this.add(chkDevMode); + } + this.type = slot == null ? LobbySlotType.LOCAL : slot.getType(); this.setPlayerName(slot == null ? "" : slot.getName()); this.setAvatarIndex(slot == null ? 0 : slot.getAvatarIndex()); @@ -186,6 +196,10 @@ public class PlayerPanel extends FPanel { update(); } + boolean isNetworkHost() { + return this.allowNetworking && this.index == 0; + } + void update() { avatarLabel.setEnabled(mayEdit); avatarLabel.setIcon(FSkin.getAvatars().get(Integer.valueOf(type == LobbySlotType.OPEN ? -1 : avatarIndex))); @@ -200,6 +214,10 @@ public class PlayerPanel extends FPanel { chkReady.setVisible(type == LobbySlotType.LOCAL || type == LobbySlotType.REMOTE); chkReady.setEnabled(mayEdit); + if (chkDevMode != null) { + chkDevMode.setEnabled(mayEdit); + } + closeBtn.setVisible(mayRemove); if (mayRemove) { @@ -585,6 +603,23 @@ public class PlayerPanel extends FPanel { }); } + private void createDevModeButton() { + chkDevMode = new FCheckBox("Dev Mode"); + + chkDevMode.addActionListener(new ActionListener() { + @Override public final void actionPerformed(final ActionEvent e) { + final boolean toggle = chkDevMode.isSelected(); + prefs.setPref(FPref.DEV_MODE_ENABLED, String.valueOf(toggle)); + ForgePreferences.DEV_MODE = toggle; + + // ensure that preferences panel reflects the change + prefs.save(); + + lobby.setDevMode(index); + } + }); + } + /** * @param index */ @@ -747,6 +782,15 @@ public class PlayerPanel extends FPanel { chkReady.setSelected(isReady); } + public boolean isDevMode() { + return chkDevMode != null && chkDevMode.isSelected(); + } + public void setIsDevMode(final boolean isDevMode) { + if (chkDevMode != null) { + chkDevMode.setSelected(isDevMode); + } + } + public void setMayEdit(final boolean mayEdit) { this.mayEdit = mayEdit; } diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java b/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java index 0cbfbfc6590..02732999231 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java @@ -275,6 +275,7 @@ public class VLobby implements ILobbyView { commanderDeckChooser.restoreSavedState(); tinyLeaderDeckChooser.restoreSavedState(); if (i == 0) { + slot.setIsDevMode(prefs.getPrefBoolean(FPref.DEV_MODE_ENABLED)); changePlayerFocus(0); } isNewPanel = true; @@ -286,6 +287,7 @@ public class VLobby implements ILobbyView { panel.setAvatarIndex(slot.getAvatarIndex()); panel.setTeam(slot.getTeam()); panel.setIsReady(slot.isReady()); + panel.setIsDevMode(slot.isDevMode()); panel.setIsArchenemy(slot.isArchenemy()); panel.setUseAiSimulation(slot.getAiOptions().contains(AIOption.USE_SIMULATION)); panel.setMayEdit(lobby.mayEdit(i)); @@ -331,6 +333,15 @@ public class VLobby implements ILobbyView { firePlayerChangeListener(index); changePlayerFocus(index); } + void setDevMode(final int index) { + // clear ready for everyone + for (int i = 0; i < activePlayersNum; i++) { + final PlayerPanel panel = playerPanels.get(i); + panel.setIsReady(false); + firePlayerChangeListener(i); + } + changePlayerFocus(index); + } void firePlayerChangeListener(final int index) { if (playerChangeListener != null) { playerChangeListener.update(index, getSlot(index)); @@ -361,7 +372,7 @@ public class VLobby implements ILobbyView { private UpdateLobbyPlayerEvent getSlot(final int index) { final PlayerPanel panel = playerPanels.get(index); - return UpdateLobbyPlayerEvent.create(panel.getType(), panel.getPlayerName(), panel.getAvatarIndex(), panel.getTeam(), panel.isArchenemy(), panel.isReady(), panel.getAiOptions()); + return UpdateLobbyPlayerEvent.create(panel.getType(), panel.getPlayerName(), panel.getAvatarIndex(), panel.getTeam(), panel.isArchenemy(), panel.isReady(), panel.isDevMode(), panel.getAiOptions()); } /** Builds the actual deck panel layouts for each player. diff --git a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java index 883c5843003..21c5ba5e069 100644 --- a/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java +++ b/forge-gui-desktop/src/main/java/forge/screens/home/settings/CSubmenuPreferences.java @@ -8,6 +8,7 @@ import forge.game.GameLogEntryType; import forge.gui.framework.FScreen; import forge.gui.framework.ICDoc; import forge.model.FModel; +import forge.net.server.FServerManager; import forge.player.GamePlayerUtil; import forge.properties.ForgeConstants; import forge.properties.ForgePreferences; @@ -63,6 +64,11 @@ public enum CSubmenuPreferences implements ICDoc { @Override public void itemStateChanged(final ItemEvent arg0) { if (updating) { return; } + // prevent changing DEV_MODE while network game running + if (FServerManager.getInstance().isMatchActive()) { + System.out.println("Can't change DEV_MODE while a network match is in progress!"); + return; + } final boolean toggle = view.getCbDevMode().isSelected(); prefs.setPref(FPref.DEV_MODE_ENABLED, String.valueOf(toggle)); diff --git a/forge-gui/src/main/java/forge/match/GameLobby.java b/forge-gui/src/main/java/forge/match/GameLobby.java index 097705ed545..4599efce415 100644 --- a/forge-gui/src/main/java/forge/match/GameLobby.java +++ b/forge-gui/src/main/java/forge/match/GameLobby.java @@ -60,6 +60,10 @@ public abstract class GameLobby implements IHasGameType { return allowNetworking; } + public final boolean isMatchActive() { + return hostedMatch != null && hostedMatch.isMatchOver() == false; + } + public void setListener(final IUpdateable listener) { this.listener = listener; } diff --git a/forge-gui/src/main/java/forge/match/LobbySlot.java b/forge-gui/src/main/java/forge/match/LobbySlot.java index 462ca739f78..9deb226fe04 100644 --- a/forge-gui/src/main/java/forge/match/LobbySlot.java +++ b/forge-gui/src/main/java/forge/match/LobbySlot.java @@ -10,7 +10,7 @@ import forge.deck.Deck; import forge.net.event.UpdateLobbyPlayerEvent; public final class LobbySlot implements Serializable { - private static final long serialVersionUID = 6918205436608794289L; + private static final long serialVersionUID = 9203252798721142264L; private LobbySlotType type; private String name; @@ -18,6 +18,7 @@ public final class LobbySlot implements Serializable { private int team; private boolean isArchenemy; private boolean isReady; + private boolean isDevMode; private Deck deck; private ImmutableSet aiOptions; @@ -28,6 +29,7 @@ public final class LobbySlot implements Serializable { this.team = team; this.isArchenemy = isArchenemy; this.isReady = isReady; + this.isDevMode = false; this.setAiOptions(aiOptions); } @@ -57,6 +59,10 @@ public final class LobbySlot implements Serializable { setIsReady(data.getReady().booleanValue()); changed = true; } + if (data.getDevMode() != null) { + setIsDevMode(data.getDevMode().booleanValue()); + changed = true; + } if (data.getAiOptions() != null) { setAiOptions(data.getAiOptions()); changed = true; @@ -112,6 +118,13 @@ public final class LobbySlot implements Serializable { this.isReady = isReady; } + public boolean isDevMode() { + return isDevMode; + } + public void setIsDevMode(final boolean isDevMode) { + this.isDevMode = isDevMode; + } + public Deck getDeck() { return deck; } diff --git a/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java b/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java index 8e8045eb8b7..59f0eb7baa1 100644 --- a/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java +++ b/forge-gui/src/main/java/forge/net/event/UpdateLobbyPlayerEvent.java @@ -11,39 +11,76 @@ import forge.match.LobbySlotType; import forge.net.server.RemoteClient; public final class UpdateLobbyPlayerEvent implements NetEvent { - private static final long serialVersionUID = -5073305607515425968L; + private static final long serialVersionUID = -7354695008599789571L; + + private LobbySlotType type = null; + private String name = null; + private int avatarIndex = -1; + private int team = -1; + private Boolean isArchenemy = null; + private Boolean isReady = null; + private Boolean isDevMode = null; + private Deck deck = null; + private DeckSection section = null; + private CardPool cards = null; + private Set aiOptions = null; - private final LobbySlotType type; - private final String name; - private final int avatarIndex; - private final int team; - private final Boolean isArchenemy; - private final Boolean isReady; - private final Deck deck; - private final DeckSection section; - private final CardPool cards; - private final Set aiOptions; public static UpdateLobbyPlayerEvent create(final LobbySlotType type, final String name, final int avatarIndex, final int team, final boolean isArchenemy, final boolean isReady, final Set aiOptions) { - return new UpdateLobbyPlayerEvent(type, name, avatarIndex, team, isArchenemy, isReady, null, null, null, aiOptions); + return new UpdateLobbyPlayerEvent(type, name, avatarIndex, team, isArchenemy, isReady, aiOptions); + } + public static UpdateLobbyPlayerEvent create(final LobbySlotType type, final String name, final int avatarIndex, final int team, final boolean isArchenemy, final boolean isReady, final boolean isDevMode, final Set aiOptions) { + return new UpdateLobbyPlayerEvent(type, name, avatarIndex, team, isArchenemy, isReady, isDevMode, aiOptions); } public static UpdateLobbyPlayerEvent deckUpdate(final Deck deck) { - return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, null, deck, null, null, null); + return new UpdateLobbyPlayerEvent(deck); } public static UpdateLobbyPlayerEvent deckUpdate(final DeckSection section, final CardPool cards) { - return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, null, null, section, cards, null); + return new UpdateLobbyPlayerEvent(section, cards); } - private UpdateLobbyPlayerEvent(final LobbySlotType type, final String name, final int avatarIndex, final int team, final Boolean isArchenemy, final Boolean isReady, final Deck deck, final DeckSection section, final CardPool cards, final Set aiOptions) { + private UpdateLobbyPlayerEvent(final Deck deck) { + this.deck = deck; + } + + private UpdateLobbyPlayerEvent(final DeckSection section, final CardPool cards) { + this.section = section; + this.cards = cards; + } + + private UpdateLobbyPlayerEvent( + final LobbySlotType type, + final String name, + final int avatarIndex, + final int team, + final boolean isArchenemy, + final boolean isReady, + final Set aiOptions) { this.type = type; this.name = name; this.avatarIndex = avatarIndex; this.team = team; this.isArchenemy = isArchenemy; this.isReady = isReady; - this.deck = deck; - this.section = section; - this.cards = cards; + this.aiOptions = aiOptions; + } + + private UpdateLobbyPlayerEvent( + final LobbySlotType type, + final String name, + final int avatarIndex, + final int team, + final boolean isArchenemy, + final boolean isReady, + final boolean isDevMode, + final Set aiOptions) { + this.type = type; + this.name = name; + this.avatarIndex = avatarIndex; + this.team = team; + this.isArchenemy = isArchenemy; + this.isReady = isReady; + this.isDevMode = isDevMode; this.aiOptions = aiOptions; } @@ -69,6 +106,9 @@ public final class UpdateLobbyPlayerEvent implements NetEvent { public Boolean getReady() { return isReady; } + public Boolean getDevMode() { + return isDevMode; + } public Deck getDeck() { return deck; } diff --git a/forge-gui/src/main/java/forge/net/server/FServerManager.java b/forge-gui/src/main/java/forge/net/server/FServerManager.java index ed71661eff8..c5af180361c 100644 --- a/forge-gui/src/main/java/forge/net/server/FServerManager.java +++ b/forge-gui/src/main/java/forge/net/server/FServerManager.java @@ -185,6 +185,10 @@ public final class FServerManager { this.localLobby = lobby; } + public boolean isMatchActive() { + return this.localLobby != null && this.localLobby.isMatchActive(); + } + public void setLobbyListener(final ILobbyListener listener) { this.lobbyListener = listener; }