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 74d9a43d3b2..cadc1989067 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 @@ -38,6 +38,7 @@ import forge.screens.deckeditor.CDeckEditorUI; import forge.screens.deckeditor.controllers.CEditorCommander; import forge.screens.deckeditor.controllers.CEditorVariant; import forge.screens.home.sanctioned.AvatarSelector; +import forge.toolbox.FCheckBox; import forge.toolbox.FComboBox; import forge.toolbox.FComboBoxWrapper; import forge.toolbox.FLabel; @@ -71,6 +72,7 @@ public class PlayerPanel extends FPanel { private FRadioButton radioAi; private JCheckBoxMenuItem radioAiUseSimulation; private FRadioButton radioOpen; + private FCheckBox chkReady; private FComboBoxWrapper teamComboBox = new FComboBoxWrapper(); private FComboBoxWrapper aeTeamComboBox = new FComboBoxWrapper(); @@ -143,8 +145,10 @@ public class PlayerPanel extends FPanel { teamComboBox.addTo(this, variantBtnConstraints + ", pushx, growx, gaptop 5px"); aeTeamComboBox.addTo(this, variantBtnConstraints + ", pushx, growx, gaptop 5px"); + createReadyButtion(); if (allowNetworking) { - this.add(radioOpen, "cell 4 1, ax left, sx 2, wrap"); + this.add(radioOpen, "cell 4 1, ax left, sx 2"); + this.add(chkReady, "cell 5 1, ax left, sx 2, wrap"); } this.add(deckLabel, variantBtnConstraints + ", cell 0 2, sx 2, ax right"); @@ -192,6 +196,7 @@ public class PlayerPanel extends FPanel { nameRandomiser.setEnabled(mayEdit); deckLabel.setVisible(mayEdit); deckBtn.setVisible(mayEdit); + chkReady.setEnabled(mayEdit); closeBtn.setVisible(mayRemove); @@ -558,6 +563,15 @@ public class PlayerPanel extends FPanel { tempBtnGroup.add(radioOpen); } + private void createReadyButtion() { + chkReady = new FCheckBox("Ready"); + chkReady.addActionListener(new ActionListener() { + @Override public final void actionPerformed(final ActionEvent e) { + lobby.setReady(index, chkReady.isSelected()); + } + }); + } + /** * @param index */ @@ -713,6 +727,13 @@ public class PlayerPanel extends FPanel { aeTeamComboBox.unsuppressActionListeners(); } + public boolean isReady() { + return chkReady.isSelected(); + } + public void setIsReady(final boolean isReady) { + chkReady.setSelected(isReady); + } + 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 abe54e90e9b..6f08f45ea0e 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 @@ -23,7 +23,9 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import forge.AIOption; +import forge.GuiBase; import forge.UiCommand; +import forge.assets.FSkinProp; import forge.deck.CardPool; import forge.deck.Deck; import forge.deck.DeckProxy; @@ -238,6 +240,7 @@ public class VLobby implements IUpdateable { panel.setPlayerName(slot.getName()); panel.setAvatar(slot.getAvatarIndex()); panel.setTeam(slot.getTeam()); + panel.setIsReady(slot.isReady()); panel.setIsArchenemy(slot.isArchenemy()); panel.setUseAiSimulation(slot.getAiOptions().contains(AIOption.USE_SIMULATION)); panel.setMayEdit(lobby.mayEdit(i)); @@ -262,6 +265,16 @@ public class VLobby implements IUpdateable { this.playerChangeListener = listener; } + void setReady(final int index, final boolean ready) { + if (ready && decks[index] == null) { + GuiBase.getInterface().showOptionDialog("Select a deck before readying!", "Error", FSkinProp.ICO_WARNING, new String[] { "Ok" }, 0); + update(); + return; + } + + firePlayerChangeListener(index); + changePlayerFocus(index); + } void firePlayerChangeListener(final int index) { if (playerChangeListener != null) { playerChangeListener.update(index, getSlot(index)); @@ -289,7 +302,7 @@ public class VLobby implements IUpdateable { 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.getAiOptions()); + return UpdateLobbyPlayerEvent.create(panel.getType(), panel.getPlayerName(), panel.getAvatarIndex(), panel.getTeam(), panel.isArchenemy(), panel.isReady(), panel.getAiOptions()); } /** Builds the actual deck panel layouts for each player. diff --git a/forge-gui/src/main/java/forge/match/GameLobby.java b/forge-gui/src/main/java/forge/match/GameLobby.java index 49694b99883..79c473bba47 100644 --- a/forge-gui/src/main/java/forge/match/GameLobby.java +++ b/forge-gui/src/main/java/forge/match/GameLobby.java @@ -115,8 +115,8 @@ public abstract class GameLobby { } otherSlot.setIsArchenemy(becomesArchenemy); } - updateView(); } + updateView(); } public IGameController getController(final int index) { @@ -134,7 +134,8 @@ public abstract class GameLobby { public void addSlot() { final int newIndex = getNumberOfSlots(); - addSlot(new LobbySlot(allowNetworking ? LobbySlotType.OPEN : LobbySlotType.LOCAL, null, newIndex, newIndex, false, Collections.emptySet())); + final LobbySlotType type = allowNetworking ? LobbySlotType.OPEN : LobbySlotType.LOCAL; + addSlot(new LobbySlot(type, null, newIndex, newIndex, false, !allowNetworking, Collections.emptySet())); } protected final void addSlot(final LobbySlot slot) { if (data.slots.size() >= MAX_PLAYERS) { diff --git a/forge-gui/src/main/java/forge/match/LobbySlot.java b/forge-gui/src/main/java/forge/match/LobbySlot.java index 319e262ee6a..65df1aa5ddc 100644 --- a/forge-gui/src/main/java/forge/match/LobbySlot.java +++ b/forge-gui/src/main/java/forge/match/LobbySlot.java @@ -18,15 +18,17 @@ public final class LobbySlot implements Serializable { private int avatarIndex; private int team; private boolean isArchenemy; + private boolean isReady; private Deck deck; private ImmutableSet aiOptions; - public LobbySlot(final LobbySlotType type, final String name, final int avatarIndex, final int team, final boolean isArchenemy, final Set aiOptions) { + public LobbySlot(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.setAiOptions(aiOptions); } @@ -46,6 +48,9 @@ public final class LobbySlot implements Serializable { if (data.getArchenemy() != null) { setIsArchenemy(data.getArchenemy().booleanValue()); } + if (data.getReady() != null) { + setIsReady(data.getReady().booleanValue()); + } if (data.getAiOptions() != null) { setAiOptions(data.getAiOptions()); } @@ -91,6 +96,13 @@ public final class LobbySlot implements Serializable { this.isArchenemy = isArchenemy; } + public boolean isReady() { + return isReady; + } + public void setIsReady(final boolean isReady) { + this.isReady = isReady; + } + public Deck getDeck() { return deck; } diff --git a/forge-gui/src/main/java/forge/match/LocalLobby.java b/forge-gui/src/main/java/forge/match/LocalLobby.java index f3ee60556d2..edb982228bb 100644 --- a/forge-gui/src/main/java/forge/match/LocalLobby.java +++ b/forge-gui/src/main/java/forge/match/LocalLobby.java @@ -15,10 +15,10 @@ public final class LocalLobby extends GameLobby { final String humanName = localName(); final int[] avatarIndices = localAvatarIndices(); - final LobbySlot slot0 = new LobbySlot(LobbySlotType.LOCAL, humanName, avatarIndices[0], 0, true, Collections.emptySet()); + final LobbySlot slot0 = new LobbySlot(LobbySlotType.LOCAL, humanName, avatarIndices[0], 0, true, true, Collections.emptySet()); addSlot(slot0); - final LobbySlot slot1 = new LobbySlot(LobbySlotType.AI, null, avatarIndices[1], 1, false, Collections.emptySet()); + final LobbySlot slot1 = new LobbySlot(LobbySlotType.AI, null, avatarIndices[1], 1, false, true, Collections.emptySet()); addSlot(slot1); } diff --git a/forge-gui/src/main/java/forge/net/ServerGameLobby.java b/forge-gui/src/main/java/forge/net/ServerGameLobby.java index 21f55ab8352..aed7320aea6 100644 --- a/forge-gui/src/main/java/forge/net/ServerGameLobby.java +++ b/forge-gui/src/main/java/forge/net/ServerGameLobby.java @@ -14,8 +14,8 @@ public final class ServerGameLobby extends GameLobby { public ServerGameLobby() { super(true); - addSlot(new LobbySlot(LobbySlotType.LOCAL, localName(), localAvatarIndices()[0], 0, true, Collections.emptySet())); - addSlot(new LobbySlot(LobbySlotType.OPEN, null, -1, 1, false, Collections.emptySet())); + addSlot(new LobbySlot(LobbySlotType.LOCAL, localName(), localAvatarIndices()[0], 0, true, false, Collections.emptySet())); + addSlot(new LobbySlot(LobbySlotType.OPEN, null, -1, 1, false, false, Collections.emptySet())); } public int connectPlayer(final String name, final int avatarIndex) { diff --git a/forge-net/src/main/java/forge/net/game/UpdateLobbyPlayerEvent.java b/forge-net/src/main/java/forge/net/game/UpdateLobbyPlayerEvent.java index 3a93b88820e..b69ed5ea718 100644 --- a/forge-net/src/main/java/forge/net/game/UpdateLobbyPlayerEvent.java +++ b/forge-net/src/main/java/forge/net/game/UpdateLobbyPlayerEvent.java @@ -17,27 +17,29 @@ public final class UpdateLobbyPlayerEvent implements NetEvent { 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 Set aiOptions) { - return new UpdateLobbyPlayerEvent(type, name, avatarIndex, team, isArchenemy, null, null, null, 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); } public static UpdateLobbyPlayerEvent deckUpdate(final Deck deck) { - return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, deck, null, null, null); + return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, null, deck, null, null, null); } public static UpdateLobbyPlayerEvent deckUpdate(final DeckSection section, final CardPool cards) { - return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, null, section, cards, null); + return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, null, null, section, cards, null); } - private UpdateLobbyPlayerEvent(final LobbySlotType type, final String name, final int avatarIndex, final int team, final Boolean isArchenemy, final Deck deck, final DeckSection section, final CardPool cards, final Set aiOptions) { + 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) { 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; @@ -62,6 +64,9 @@ public final class UpdateLobbyPlayerEvent implements NetEvent { public Boolean getArchenemy() { return isArchenemy; } + public Boolean getReady() { + return isReady; + } public Deck getDeck() { return deck; }