mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
Start fleshing out network support. Preliminary support for:
- Network communication (both chat and game data); - Lobby including remote players. Long way to go before actually starting a network game, but we're getting there!
This commit is contained in:
26
.gitattributes
vendored
26
.gitattributes
vendored
@@ -928,15 +928,18 @@ forge-gui-desktop/src/main/java/forge/screens/deckeditor/views/VDeckgen.java -te
|
|||||||
forge-gui-desktop/src/main/java/forge/screens/deckeditor/views/VProbabilities.java -text
|
forge-gui-desktop/src/main/java/forge/screens/deckeditor/views/VProbabilities.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/deckeditor/views/VStatistics.java -text
|
forge-gui-desktop/src/main/java/forge/screens/deckeditor/views/VStatistics.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/CHomeUI.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/CHomeUI.java -text
|
||||||
|
forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/EMenuGroup.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/EMenuGroup.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/EMenuItem.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/EMenuItem.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/IVSubmenu.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/IVSubmenu.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/LblGroup.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/LblGroup.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/LblHeader.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/LblHeader.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/LblMenuItem.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/LblMenuItem.java -text
|
||||||
|
forge-gui-desktop/src/main/java/forge/screens/home/PlayerPanel.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/PnlGroup.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/PnlGroup.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/StartButton.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/StartButton.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/VHomeUI.java -text
|
||||||
|
forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/CSubmenuGauntletBuild.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/CSubmenuGauntletBuild.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/CSubmenuGauntletContests.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/CSubmenuGauntletContests.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/CSubmenuGauntletLoad.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/CSubmenuGauntletLoad.java -text
|
||||||
@@ -947,7 +950,9 @@ forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletBuil
|
|||||||
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletContests.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletContests.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletLoad.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletLoad.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletQuick.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/gauntlet/VSubmenuGauntletQuick.java -text
|
||||||
|
forge-gui-desktop/src/main/java/forge/screens/home/online/COnlineLobby.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/online/CSubmenuOnlineLobby.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/online/CSubmenuOnlineLobby.java -text
|
||||||
|
forge-gui-desktop/src/main/java/forge/screens/home/online/VOnlineLobby.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/online/VSubmenuOnlineLobby.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/online/VSubmenuOnlineLobby.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/package-info.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/package-info.java -text
|
||||||
forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuChallenges.java -text
|
forge-gui-desktop/src/main/java/forge/screens/home/quest/CSubmenuChallenges.java -text
|
||||||
@@ -17425,6 +17430,7 @@ forge-gui/src/main/java/forge/limited/package-info.java svneol=native#text/plain
|
|||||||
forge-gui/src/main/java/forge/match/AbstractGuiGame.java -text
|
forge-gui/src/main/java/forge/match/AbstractGuiGame.java -text
|
||||||
forge-gui/src/main/java/forge/match/HostedMatch.java -text
|
forge-gui/src/main/java/forge/match/HostedMatch.java -text
|
||||||
forge-gui/src/main/java/forge/match/MatchConstants.java -text
|
forge-gui/src/main/java/forge/match/MatchConstants.java -text
|
||||||
|
forge-gui/src/main/java/forge/match/NetGuiGame.java -text
|
||||||
forge-gui/src/main/java/forge/match/NextGameDecision.java -text
|
forge-gui/src/main/java/forge/match/NextGameDecision.java -text
|
||||||
forge-gui/src/main/java/forge/match/input/Input.java -text
|
forge-gui/src/main/java/forge/match/input/Input.java -text
|
||||||
forge-gui/src/main/java/forge/match/input/InputAttack.java -text
|
forge-gui/src/main/java/forge/match/input/InputAttack.java -text
|
||||||
@@ -17456,6 +17462,10 @@ forge-gui/src/main/java/forge/model/MetaSet.java -text
|
|||||||
forge-gui/src/main/java/forge/model/MultipleForgeJarsFoundError.java -text
|
forge-gui/src/main/java/forge/model/MultipleForgeJarsFoundError.java -text
|
||||||
forge-gui/src/main/java/forge/model/UnOpenedMeta.java -text
|
forge-gui/src/main/java/forge/model/UnOpenedMeta.java -text
|
||||||
forge-gui/src/main/java/forge/model/package-info.java svneol=native#text/plain
|
forge-gui/src/main/java/forge/model/package-info.java svneol=native#text/plain
|
||||||
|
forge-gui/src/main/java/forge/net/FGameClient.java -text
|
||||||
|
forge-gui/src/main/java/forge/net/FServerManager.java -text
|
||||||
|
forge-gui/src/main/java/forge/net/NetGame.java -text
|
||||||
|
forge-gui/src/main/java/forge/net/package-info.java -text
|
||||||
forge-gui/src/main/java/forge/planarconquest/ConquestAction.java -text
|
forge-gui/src/main/java/forge/planarconquest/ConquestAction.java -text
|
||||||
forge-gui/src/main/java/forge/planarconquest/ConquestCommander.java -text
|
forge-gui/src/main/java/forge/planarconquest/ConquestCommander.java -text
|
||||||
forge-gui/src/main/java/forge/planarconquest/ConquestController.java -text
|
forge-gui/src/main/java/forge/planarconquest/ConquestController.java -text
|
||||||
@@ -17473,6 +17483,7 @@ forge-gui/src/main/java/forge/player/HumanCostDecision.java -text
|
|||||||
forge-gui/src/main/java/forge/player/HumanPlay.java -text
|
forge-gui/src/main/java/forge/player/HumanPlay.java -text
|
||||||
forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java -text
|
forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java -text
|
||||||
forge-gui/src/main/java/forge/player/LobbyPlayerHuman.java -text
|
forge-gui/src/main/java/forge/player/LobbyPlayerHuman.java -text
|
||||||
|
forge-gui/src/main/java/forge/player/NetGameController.java -text
|
||||||
forge-gui/src/main/java/forge/player/PlayerControllerHuman.java -text
|
forge-gui/src/main/java/forge/player/PlayerControllerHuman.java -text
|
||||||
forge-gui/src/main/java/forge/player/TargetSelection.java -text
|
forge-gui/src/main/java/forge/player/TargetSelection.java -text
|
||||||
forge-gui/src/main/java/forge/player/package-info.java -text
|
forge-gui/src/main/java/forge/player/package-info.java -text
|
||||||
@@ -17587,6 +17598,7 @@ forge-net/src/main/java/forge/net/IConnectionObserver.java -text
|
|||||||
forge-net/src/main/java/forge/net/Lobby.java -text
|
forge-net/src/main/java/forge/net/Lobby.java -text
|
||||||
forge-net/src/main/java/forge/net/LobbyPlayerRemote.java -text
|
forge-net/src/main/java/forge/net/LobbyPlayerRemote.java -text
|
||||||
forge-net/src/main/java/forge/net/NetServer.java -text
|
forge-net/src/main/java/forge/net/NetServer.java -text
|
||||||
|
forge-net/src/main/java/forge/net/client/GameServlet.java -text
|
||||||
forge-net/src/main/java/forge/net/client/INetClient.java -text
|
forge-net/src/main/java/forge/net/client/INetClient.java -text
|
||||||
forge-net/src/main/java/forge/net/client/InvalidFieldInPacketException.java -text
|
forge-net/src/main/java/forge/net/client/InvalidFieldInPacketException.java -text
|
||||||
forge-net/src/main/java/forge/net/client/NetClient.java -text
|
forge-net/src/main/java/forge/net/client/NetClient.java -text
|
||||||
@@ -17596,6 +17608,20 @@ forge-net/src/main/java/forge/net/client/state/IClientState.java -text
|
|||||||
forge-net/src/main/java/forge/net/client/state/InLobbyClientState.java -text
|
forge-net/src/main/java/forge/net/client/state/InLobbyClientState.java -text
|
||||||
forge-net/src/main/java/forge/net/client/state/UnauthorizedClientState.java -text
|
forge-net/src/main/java/forge/net/client/state/UnauthorizedClientState.java -text
|
||||||
forge-net/src/main/java/forge/net/client/state/package-info.java -text
|
forge-net/src/main/java/forge/net/client/state/package-info.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/GuiGameEvent.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/IRemote.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/LoginEvent.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/LogoutEvent.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/MessageEvent.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/NetEvent.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/RegisterDeckEvent.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/client/ILobbyListener.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/client/IToServer.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/client/package-info.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/package-info.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/server/IToClient.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/server/RemoteClient.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/server/package-info.java -text
|
||||||
forge-net/src/main/java/forge/net/package-info.java -text
|
forge-net/src/main/java/forge/net/package-info.java -text
|
||||||
forge-net/src/main/java/forge/net/protocol/ClientProtocol.java -text
|
forge-net/src/main/java/forge/net/protocol/ClientProtocol.java -text
|
||||||
forge-net/src/main/java/forge/net/protocol/ClientProtocolJson.java -text
|
forge-net/src/main/java/forge/net/protocol/ClientProtocolJson.java -text
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import forge.download.GuiDownloader;
|
|||||||
import forge.error.BugReportDialog;
|
import forge.error.BugReportDialog;
|
||||||
import forge.gui.BoxedProductCardListViewer;
|
import forge.gui.BoxedProductCardListViewer;
|
||||||
import forge.gui.CardListViewer;
|
import forge.gui.CardListViewer;
|
||||||
|
import forge.gui.FNetOverlay;
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
import forge.gui.framework.FScreen;
|
import forge.gui.framework.FScreen;
|
||||||
import forge.interfaces.IGuiBase;
|
import forge.interfaces.IGuiBase;
|
||||||
@@ -278,4 +279,10 @@ public class GuiDesktop implements IGuiBase {
|
|||||||
Singletons.getControl().addMatch(match);
|
Singletons.getControl().addMatch(match);
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void netMessage(final String origin, final String message) {
|
||||||
|
FNetOverlay.SINGLETON_INSTANCE.showUp("");
|
||||||
|
FNetOverlay.SINGLETON_INSTANCE.addMessage(origin, message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
package forge.gui;
|
package forge.gui;
|
||||||
|
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.net.FGameClient;
|
||||||
|
import forge.net.game.MessageEvent;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.toolbox.*;
|
import forge.toolbox.*;
|
||||||
import forge.toolbox.FSkin.SkinnedPanel;
|
import forge.toolbox.FSkin.SkinnedPanel;
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
@@ -31,20 +35,26 @@ public enum FNetOverlay {
|
|||||||
private final FTextField txtInput = new FTextField.Builder().maxLength(60).build();
|
private final FTextField txtInput = new FTextField.Builder().maxLength(60).build();
|
||||||
private final FLabel cmdSend = new FLabel.ButtonBuilder().text("Send").build();
|
private final FLabel cmdSend = new FLabel.ButtonBuilder().text("Send").build();
|
||||||
|
|
||||||
|
|
||||||
//private boolean minimized = false;
|
//private boolean minimized = false;
|
||||||
private int height = 120;
|
private int height = 120;
|
||||||
private int width = 400;
|
private int width = 400;
|
||||||
|
|
||||||
|
private FGameClient client = null;
|
||||||
|
public void setGameClient(final FGameClient client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
private final ActionListener onSend = new ActionListener() {
|
private final ActionListener onSend = new ActionListener() {
|
||||||
|
@Override public final void actionPerformed(final ActionEvent e) {
|
||||||
@Override
|
final String message = txtInput.getText();
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
String message = txtInput.getText();
|
|
||||||
txtInput.setText("");
|
txtInput.setText("");
|
||||||
if ( StringUtils.isBlank(message) )
|
if (StringUtils.isBlank(message)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client != null) {
|
||||||
|
client.send(new MessageEvent(FModel.getPreferences().getPref(FPref.PLAYER_NAME), message));
|
||||||
|
}
|
||||||
// lobby.speak(ChatArea.Room, lobby.getGuiPlayer(), message);
|
// lobby.speak(ChatArea.Room, lobby.getGuiPlayer(), message);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import forge.screens.home.gauntlet.VSubmenuGauntletBuild;
|
|||||||
import forge.screens.home.gauntlet.VSubmenuGauntletContests;
|
import forge.screens.home.gauntlet.VSubmenuGauntletContests;
|
||||||
import forge.screens.home.gauntlet.VSubmenuGauntletLoad;
|
import forge.screens.home.gauntlet.VSubmenuGauntletLoad;
|
||||||
import forge.screens.home.gauntlet.VSubmenuGauntletQuick;
|
import forge.screens.home.gauntlet.VSubmenuGauntletQuick;
|
||||||
|
import forge.screens.home.online.VOnlineLobby;
|
||||||
import forge.screens.home.online.VSubmenuOnlineLobby;
|
import forge.screens.home.online.VSubmenuOnlineLobby;
|
||||||
import forge.screens.home.quest.VSubmenuChallenges;
|
import forge.screens.home.quest.VSubmenuChallenges;
|
||||||
import forge.screens.home.quest.VSubmenuDuels;
|
import forge.screens.home.quest.VSubmenuDuels;
|
||||||
@@ -73,9 +74,11 @@ public enum EDocID {
|
|||||||
HOME_DRAFT (VSubmenuDraft.SINGLETON_INSTANCE),
|
HOME_DRAFT (VSubmenuDraft.SINGLETON_INSTANCE),
|
||||||
HOME_SEALED (VSubmenuSealed.SINGLETON_INSTANCE),
|
HOME_SEALED (VSubmenuSealed.SINGLETON_INSTANCE),
|
||||||
HOME_WINSTON (VSubmenuWinston.SINGLETON_INSTANCE),
|
HOME_WINSTON (VSubmenuWinston.SINGLETON_INSTANCE),
|
||||||
HOME_LOBBY (VSubmenuOnlineLobby.SINGLETON_INSTANCE),
|
HOME_NETWORK (VSubmenuOnlineLobby.SINGLETON_INSTANCE),
|
||||||
HOME_RELEASE_NOTES (VSubmenuReleaseNotes.SINGLETON_INSTANCE),
|
HOME_RELEASE_NOTES (VSubmenuReleaseNotes.SINGLETON_INSTANCE),
|
||||||
|
|
||||||
|
ONLINE_LOBBY (VOnlineLobby.SINGLETON_INSTANCE),
|
||||||
|
|
||||||
REPORT_MESSAGE (),
|
REPORT_MESSAGE (),
|
||||||
REPORT_STACK (),
|
REPORT_STACK (),
|
||||||
REPORT_COMBAT (),
|
REPORT_COMBAT (),
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import forge.screens.deckeditor.CDeckEditorUI;
|
|||||||
import forge.screens.deckeditor.VDeckEditorUI;
|
import forge.screens.deckeditor.VDeckEditorUI;
|
||||||
import forge.screens.home.CHomeUI;
|
import forge.screens.home.CHomeUI;
|
||||||
import forge.screens.home.VHomeUI;
|
import forge.screens.home.VHomeUI;
|
||||||
|
import forge.screens.home.online.COnlineLobby;
|
||||||
|
import forge.screens.home.online.VOnlineLobby;
|
||||||
import forge.screens.match.CMatchUI;
|
import forge.screens.match.CMatchUI;
|
||||||
import forge.screens.match.VMatchUI;
|
import forge.screens.match.VMatchUI;
|
||||||
import forge.screens.workshop.CWorkshopUI;
|
import forge.screens.workshop.CWorkshopUI;
|
||||||
@@ -151,6 +153,15 @@ public class FScreen {
|
|||||||
"Leave Bazaar",
|
"Leave Bazaar",
|
||||||
null,
|
null,
|
||||||
false);
|
false);
|
||||||
|
public static final FScreen ONLINE_LOBBY = new FScreen(
|
||||||
|
VOnlineLobby.SINGLETON_INSTANCE,
|
||||||
|
COnlineLobby.SINGLETON_INSTANCE,
|
||||||
|
"Online Lobby",
|
||||||
|
FSkin.getImage(FSkinProp.IMG_CHAOS),
|
||||||
|
true,
|
||||||
|
"Leave Lobby",
|
||||||
|
null,
|
||||||
|
false);
|
||||||
|
|
||||||
private final IVTopLevelUI view;
|
private final IVTopLevelUI view;
|
||||||
private final ICDoc controller;
|
private final ICDoc controller;
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
package forge.screens.home;
|
package forge.screens.home;
|
||||||
|
|
||||||
import forge.UiCommand;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
|
import forge.UiCommand;
|
||||||
import forge.gui.FNetOverlay;
|
import forge.gui.FNetOverlay;
|
||||||
import forge.gui.framework.EDocID;
|
import forge.gui.framework.EDocID;
|
||||||
import forge.gui.framework.ICDoc;
|
import forge.gui.framework.ICDoc;
|
||||||
@@ -9,17 +13,12 @@ import forge.menus.IMenuProvider;
|
|||||||
import forge.menus.MenuUtil;
|
import forge.menus.MenuUtil;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.net.FServer;
|
import forge.net.FServer;
|
||||||
import forge.net.NetServer;
|
import forge.net.FServerManager;
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.properties.ForgeConstants;
|
|
||||||
import forge.screens.home.sanctioned.VSubmenuConstructed;
|
import forge.screens.home.sanctioned.VSubmenuConstructed;
|
||||||
import forge.toolbox.FAbsolutePositioner;
|
import forge.toolbox.FAbsolutePositioner;
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assembles Swing components of exit submenu option singleton.
|
* Assembles Swing components of exit submenu option singleton.
|
||||||
*
|
*
|
||||||
@@ -88,13 +87,13 @@ public enum CHomeUI implements ICDoc, IMenuProvider {
|
|||||||
VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setCommand(new Runnable() {
|
VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setCommand(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
NetServer srv = FServer.getServer();
|
//final NetServer srv = FServer.getServer();
|
||||||
srv.listen(ForgeConstants.SERVER_PORT_NUMBER);
|
//srv.listen(ForgeConstants.SERVER_PORT_NUMBER);
|
||||||
|
|
||||||
VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setEnabled(true);
|
VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setEnabled(true);
|
||||||
VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setEnabled(false);
|
VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setEnabled(false);
|
||||||
|
|
||||||
FNetOverlay.SINGLETON_INSTANCE.showUp("Server listening on port " + srv.getPortNumber());
|
FNetOverlay.SINGLETON_INSTANCE.showUp("");//"Server listening on port " + srv.getPortNumber());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -102,6 +101,7 @@ public enum CHomeUI implements ICDoc, IMenuProvider {
|
|||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
FServer.getServer().stop();
|
FServer.getServer().stop();
|
||||||
|
FServerManager.getInstance().stopServer();
|
||||||
VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setEnabled(false);
|
VHomeUI.SINGLETON_INSTANCE.getLblStopServer().setEnabled(false);
|
||||||
VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setEnabled(true);
|
VHomeUI.SINGLETON_INSTANCE.getLblStartServer().setEnabled(true);
|
||||||
|
|
||||||
|
|||||||
372
forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java
Normal file
372
forge-gui-desktop/src/main/java/forge/screens/home/CLobby.java
Normal file
@@ -0,0 +1,372 @@
|
|||||||
|
package forge.screens.home;
|
||||||
|
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
|
||||||
|
import com.beust.jcommander.internal.Maps;
|
||||||
|
|
||||||
|
import forge.GuiBase;
|
||||||
|
import forge.LobbyPlayer;
|
||||||
|
import forge.deck.CardPool;
|
||||||
|
import forge.deck.Deck;
|
||||||
|
import forge.deck.DeckFormat;
|
||||||
|
import forge.deck.DeckSection;
|
||||||
|
import forge.deck.DeckType;
|
||||||
|
import forge.deck.DeckgenUtil;
|
||||||
|
import forge.game.GameType;
|
||||||
|
import forge.game.player.RegisteredPlayer;
|
||||||
|
import forge.gui.GuiDialog;
|
||||||
|
import forge.interfaces.IGuiGame;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.match.HostedMatch;
|
||||||
|
import forge.model.CardCollections;
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.player.GamePlayerUtil;
|
||||||
|
import forge.properties.ForgePreferences;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
|
import forge.toolbox.FList;
|
||||||
|
import forge.toolbox.FOptionPane;
|
||||||
|
import forge.util.Aggregates;
|
||||||
|
import forge.util.storage.IStorage;
|
||||||
|
|
||||||
|
public class CLobby {
|
||||||
|
|
||||||
|
private final VLobby view;
|
||||||
|
public CLobby(final VLobby view) {
|
||||||
|
this.view = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
@Override public final void run() {
|
||||||
|
final CardCollections cColl = FModel.getDecks();
|
||||||
|
FList<Object> deckList;
|
||||||
|
Vector<Object> listData;
|
||||||
|
Object val;
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
// Commander: reinit deck list and restore last selections (if any)
|
||||||
|
deckList = view.getCommanderDeckLists().get(i);
|
||||||
|
listData = new Vector<Object>();
|
||||||
|
listData.add("Generate");
|
||||||
|
if (cColl.getCommander().size() > 0) {
|
||||||
|
listData.add("Random");
|
||||||
|
for (Deck comDeck : cColl.getCommander()) {
|
||||||
|
listData.add(comDeck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = deckList.getSelectedValue();
|
||||||
|
deckList.setListData(listData);
|
||||||
|
if (null != val) {
|
||||||
|
deckList.setSelectedValue(val, true);
|
||||||
|
}
|
||||||
|
if (-1 == deckList.getSelectedIndex()) {
|
||||||
|
deckList.setSelectedIndex(0);
|
||||||
|
} // End Commander
|
||||||
|
|
||||||
|
// Archenemy: reinit deck list and restore last selections (if any)
|
||||||
|
deckList = view.getSchemeDeckLists().get(i);
|
||||||
|
listData = new Vector<Object>();
|
||||||
|
listData.add("Use deck's scheme section (random if unavailable)");
|
||||||
|
listData.add("Generate");
|
||||||
|
if (cColl.getScheme().size() > 0) {
|
||||||
|
listData.add("Random");
|
||||||
|
for (Deck schemeDeck : cColl.getScheme()) {
|
||||||
|
listData.add(schemeDeck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val = deckList.getSelectedValue();
|
||||||
|
deckList.setListData(listData);
|
||||||
|
if (null != val) {
|
||||||
|
deckList.setSelectedValue(val, true);
|
||||||
|
}
|
||||||
|
if (-1 == deckList.getSelectedIndex()) {
|
||||||
|
deckList.setSelectedIndex(0);
|
||||||
|
} // End Archenemy
|
||||||
|
|
||||||
|
// Planechase: reinit deck lists and restore last selections (if any)
|
||||||
|
deckList = view.getPlanarDeckLists().get(i);
|
||||||
|
listData = new Vector<Object>();
|
||||||
|
|
||||||
|
listData.add("Use deck's planes section (random if unavailable)");
|
||||||
|
listData.add("Generate");
|
||||||
|
if (cColl.getPlane().size() > 0) {
|
||||||
|
listData.add("Random");
|
||||||
|
for (Deck planarDeck : cColl.getPlane()) {
|
||||||
|
listData.add(planarDeck);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val = deckList.getSelectedValue();
|
||||||
|
deckList.setListData(listData);
|
||||||
|
if (null != val) {
|
||||||
|
deckList.setSelectedValue(val, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-1 == deckList.getSelectedIndex()) {
|
||||||
|
deckList.setSelectedIndex(0);
|
||||||
|
} // End Planechase
|
||||||
|
|
||||||
|
view.updateVanguardList(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// General updates when switching back to this view
|
||||||
|
view.updatePlayersFromPrefs();
|
||||||
|
view.getBtnStart().requestFocusInWindow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
view.getDeckChooser(0).initialize(FPref.CONSTRUCTED_P1_DECK_STATE, DeckType.PRECONSTRUCTED_DECK);
|
||||||
|
view.getDeckChooser(1).initialize(FPref.CONSTRUCTED_P2_DECK_STATE, DeckType.COLOR_DECK);
|
||||||
|
view.getDeckChooser(2).initialize(FPref.CONSTRUCTED_P3_DECK_STATE, DeckType.COLOR_DECK);
|
||||||
|
view.getDeckChooser(3).initialize(FPref.CONSTRUCTED_P4_DECK_STATE, DeckType.COLOR_DECK);
|
||||||
|
view.getDeckChooser(4).initialize(FPref.CONSTRUCTED_P5_DECK_STATE, DeckType.COLOR_DECK);
|
||||||
|
view.getDeckChooser(5).initialize(FPref.CONSTRUCTED_P6_DECK_STATE, DeckType.COLOR_DECK);
|
||||||
|
view.getDeckChooser(6).initialize(FPref.CONSTRUCTED_P7_DECK_STATE, DeckType.COLOR_DECK);
|
||||||
|
view.getDeckChooser(7).initialize(FPref.CONSTRUCTED_P8_DECK_STATE, DeckType.COLOR_DECK);
|
||||||
|
|
||||||
|
// Start button event handling
|
||||||
|
view.getBtnStart().addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(final ActionEvent arg0) {
|
||||||
|
startGame(view.getAppliedVariants());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
final ForgePreferences prefs = FModel.getPreferences();
|
||||||
|
// Checkbox event handling
|
||||||
|
view.getCbSingletons().addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(final ActionEvent arg0) {
|
||||||
|
prefs.setPref(FPref.DECKGEN_SINGLETONS, String.valueOf(view.getCbSingletons().isSelected()));
|
||||||
|
prefs.save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
view.getCbArtifacts().addActionListener(new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(final ActionEvent arg0) {
|
||||||
|
prefs.setPref(FPref.DECKGEN_ARTIFACTS, String.valueOf(view.getCbArtifacts().isSelected()));
|
||||||
|
prefs.save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Pre-select checkboxes
|
||||||
|
view.getCbSingletons().setSelected(prefs.getPrefBoolean(FPref.DECKGEN_SINGLETONS));
|
||||||
|
view.getCbArtifacts().setSelected(prefs.getPrefBoolean(FPref.DECKGEN_ARTIFACTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Starts a match with the applied variants. */
|
||||||
|
private void startGame(final Set<GameType> variantTypes) {
|
||||||
|
if (!view.isEnoughTeams()) {
|
||||||
|
FOptionPane.showMessageDialog("There are not enough teams! Please adjust team allocations.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final int i : view.getParticipants()) {
|
||||||
|
if (view.getDeckChooser(i).getPlayer() == null) {
|
||||||
|
FOptionPane.showMessageDialog("Please specify a deck for " + view.getPlayerName(i));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} // Is it even possible anymore? I think current implementation assigns decks automatically.
|
||||||
|
|
||||||
|
GameType autoGenerateVariant = null;
|
||||||
|
boolean isCommanderMatch = false;
|
||||||
|
boolean isTinyLeadersMatch = false;
|
||||||
|
if (!variantTypes.isEmpty()) {
|
||||||
|
isTinyLeadersMatch = variantTypes.contains(GameType.TinyLeaders);
|
||||||
|
isCommanderMatch = isTinyLeadersMatch || variantTypes.contains(GameType.Commander);
|
||||||
|
if (!isCommanderMatch) {
|
||||||
|
for (GameType variant : variantTypes) {
|
||||||
|
if (variant.isAutoGenerated()) {
|
||||||
|
autoGenerateVariant = variant;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean checkLegality = FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY);
|
||||||
|
|
||||||
|
//Auto-generated decks don't need to be checked here
|
||||||
|
//Commander deck replaces regular deck and is checked later
|
||||||
|
if (checkLegality && autoGenerateVariant == null && !isCommanderMatch) {
|
||||||
|
for (final int i : view.getParticipants()) {
|
||||||
|
String name = view.getPlayerName(i);
|
||||||
|
String errMsg = GameType.Constructed.getDeckFormat().getDeckConformanceProblem(view.getDeckChooser(i).getPlayer().getDeck());
|
||||||
|
if (null != errMsg) {
|
||||||
|
FOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid Deck");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<RegisteredPlayer> players = new ArrayList<RegisteredPlayer>();
|
||||||
|
final Map<RegisteredPlayer, IGuiGame> guis = Maps.newHashMap();
|
||||||
|
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
||||||
|
for (final int i : view.getParticipants()) {
|
||||||
|
final String name = view.getPlayerName(i);
|
||||||
|
final boolean isAI = view.isPlayerAI(i);
|
||||||
|
final LobbyPlayer lobbyPlayer = isAI
|
||||||
|
? GamePlayerUtil.createAiPlayer(name, view.getPlayerAvatar(i), view.getAiOptions(i))
|
||||||
|
: GamePlayerUtil.getGuiPlayer(name, i);
|
||||||
|
RegisteredPlayer rp = view.getDeckChooser(i).getPlayer();
|
||||||
|
|
||||||
|
if (variantTypes.isEmpty()) {
|
||||||
|
rp.setTeamNumber(view.getTeam(i));
|
||||||
|
players.add(rp.setPlayer(lobbyPlayer));
|
||||||
|
} else {
|
||||||
|
Deck deck = null;
|
||||||
|
PaperCard vanguardAvatar = null;
|
||||||
|
if (isCommanderMatch) {
|
||||||
|
final Object selected = view.getCommanderDeckLists().get(i).getSelectedValue();
|
||||||
|
if (selected instanceof String) {
|
||||||
|
final String sel = (String) selected;
|
||||||
|
final IStorage<Deck> comDecks = FModel.getDecks().getCommander();
|
||||||
|
if (sel.equals("Random") && comDecks.size() > 0) {
|
||||||
|
deck = Aggregates.random(comDecks);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
deck = (Deck) selected;
|
||||||
|
}
|
||||||
|
GameType commanderGameType = isTinyLeadersMatch ? GameType.TinyLeaders : GameType.Commander;
|
||||||
|
if (deck == null) { //Can be null if player deselects the list selection or chose Generate
|
||||||
|
deck = DeckgenUtil.generateCommanderDeck(isAI, commanderGameType);
|
||||||
|
}
|
||||||
|
if (checkLegality) {
|
||||||
|
String errMsg = commanderGameType.getDeckFormat().getDeckConformanceProblem(deck);
|
||||||
|
if (null != errMsg) {
|
||||||
|
FOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid " + commanderGameType + " Deck");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (autoGenerateVariant != null) {
|
||||||
|
deck = autoGenerateVariant.autoGenerateDeck(rp);
|
||||||
|
CardPool avatarPool = deck.get(DeckSection.Avatar);
|
||||||
|
if (avatarPool != null) {
|
||||||
|
vanguardAvatar = avatarPool.get(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialise variables for other variants
|
||||||
|
deck = deck == null ? rp.getDeck() : deck;
|
||||||
|
Iterable<PaperCard> schemes = null;
|
||||||
|
final boolean playerIsArchenemy = view.isPlayerArchenemy(i);
|
||||||
|
Iterable<PaperCard> planes = null;
|
||||||
|
|
||||||
|
//Archenemy
|
||||||
|
if (variantTypes.contains(GameType.ArchenemyRumble)
|
||||||
|
|| (variantTypes.contains(GameType.Archenemy) && playerIsArchenemy)) {
|
||||||
|
Object selected = view.getSchemeDeckLists().get(i).getSelectedValue();
|
||||||
|
CardPool schemePool = null;
|
||||||
|
if (selected instanceof String) {
|
||||||
|
String sel = (String) selected;
|
||||||
|
if (sel.contains("Use deck's scheme section")) {
|
||||||
|
if (deck.has(DeckSection.Schemes)) {
|
||||||
|
schemePool = deck.get(DeckSection.Schemes);
|
||||||
|
} else {
|
||||||
|
sel = "Random";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IStorage<Deck> sDecks = FModel.getDecks().getScheme();
|
||||||
|
if (sel.equals("Random") && sDecks.size() != 0) {
|
||||||
|
schemePool = Aggregates.random(sDecks).get(DeckSection.Schemes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
schemePool = ((Deck) selected).get(DeckSection.Schemes);
|
||||||
|
}
|
||||||
|
if (schemePool == null) { //Can be null if player deselects the list selection or chose Generate
|
||||||
|
schemePool = DeckgenUtil.generateSchemePool();
|
||||||
|
}
|
||||||
|
if (checkLegality) {
|
||||||
|
String errMsg = DeckFormat.getSchemeSectionConformanceProblem(schemePool);
|
||||||
|
if (null != errMsg) {
|
||||||
|
FOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid Scheme Deck");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
schemes = schemePool.toFlatList();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Planechase
|
||||||
|
if (variantTypes.contains(GameType.Planechase)) {
|
||||||
|
Object selected = view.getPlanarDeckLists().get(i).getSelectedValue();
|
||||||
|
CardPool planePool = null;
|
||||||
|
if (selected instanceof String) {
|
||||||
|
String sel = (String) selected;
|
||||||
|
if (sel.contains("Use deck's planes section")) {
|
||||||
|
if (deck.has(DeckSection.Planes)) {
|
||||||
|
planePool = deck.get(DeckSection.Planes);
|
||||||
|
} else {
|
||||||
|
sel = "Random";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IStorage<Deck> pDecks = FModel.getDecks().getPlane();
|
||||||
|
if (sel.equals("Random") && pDecks.size() != 0) {
|
||||||
|
planePool = Aggregates.random(pDecks).get(DeckSection.Planes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
planePool = ((Deck) selected).get(DeckSection.Planes);
|
||||||
|
}
|
||||||
|
if (planePool == null) { //Can be null if player deselects the list selection or chose Generate
|
||||||
|
planePool = DeckgenUtil.generatePlanarPool();
|
||||||
|
}
|
||||||
|
if (checkLegality) {
|
||||||
|
String errMsg = DeckFormat.getPlaneSectionConformanceProblem(planePool);
|
||||||
|
if (null != errMsg) {
|
||||||
|
FOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid Planar Deck");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
planes = planePool.toFlatList();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Vanguard
|
||||||
|
if (variantTypes.contains(GameType.Vanguard)) {
|
||||||
|
Object selected = view.getVanguardLists().get(i).getSelectedValue();
|
||||||
|
if (selected instanceof String) {
|
||||||
|
String sel = (String) selected;
|
||||||
|
if (sel.contains("Use deck's default avatar") && deck.has(DeckSection.Avatar)) {
|
||||||
|
vanguardAvatar = deck.get(DeckSection.Avatar).get(0);
|
||||||
|
} else { //Only other string is "Random"
|
||||||
|
if (isAI) { //AI
|
||||||
|
vanguardAvatar = Aggregates.random(view.getNonRandomAiAvatars());
|
||||||
|
} else { //Human
|
||||||
|
vanguardAvatar = Aggregates.random(view.getNonRandomHumanAvatars());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
vanguardAvatar = (PaperCard)selected;
|
||||||
|
}
|
||||||
|
if (vanguardAvatar == null) { //ERROR! null if avatar deselected on list
|
||||||
|
GuiDialog.message("No Vanguard avatar selected for " + name
|
||||||
|
+ ". Please choose one or disable the Vanguard variant");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rp = RegisteredPlayer.forVariants(variantTypes, deck, schemes, playerIsArchenemy, planes, vanguardAvatar);
|
||||||
|
rp.setTeamNumber(view.getTeam(i));
|
||||||
|
players.add(rp.setPlayer(lobbyPlayer));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isAI) {
|
||||||
|
guis.put(rp, gui);
|
||||||
|
}
|
||||||
|
view.getDeckChooser(i).saveState();
|
||||||
|
}
|
||||||
|
|
||||||
|
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
||||||
|
hostedMatch.startMatch(GameType.Constructed, variantTypes, players, guis);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ package forge.screens.home;
|
|||||||
*/
|
*/
|
||||||
public enum EMenuGroup {
|
public enum EMenuGroup {
|
||||||
SANCTIONED ("Sanctioned Formats"),
|
SANCTIONED ("Sanctioned Formats"),
|
||||||
//ONLINE ("Online Multiplayer"),
|
ONLINE ("Online Multiplayer"),
|
||||||
QUEST ("Quest Mode"),
|
QUEST ("Quest Mode"),
|
||||||
GAUNTLET ("Gauntlets"),
|
GAUNTLET ("Gauntlets"),
|
||||||
SETTINGS ("Game Settings");
|
SETTINGS ("Game Settings");
|
||||||
|
|||||||
@@ -0,0 +1,670 @@
|
|||||||
|
package forge.screens.home;
|
||||||
|
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.FocusAdapter;
|
||||||
|
import java.awt.event.FocusEvent;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.ButtonGroup;
|
||||||
|
import javax.swing.JCheckBoxMenuItem;
|
||||||
|
import javax.swing.JPopupMenu;
|
||||||
|
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.UiCommand;
|
||||||
|
import forge.assets.FSkinProp;
|
||||||
|
import forge.deck.DeckSection;
|
||||||
|
import forge.game.GameType;
|
||||||
|
import forge.gui.framework.FScreen;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.properties.ForgePreferences;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
|
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.FComboBox;
|
||||||
|
import forge.toolbox.FComboBoxWrapper;
|
||||||
|
import forge.toolbox.FLabel;
|
||||||
|
import forge.toolbox.FMouseAdapter;
|
||||||
|
import forge.toolbox.FPanel;
|
||||||
|
import forge.toolbox.FRadioButton;
|
||||||
|
import forge.toolbox.FSkin;
|
||||||
|
import forge.toolbox.FSkin.SkinColor;
|
||||||
|
import forge.toolbox.FSkin.SkinImage;
|
||||||
|
import forge.toolbox.FTextField;
|
||||||
|
import forge.util.MyRandom;
|
||||||
|
import forge.util.NameGenerator;
|
||||||
|
import forge.util.gui.SOptionPane;
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class PlayerPanel extends FPanel {
|
||||||
|
private final static ForgePreferences prefs = FModel.getPreferences();
|
||||||
|
private static final SkinColor unfocusedPlayerOverlay = FSkin.getColor(FSkin.Colors.CLR_OVERLAY).alphaColor(120);
|
||||||
|
|
||||||
|
private final int index;
|
||||||
|
private final boolean allowRemote;
|
||||||
|
|
||||||
|
private final FLabel nameRandomiser;
|
||||||
|
private final FLabel avatarLabel = new FLabel.Builder().opaque(true).hoverable(true).iconScaleFactor(0.99f).iconInBackground(true).build();
|
||||||
|
private int avatarIndex;
|
||||||
|
|
||||||
|
private final FTextField txtPlayerName = new FTextField.Builder().text("Player name").build();
|
||||||
|
private FRadioButton radioHuman;
|
||||||
|
private FRadioButton radioAi;
|
||||||
|
private JCheckBoxMenuItem radioAiUseSimulation;
|
||||||
|
private FRadioButton radioOpen;
|
||||||
|
/** Whether this panel is occupied by a remote player. */
|
||||||
|
private boolean isRemote;
|
||||||
|
|
||||||
|
private FComboBoxWrapper<Object> teamComboBox = new FComboBoxWrapper<Object>();
|
||||||
|
private FComboBoxWrapper<Object> aeTeamComboBox = new FComboBoxWrapper<Object>();
|
||||||
|
|
||||||
|
private final FLabel deckBtn = new FLabel.ButtonBuilder().text("Select a deck").build();
|
||||||
|
private final FLabel deckLabel;
|
||||||
|
|
||||||
|
private final String variantBtnConstraints = "height 30px, hidemode 3";
|
||||||
|
|
||||||
|
private boolean playerIsArchenemy = false;
|
||||||
|
private final FLabel scmDeckSelectorBtn = new FLabel.ButtonBuilder().text("Select a scheme deck").build();
|
||||||
|
private final FLabel scmDeckEditor = new FLabel.ButtonBuilder().text("Scheme Deck Editor").build();
|
||||||
|
private final FLabel scmLabel;
|
||||||
|
|
||||||
|
private final FLabel cmdDeckSelectorBtn = new FLabel.ButtonBuilder().text("Select a Commander deck").build();
|
||||||
|
private final FLabel cmdDeckEditor = new FLabel.ButtonBuilder().text("Commander Deck Editor").build();
|
||||||
|
private final FLabel cmdLabel;
|
||||||
|
|
||||||
|
private final FLabel pchDeckSelectorBtn = new FLabel.ButtonBuilder().text("Select a planar deck").build();
|
||||||
|
private final FLabel pchDeckEditor = new FLabel.ButtonBuilder().text("Planar Deck Editor").build();
|
||||||
|
private final FLabel pchLabel;
|
||||||
|
|
||||||
|
private final FLabel vgdSelectorBtn = new FLabel.ButtonBuilder().text("Select a Vanguard avatar").build();
|
||||||
|
private final FLabel vgdLabel;
|
||||||
|
|
||||||
|
private final VLobby lobby;
|
||||||
|
public PlayerPanel(final VLobby lobby, final int index, final boolean allowRemote) {
|
||||||
|
super();
|
||||||
|
this.lobby = lobby;
|
||||||
|
this.deckLabel = lobby.newLabel("Deck:");
|
||||||
|
this.scmLabel = lobby.newLabel("Scheme deck:");
|
||||||
|
this.cmdLabel = lobby.newLabel("Commander deck:");
|
||||||
|
this.pchLabel = lobby.newLabel("Planar deck:");
|
||||||
|
this.vgdLabel = lobby.newLabel("Vanguard:");
|
||||||
|
|
||||||
|
this.index = index;
|
||||||
|
this.allowRemote = allowRemote;
|
||||||
|
this.playerIsArchenemy = index == 0;
|
||||||
|
|
||||||
|
setLayout(new MigLayout("insets 10px, gap 5px"));
|
||||||
|
|
||||||
|
// Add a button to players 3+ (or if server) to remove them from the setup
|
||||||
|
if (index >= 2 || allowRemote) {
|
||||||
|
FLabel closeBtn = createCloseButton();
|
||||||
|
this.add(closeBtn, "w 20, h 20, pos (container.w-20) 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
createAvatar();
|
||||||
|
this.add(avatarLabel, "spany 2, width 80px, height 80px");
|
||||||
|
|
||||||
|
createNameEditor();
|
||||||
|
this.add(lobby.newLabel("Name:"), "w 40px, h 30px, gaptop 5px");
|
||||||
|
this.add(txtPlayerName, "h 30px, pushx, growx");
|
||||||
|
|
||||||
|
nameRandomiser = createNameRandomizer();
|
||||||
|
this.add(nameRandomiser, "h 30px, w 30px, gaptop 5px");
|
||||||
|
|
||||||
|
createPlayerTypeOptions();
|
||||||
|
this.add(radioHuman, "gapright 5px");
|
||||||
|
this.add(radioAi, "wrap");
|
||||||
|
|
||||||
|
this.add(lobby.newLabel("Team:"), "w 40px, h 30px");
|
||||||
|
populateTeamsComboBoxes();
|
||||||
|
teamComboBox.addActionListener(teamListener);
|
||||||
|
aeTeamComboBox.addActionListener(teamListener);
|
||||||
|
teamComboBox.addTo(this, variantBtnConstraints + ", pushx, growx, gaptop 5px");
|
||||||
|
aeTeamComboBox.addTo(this, variantBtnConstraints + ", pushx, growx, gaptop 5px");
|
||||||
|
if (allowRemote) {
|
||||||
|
this.add(radioOpen, "gapleft 1px");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.add(deckLabel, variantBtnConstraints + ", cell 0 2, sx 2, ax right");
|
||||||
|
this.add(deckBtn, variantBtnConstraints + ", cell 2 2, pushx, growx, wmax 100%-153px, h 30px, spanx 4, wrap");
|
||||||
|
|
||||||
|
addHandlersDeckSelector();
|
||||||
|
|
||||||
|
this.add(cmdLabel, variantBtnConstraints + ", cell 0 3, sx 2, ax right");
|
||||||
|
this.add(cmdDeckSelectorBtn, variantBtnConstraints + ", cell 2 3, growx, pushx");
|
||||||
|
this.add(cmdDeckEditor, variantBtnConstraints + ", cell 3 3, sx 3, growx, wrap");
|
||||||
|
|
||||||
|
this.add(scmLabel, variantBtnConstraints + ", cell 0 4, sx 2, ax right");
|
||||||
|
this.add(scmDeckSelectorBtn, variantBtnConstraints + ", cell 2 4, growx, pushx");
|
||||||
|
this.add(scmDeckEditor, variantBtnConstraints + ", cell 3 4, sx 3, growx, wrap");
|
||||||
|
|
||||||
|
this.add(pchLabel, variantBtnConstraints + ", cell 0 5, sx 2, ax right");
|
||||||
|
this.add(pchDeckSelectorBtn, variantBtnConstraints + ", cell 2 5, growx, pushx");
|
||||||
|
this.add(pchDeckEditor, variantBtnConstraints + ", cell 3 5, sx 3, growx, wrap");
|
||||||
|
|
||||||
|
this.add(vgdLabel, variantBtnConstraints + ", cell 0 6, sx 2, ax right");
|
||||||
|
this.add(vgdSelectorBtn, variantBtnConstraints + ", cell 2 6, sx 4, growx, wrap");
|
||||||
|
|
||||||
|
addHandlersToVariantsControls();
|
||||||
|
updateVariantControlsVisibility();
|
||||||
|
|
||||||
|
this.addMouseListener(new FMouseAdapter() {
|
||||||
|
@Override public final void onLeftMouseDown(final MouseEvent e) {
|
||||||
|
avatarLabel.requestFocusInWindow();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void update() {
|
||||||
|
final boolean enableComponents = !(isOpen() || isRemote());
|
||||||
|
avatarLabel.setEnabled(enableComponents);
|
||||||
|
txtPlayerName.setEnabled(enableComponents);
|
||||||
|
nameRandomiser.setEnabled(enableComponents);
|
||||||
|
deckLabel.setVisible(enableComponents);
|
||||||
|
deckBtn.setVisible(enableComponents);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final FMouseAdapter radioMouseAdapter = new FMouseAdapter() {
|
||||||
|
@Override public final void onLeftClick(final MouseEvent e) {
|
||||||
|
avatarLabel.requestFocusInWindow();
|
||||||
|
lobby.updateVanguardList(index);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Listens to name text fields and gives the appropriate player focus.
|
||||||
|
* Also saves the name preference when leaving player one's text field. */
|
||||||
|
private FocusAdapter nameFocusListener = new FocusAdapter() {
|
||||||
|
@Override
|
||||||
|
public void focusGained(FocusEvent e) {
|
||||||
|
lobby.changePlayerFocus(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusLost(FocusEvent e) {
|
||||||
|
final Object source = e.getSource();
|
||||||
|
if (source instanceof FTextField) { // the text box
|
||||||
|
FTextField nField = (FTextField)source;
|
||||||
|
String newName = nField.getText().trim();
|
||||||
|
if (index == 0 && !StringUtils.isBlank(newName)
|
||||||
|
&& StringUtils.isAlphanumericSpace(newName) && prefs.getPref(FPref.PLAYER_NAME) != newName) {
|
||||||
|
prefs.setPref(FPref.PLAYER_NAME, newName);
|
||||||
|
prefs.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Listens to avatar buttons and gives the appropriate player focus. */
|
||||||
|
private FocusAdapter avatarFocusListener = new FocusAdapter() {
|
||||||
|
@Override
|
||||||
|
public void focusGained(FocusEvent e) {
|
||||||
|
lobby.changePlayerFocus(index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
private FMouseAdapter avatarMouseListener = new FMouseAdapter() {
|
||||||
|
@Override public final void onLeftClick(final MouseEvent e) {
|
||||||
|
if (!avatarLabel.isEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final FLabel avatar = (FLabel)e.getSource();
|
||||||
|
|
||||||
|
PlayerPanel.this.lobby.changePlayerFocus(index);
|
||||||
|
avatar.requestFocusInWindow();
|
||||||
|
|
||||||
|
final AvatarSelector aSel = new AvatarSelector(getPlayerName(), avatarIndex, PlayerPanel.this.lobby.getUsedAvatars());
|
||||||
|
for (final FLabel lbl : aSel.getSelectables()) {
|
||||||
|
lbl.setCommand(new UiCommand() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
setAvatar(Integer.valueOf(lbl.getName().substring(11)));
|
||||||
|
aSel.setVisible(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
aSel.setVisible(true);
|
||||||
|
aSel.dispose();
|
||||||
|
|
||||||
|
if (index < 2) {
|
||||||
|
PlayerPanel.this.lobby.updateAvatarPrefs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override public final void onRightClick(final MouseEvent e) {
|
||||||
|
if (!avatarLabel.isEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerPanel.this.lobby.changePlayerFocus(index);
|
||||||
|
avatarLabel.requestFocusInWindow();
|
||||||
|
|
||||||
|
setRandomAvatar();
|
||||||
|
|
||||||
|
if (index < 2) {
|
||||||
|
PlayerPanel.this.lobby.updateAvatarPrefs();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void updateVariantControlsVisibility() {
|
||||||
|
boolean isCommanderApplied = false;
|
||||||
|
boolean isPlanechaseApplied = false;
|
||||||
|
boolean isVanguardApplied = false;
|
||||||
|
boolean isArchenemyApplied = false;
|
||||||
|
boolean archenemyVisiblity = false;
|
||||||
|
boolean isDeckBuildingAllowed = true;
|
||||||
|
|
||||||
|
for (final GameType variant : lobby.getAppliedVariants()) {
|
||||||
|
switch (variant) {
|
||||||
|
case Archenemy:
|
||||||
|
isArchenemyApplied = true;
|
||||||
|
if (playerIsArchenemy) {
|
||||||
|
archenemyVisiblity = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ArchenemyRumble:
|
||||||
|
archenemyVisiblity = true;
|
||||||
|
break;
|
||||||
|
case Commander:
|
||||||
|
case TinyLeaders:
|
||||||
|
isCommanderApplied = true;
|
||||||
|
isDeckBuildingAllowed = false; //Commander deck replaces basic deck, so hide that
|
||||||
|
break;
|
||||||
|
case Planechase:
|
||||||
|
isPlanechaseApplied = true;
|
||||||
|
break;
|
||||||
|
case Vanguard:
|
||||||
|
isVanguardApplied = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (variant.isAutoGenerated()) {
|
||||||
|
isDeckBuildingAllowed = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deckLabel.setVisible(isDeckBuildingAllowed);
|
||||||
|
deckBtn.setVisible(isDeckBuildingAllowed);
|
||||||
|
cmdDeckSelectorBtn.setVisible(isCommanderApplied);
|
||||||
|
cmdDeckEditor.setVisible(isCommanderApplied);
|
||||||
|
cmdLabel.setVisible(isCommanderApplied);
|
||||||
|
|
||||||
|
scmDeckSelectorBtn.setVisible(archenemyVisiblity);
|
||||||
|
scmDeckEditor.setVisible(archenemyVisiblity);
|
||||||
|
scmLabel.setVisible(archenemyVisiblity);
|
||||||
|
|
||||||
|
teamComboBox.setVisible(!isArchenemyApplied);
|
||||||
|
aeTeamComboBox.setVisible(isArchenemyApplied);
|
||||||
|
aeTeamComboBox.setEnabled(!(isArchenemyApplied && playerIsArchenemy));
|
||||||
|
|
||||||
|
pchDeckSelectorBtn.setVisible(isPlanechaseApplied);
|
||||||
|
pchDeckEditor.setVisible(isPlanechaseApplied);
|
||||||
|
pchLabel.setVisible(isPlanechaseApplied);
|
||||||
|
|
||||||
|
vgdSelectorBtn.setVisible(isVanguardApplied);
|
||||||
|
vgdLabel.setVisible(isVanguardApplied);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paintComponent(Graphics g) {
|
||||||
|
super.paintComponent(g);
|
||||||
|
if (lobby.getPlayerPanelWithFocus() != this) {
|
||||||
|
FSkin.setGraphicsColor(g, unfocusedPlayerOverlay);
|
||||||
|
g.fillRect(0, 0, this.getWidth(), this.getHeight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAi() {
|
||||||
|
return radioAi.isSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSimulatedAi() {
|
||||||
|
return radioAi.isSelected() && radioAiUseSimulation.isSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOpen() {
|
||||||
|
return radioOpen.isSelected() && !isRemote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isArchenemy() {
|
||||||
|
return playerIsArchenemy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isRemote() {
|
||||||
|
return isRemote;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemote(final boolean remote) {
|
||||||
|
isRemote = remote;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVanguardButtonText(String text) {
|
||||||
|
vgdSelectorBtn.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeckSelectorButtonText(String text) {
|
||||||
|
deckBtn.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void focusOnAvatar() {
|
||||||
|
avatarLabel.requestFocusInWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void populateTeamsComboBoxes() {
|
||||||
|
aeTeamComboBox.addItem("Archenemy");
|
||||||
|
aeTeamComboBox.addItem("Heroes");
|
||||||
|
aeTeamComboBox.setSelectedIndex(lobby.getArchenemyTeams().get(index) - 1);
|
||||||
|
aeTeamComboBox.setEnabled(playerIsArchenemy);
|
||||||
|
|
||||||
|
for (int i = 1; i <= VLobby.MAX_PLAYERS; i++) {
|
||||||
|
teamComboBox.addItem(i);
|
||||||
|
}
|
||||||
|
teamComboBox.setSelectedIndex(lobby.getTeams().get(index) - 1);
|
||||||
|
teamComboBox.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ActionListener teamListener = new ActionListener() {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
FComboBox<Object> cb = (FComboBox<Object>)e.getSource();
|
||||||
|
cb.requestFocusInWindow();
|
||||||
|
Object selection = cb.getSelectedItem();
|
||||||
|
|
||||||
|
if (null == selection) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (PlayerPanel.this.lobby.getAppliedVariants().contains(GameType.Archenemy)) {
|
||||||
|
String sel = (String) selection;
|
||||||
|
if (sel.contains("Archenemy")) {
|
||||||
|
PlayerPanel.this.lobby.setLastArchenemy(index);
|
||||||
|
for (PlayerPanel pp : PlayerPanel.this.lobby.getPlayerPanels()) {
|
||||||
|
int i = pp.index;
|
||||||
|
PlayerPanel.this.lobby.getArchenemyTeams().set(i, i == PlayerPanel.this.lobby.getLastArchenemy() ? 1 : 2);
|
||||||
|
pp.aeTeamComboBox.setSelectedIndex(i == PlayerPanel.this.lobby.getLastArchenemy() ? 0 : 1);
|
||||||
|
pp.toggleIsPlayerArchenemy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Integer sel = (Integer) selection;
|
||||||
|
PlayerPanel.this.lobby.getTeams().set(index, sel);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerPanel.this.lobby.changePlayerFocus(index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public void toggleIsPlayerArchenemy() {
|
||||||
|
if (lobby.getAppliedVariants().contains(GameType.Archenemy)) {
|
||||||
|
playerIsArchenemy = lobby.getLastArchenemy() == index;
|
||||||
|
} else {
|
||||||
|
playerIsArchenemy = lobby.getAppliedVariants().contains(GameType.ArchenemyRumble);
|
||||||
|
}
|
||||||
|
updateVariantControlsVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param index
|
||||||
|
*/
|
||||||
|
private void addHandlersToVariantsControls() {
|
||||||
|
// Archenemy buttons
|
||||||
|
scmDeckSelectorBtn.setCommand(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PlayerPanel.this.lobby.setCurrentGameMode(PlayerPanel.this.lobby.getVntArchenemy().isSelected() ? GameType.Archenemy : GameType.ArchenemyRumble);
|
||||||
|
scmDeckSelectorBtn.requestFocusInWindow();
|
||||||
|
PlayerPanel.this.lobby.changePlayerFocus(index, PlayerPanel.this.lobby.getCurrentGameMode());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
scmDeckEditor.setCommand(new UiCommand() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PlayerPanel.this.lobby.setCurrentGameMode(PlayerPanel.this.lobby.getVntArchenemy().isSelected() ? GameType.Archenemy : GameType.ArchenemyRumble);
|
||||||
|
Predicate<PaperCard> predSchemes = new Predicate<PaperCard>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(PaperCard arg0) {
|
||||||
|
return arg0.getRules().getType().isScheme();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_ARCHENEMY);
|
||||||
|
CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(
|
||||||
|
new CEditorVariant(FModel.getDecks().getScheme(), predSchemes, DeckSection.Schemes, FScreen.DECK_EDITOR_ARCHENEMY, CDeckEditorUI.SINGLETON_INSTANCE.getCDetailPicture()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Commander buttons
|
||||||
|
cmdDeckSelectorBtn.setCommand(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PlayerPanel.this.lobby.setCurrentGameMode(PlayerPanel.this.lobby.getVntTinyLeaders().isSelected() ? GameType.TinyLeaders : GameType.Commander);
|
||||||
|
cmdDeckSelectorBtn.requestFocusInWindow();
|
||||||
|
PlayerPanel.this.lobby.changePlayerFocus(index, PlayerPanel.this.lobby.getCurrentGameMode());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cmdDeckEditor.setCommand(new UiCommand() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PlayerPanel.this.lobby.setCurrentGameMode(PlayerPanel.this.lobby.getVntTinyLeaders().isSelected() ? GameType.TinyLeaders : GameType.Commander);
|
||||||
|
Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_COMMANDER);
|
||||||
|
CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(new CEditorCommander(CDeckEditorUI.SINGLETON_INSTANCE.getCDetailPicture()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Planechase buttons
|
||||||
|
pchDeckSelectorBtn.setCommand(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Planechase);
|
||||||
|
pchDeckSelectorBtn.requestFocusInWindow();
|
||||||
|
PlayerPanel.this.lobby.changePlayerFocus(index, GameType.Planechase);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
pchDeckEditor.setCommand(new UiCommand() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Planechase);
|
||||||
|
Predicate<PaperCard> predPlanes = new Predicate<PaperCard>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(PaperCard arg0) {
|
||||||
|
return arg0.getRules().getType().isPlane() || arg0.getRules().getType().isPhenomenon();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_PLANECHASE);
|
||||||
|
CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(
|
||||||
|
new CEditorVariant(FModel.getDecks().getPlane(), predPlanes, DeckSection.Planes, FScreen.DECK_EDITOR_PLANECHASE, CDeckEditorUI.SINGLETON_INSTANCE.getCDetailPicture()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Vanguard buttons
|
||||||
|
vgdSelectorBtn.setCommand(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Vanguard);
|
||||||
|
vgdSelectorBtn.requestFocusInWindow();
|
||||||
|
PlayerPanel.this.lobby.changePlayerFocus(index, GameType.Vanguard);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param index
|
||||||
|
*/
|
||||||
|
private void createPlayerTypeOptions() {
|
||||||
|
radioHuman = new FRadioButton(allowRemote ? "Local" : "Human", index == 0);
|
||||||
|
radioAi = new FRadioButton("AI", !allowRemote && index != 0);
|
||||||
|
radioOpen = new FRadioButton("Open", allowRemote && index != 0);
|
||||||
|
final JPopupMenu menu = new JPopupMenu();
|
||||||
|
radioAiUseSimulation = new JCheckBoxMenuItem("Use Simulation");
|
||||||
|
menu.add(radioAiUseSimulation);
|
||||||
|
radioAi.setComponentPopupMenu(menu);
|
||||||
|
|
||||||
|
radioHuman.addMouseListener(radioMouseAdapter);
|
||||||
|
radioAi.addMouseListener(radioMouseAdapter);
|
||||||
|
radioOpen.addMouseListener(radioMouseAdapter);
|
||||||
|
|
||||||
|
final ButtonGroup tempBtnGroup = new ButtonGroup();
|
||||||
|
tempBtnGroup.add(radioHuman);
|
||||||
|
tempBtnGroup.add(radioAi);
|
||||||
|
tempBtnGroup.add(radioOpen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param index
|
||||||
|
*/
|
||||||
|
private void addHandlersDeckSelector() {
|
||||||
|
deckBtn.setCommand(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Constructed);
|
||||||
|
deckBtn.requestFocusInWindow();
|
||||||
|
PlayerPanel.this.lobby.changePlayerFocus(index, GameType.Constructed);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param index
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private FLabel createNameRandomizer() {
|
||||||
|
final FLabel newNameBtn = new FLabel.Builder().tooltip("Get a new random name").iconInBackground(false)
|
||||||
|
.icon(FSkin.getIcon(FSkinProp.ICO_EDIT)).hoverable(true).opaque(false)
|
||||||
|
.unhoveredAlpha(0.9f).build();
|
||||||
|
newNameBtn.setCommand(new UiCommand() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
String newName = PlayerPanel.this.lobby.getNewName();
|
||||||
|
if (null == newName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
txtPlayerName.setText(newName);
|
||||||
|
|
||||||
|
if (index == 0) {
|
||||||
|
prefs.setPref(FPref.PLAYER_NAME, newName);
|
||||||
|
prefs.save();
|
||||||
|
}
|
||||||
|
txtPlayerName.requestFocus();
|
||||||
|
PlayerPanel.this.lobby.changePlayerFocus(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
newNameBtn.addFocusListener(nameFocusListener);
|
||||||
|
return newNameBtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param index
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private void createNameEditor() {
|
||||||
|
String name;
|
||||||
|
if (index == 0) {
|
||||||
|
name = FModel.getPreferences().getPref(FPref.PLAYER_NAME);
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
name = "Human";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
name = NameGenerator.getRandomName("Any", "Any", lobby.getPlayerNames());
|
||||||
|
}
|
||||||
|
|
||||||
|
txtPlayerName.setText(name);
|
||||||
|
txtPlayerName.setFocusable(true);
|
||||||
|
txtPlayerName.setFont(FSkin.getFont(14));
|
||||||
|
txtPlayerName.addActionListener(lobby.nameListener);
|
||||||
|
txtPlayerName.addFocusListener(nameFocusListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FLabel createCloseButton() {
|
||||||
|
final FLabel closeBtn = new FLabel.Builder().tooltip("Remove").iconInBackground(false)
|
||||||
|
.icon(FSkin.getIcon(FSkinProp.ICO_CLOSE)).hoverable(true).build();
|
||||||
|
closeBtn.setCommand(new Runnable() {
|
||||||
|
@Override public final void run() {
|
||||||
|
if (isRemote() && !SOptionPane.showConfirmDialog("Really kick player?", "Kick", false)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PlayerPanel.this.lobby.removePlayer(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return closeBtn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAvatar() {
|
||||||
|
String[] currentPrefs = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");
|
||||||
|
if (index < currentPrefs.length) {
|
||||||
|
avatarIndex = Integer.parseInt(currentPrefs[index]);
|
||||||
|
avatarLabel.setIcon(FSkin.getAvatars().get(avatarIndex));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setRandomAvatar();
|
||||||
|
}
|
||||||
|
|
||||||
|
avatarLabel.setToolTipText("L-click: Select avatar. R-click: Randomize avatar.");
|
||||||
|
avatarLabel.addFocusListener(avatarFocusListener);
|
||||||
|
avatarLabel.addMouseListener(avatarMouseListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Applies a random avatar, avoiding avatars already used.
|
||||||
|
* @param playerIndex */
|
||||||
|
public void setRandomAvatar() {
|
||||||
|
int random = 0;
|
||||||
|
|
||||||
|
List<Integer> usedAvatars = lobby.getUsedAvatars();
|
||||||
|
do {
|
||||||
|
random = MyRandom.getRandom().nextInt(FSkin.getAvatars().size());
|
||||||
|
} while (usedAvatars.contains(random));
|
||||||
|
setAvatar(random);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAvatar(int newAvatarIndex) {
|
||||||
|
avatarIndex = newAvatarIndex;
|
||||||
|
SkinImage icon = FSkin.getAvatars().get(newAvatarIndex);
|
||||||
|
avatarLabel.setIcon(icon);
|
||||||
|
avatarLabel.repaintSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final FSkin.LineSkinBorder focusedBorder = new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS).alphaColor(255), 3);
|
||||||
|
private final FSkin.LineSkinBorder defaultBorder = new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_THEME).alphaColor(200), 2);
|
||||||
|
|
||||||
|
public void setFocused(boolean focused) {
|
||||||
|
avatarLabel.setBorder(focused ? focusedBorder : defaultBorder);
|
||||||
|
avatarLabel.setHoverable(focused);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAvatarIndex() {
|
||||||
|
return avatarIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlayerName(String string) {
|
||||||
|
txtPlayerName.setText(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlayerName() {
|
||||||
|
return txtPlayerName.getText();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,17 +17,43 @@
|
|||||||
*/
|
*/
|
||||||
package forge.screens.home;
|
package forge.screens.home;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Graphics;
|
||||||
|
import java.awt.Graphics2D;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.SortedMap;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.ScrollPaneConstants;
|
||||||
|
import javax.swing.SwingConstants;
|
||||||
|
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.assets.FSkinProp;
|
import forge.assets.FSkinProp;
|
||||||
import forge.gui.framework.*;
|
import forge.gui.framework.EDocID;
|
||||||
|
import forge.gui.framework.FScreen;
|
||||||
|
import forge.gui.framework.ICDoc;
|
||||||
|
import forge.gui.framework.ILocalRepaint;
|
||||||
|
import forge.gui.framework.IVTopLevelUI;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
|
||||||
import forge.properties.ForgeConstants;
|
import forge.properties.ForgeConstants;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.home.gauntlet.VSubmenuGauntletBuild;
|
import forge.screens.home.gauntlet.VSubmenuGauntletBuild;
|
||||||
import forge.screens.home.gauntlet.VSubmenuGauntletContests;
|
import forge.screens.home.gauntlet.VSubmenuGauntletContests;
|
||||||
import forge.screens.home.gauntlet.VSubmenuGauntletLoad;
|
import forge.screens.home.gauntlet.VSubmenuGauntletLoad;
|
||||||
import forge.screens.home.gauntlet.VSubmenuGauntletQuick;
|
import forge.screens.home.gauntlet.VSubmenuGauntletQuick;
|
||||||
import forge.screens.home.quest.*;
|
import forge.screens.home.online.VSubmenuOnlineLobby;
|
||||||
|
import forge.screens.home.quest.VSubmenuChallenges;
|
||||||
|
import forge.screens.home.quest.VSubmenuDuels;
|
||||||
|
import forge.screens.home.quest.VSubmenuQuestData;
|
||||||
|
import forge.screens.home.quest.VSubmenuQuestDecks;
|
||||||
|
import forge.screens.home.quest.VSubmenuQuestDraft;
|
||||||
|
import forge.screens.home.quest.VSubmenuQuestPrefs;
|
||||||
import forge.screens.home.sanctioned.VSubmenuConstructed;
|
import forge.screens.home.sanctioned.VSubmenuConstructed;
|
||||||
import forge.screens.home.sanctioned.VSubmenuDraft;
|
import forge.screens.home.sanctioned.VSubmenuDraft;
|
||||||
import forge.screens.home.sanctioned.VSubmenuSealed;
|
import forge.screens.home.sanctioned.VSubmenuSealed;
|
||||||
@@ -42,13 +68,6 @@ import forge.toolbox.FSkin;
|
|||||||
import forge.toolbox.FSkin.SkinColor;
|
import forge.toolbox.FSkin.SkinColor;
|
||||||
import forge.toolbox.FSkin.SkinnedPanel;
|
import forge.toolbox.FSkin.SkinnedPanel;
|
||||||
import forge.view.FView;
|
import forge.view.FView;
|
||||||
import net.miginfocom.swing.MigLayout;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Top level view class for home UI drag layout.<br>
|
* Top level view class for home UI drag layout.<br>
|
||||||
|
|||||||
792
forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java
Normal file
792
forge-gui-desktop/src/main/java/forge/screens/home/VLobby.java
Normal file
@@ -0,0 +1,792 @@
|
|||||||
|
package forge.screens.home;
|
||||||
|
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.ItemEvent;
|
||||||
|
import java.awt.event.ItemListener;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import javax.swing.JButton;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.ScrollPaneConstants;
|
||||||
|
import javax.swing.event.ListSelectionEvent;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import forge.UiCommand;
|
||||||
|
import forge.deck.DeckProxy;
|
||||||
|
import forge.deck.DeckType;
|
||||||
|
import forge.deckchooser.DecksComboBoxEvent;
|
||||||
|
import forge.deckchooser.FDeckChooser;
|
||||||
|
import forge.deckchooser.IDecksComboBoxListener;
|
||||||
|
import forge.game.GameType;
|
||||||
|
import forge.game.card.CardView;
|
||||||
|
import forge.gui.CardDetailPanel;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.properties.ForgePreferences;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
|
import forge.toolbox.FCheckBox;
|
||||||
|
import forge.toolbox.FLabel;
|
||||||
|
import forge.toolbox.FList;
|
||||||
|
import forge.toolbox.FOptionPane;
|
||||||
|
import forge.toolbox.FPanel;
|
||||||
|
import forge.toolbox.FScrollPane;
|
||||||
|
import forge.toolbox.FScrollPanel;
|
||||||
|
import forge.toolbox.FSkin;
|
||||||
|
import forge.toolbox.FSkin.SkinImage;
|
||||||
|
import forge.toolbox.FTextField;
|
||||||
|
import forge.util.Lang;
|
||||||
|
import forge.util.NameGenerator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lobby view. View of a number of players at the deck selection stage.
|
||||||
|
*
|
||||||
|
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
||||||
|
*/
|
||||||
|
public class VLobby {
|
||||||
|
|
||||||
|
static final int MAX_PLAYERS = 8;
|
||||||
|
private static final ForgePreferences prefs = FModel.getPreferences();
|
||||||
|
|
||||||
|
// General variables
|
||||||
|
private final boolean allowRemote;
|
||||||
|
private final LblHeader lblTitle = new LblHeader("Sanctioned Format: Constructed");
|
||||||
|
private int activePlayersNum = 2;
|
||||||
|
private int playerWithFocus = 0; // index of the player that currently has focus
|
||||||
|
private PlayerPanel playerPanelWithFocus;
|
||||||
|
private GameType currentGameMode = GameType.Constructed;
|
||||||
|
private List<Integer> teams = new ArrayList<Integer>(MAX_PLAYERS);
|
||||||
|
private List<Integer> archenemyTeams = new ArrayList<Integer>(MAX_PLAYERS);
|
||||||
|
|
||||||
|
private final StartButton btnStart = new StartButton();
|
||||||
|
private final JPanel pnlStart = new JPanel(new MigLayout("insets 0, gap 0, wrap 2"));
|
||||||
|
private final JPanel constructedFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); // Main content frame
|
||||||
|
|
||||||
|
// Variants frame and variables
|
||||||
|
private final Set<GameType> appliedVariants = new TreeSet<GameType>();
|
||||||
|
private final FPanel variantsPanel = new FPanel(new MigLayout("insets 10, gapx 10"));
|
||||||
|
private final VariantCheckBox vntVanguard = new VariantCheckBox(GameType.Vanguard);
|
||||||
|
private final VariantCheckBox vntMomirBasic = new VariantCheckBox(GameType.MomirBasic);
|
||||||
|
private final VariantCheckBox vntCommander = new VariantCheckBox(GameType.Commander);
|
||||||
|
private final VariantCheckBox vntTinyLeaders = new VariantCheckBox(GameType.TinyLeaders);
|
||||||
|
private final VariantCheckBox vntPlanechase = new VariantCheckBox(GameType.Planechase);
|
||||||
|
private final VariantCheckBox vntArchenemy = new VariantCheckBox(GameType.Archenemy);
|
||||||
|
private final VariantCheckBox vntArchenemyRumble = new VariantCheckBox(GameType.ArchenemyRumble);
|
||||||
|
|
||||||
|
// Player frame elements
|
||||||
|
private final JPanel playersFrame = new JPanel(new MigLayout("insets 0, gap 0 5, wrap, hidemode 3"));
|
||||||
|
private final FScrollPanel playersScroll = new FScrollPanel(new MigLayout("insets 0, gap 0, wrap, hidemode 3"), true);
|
||||||
|
private final List<PlayerPanel> playerPanels = new ArrayList<PlayerPanel>(MAX_PLAYERS);
|
||||||
|
|
||||||
|
private final FLabel addPlayerBtn = new FLabel.ButtonBuilder().fontSize(14).text("Add a Player").build();
|
||||||
|
|
||||||
|
// Deck frame elements
|
||||||
|
private final JPanel decksFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap, hidemode 3"));
|
||||||
|
private final List<FDeckChooser> deckChoosers = new ArrayList<FDeckChooser>(8);
|
||||||
|
private final FCheckBox cbSingletons = new FCheckBox("Singleton Mode");
|
||||||
|
private final FCheckBox cbArtifacts = new FCheckBox("Remove Artifacts");
|
||||||
|
|
||||||
|
// Variants
|
||||||
|
private final List<FList<Object>> schemeDeckLists = new ArrayList<FList<Object>>();
|
||||||
|
private final List<FPanel> schemeDeckPanels = new ArrayList<FPanel>(MAX_PLAYERS);
|
||||||
|
private int lastArchenemy = 0;
|
||||||
|
|
||||||
|
private final List<FList<Object>> commanderDeckLists = new ArrayList<FList<Object>>();
|
||||||
|
private final List<FPanel> commanderDeckPanels = new ArrayList<FPanel>(MAX_PLAYERS);
|
||||||
|
|
||||||
|
private final List<FList<Object>> planarDeckLists = new ArrayList<FList<Object>>();
|
||||||
|
private final List<FPanel> planarDeckPanels = new ArrayList<FPanel>(MAX_PLAYERS);
|
||||||
|
|
||||||
|
private final List<FList<Object>> vgdAvatarLists = new ArrayList<FList<Object>>();
|
||||||
|
private final List<FPanel> vgdPanels = new ArrayList<FPanel>(MAX_PLAYERS);
|
||||||
|
private final List<CardDetailPanel> vgdAvatarDetails = new ArrayList<CardDetailPanel>();
|
||||||
|
private final List<PaperCard> vgdAllAvatars = new ArrayList<PaperCard>();
|
||||||
|
private final List<PaperCard> vgdAllAiAvatars = new ArrayList<PaperCard>();
|
||||||
|
private final List<PaperCard> nonRandomHumanAvatars = new ArrayList<PaperCard>();
|
||||||
|
private final List<PaperCard> nonRandomAiAvatars = new ArrayList<PaperCard>();
|
||||||
|
private final Vector<Object> humanListData = new Vector<Object>();
|
||||||
|
private final Vector<Object> aiListData = new Vector<Object>();
|
||||||
|
|
||||||
|
// CTR
|
||||||
|
public VLobby(final boolean allowRemote) {
|
||||||
|
this.allowRemote = allowRemote;
|
||||||
|
lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
//////////////////// Variants Panel ////////////////////
|
||||||
|
|
||||||
|
variantsPanel.setOpaque(false);
|
||||||
|
variantsPanel.add(newLabel("Variants:"));
|
||||||
|
variantsPanel.add(vntVanguard);
|
||||||
|
variantsPanel.add(vntMomirBasic);
|
||||||
|
variantsPanel.add(vntCommander);
|
||||||
|
variantsPanel.add(vntTinyLeaders);
|
||||||
|
variantsPanel.add(vntPlanechase);
|
||||||
|
variantsPanel.add(vntArchenemy);
|
||||||
|
variantsPanel.add(vntArchenemyRumble);
|
||||||
|
|
||||||
|
constructedFrame.add(new FScrollPane(variantsPanel, false, true,
|
||||||
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
||||||
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
|
||||||
|
"w 100%, h 45px!, gapbottom 10px, spanx 2, wrap");
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
///////////////////// Player Panel /////////////////////
|
||||||
|
|
||||||
|
// Construct individual player panels
|
||||||
|
String constraints = "pushx, growx, wrap, hidemode 3";
|
||||||
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||||
|
teams.add(i + 1);
|
||||||
|
archenemyTeams.add(i == 0 ? 1 : 2);
|
||||||
|
|
||||||
|
final PlayerPanel player = new PlayerPanel(this, i, allowRemote);
|
||||||
|
playerPanels.add(player);
|
||||||
|
|
||||||
|
// Populate players panel
|
||||||
|
player.setVisible(i < activePlayersNum);
|
||||||
|
|
||||||
|
playersScroll.add(player, constraints);
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
constraints += ", gaptop 5px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
playerPanelWithFocus = playerPanels.get(0);
|
||||||
|
playerPanelWithFocus.setFocused(true);
|
||||||
|
|
||||||
|
playersFrame.setOpaque(false);
|
||||||
|
playersFrame.add(playersScroll, "w 100%, h 100%-35px");
|
||||||
|
|
||||||
|
addPlayerBtn.setFocusable(true);
|
||||||
|
addPlayerBtn.setCommand(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
addPlayer();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
playersFrame.add(addPlayerBtn, "height 30px!, growx, pushx");
|
||||||
|
|
||||||
|
constructedFrame.add(playersFrame, "gapright 10px, w 50%-5px, growy, pushy");
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////
|
||||||
|
////////////////////// Deck Panel //////////////////////
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||||
|
buildDeckPanel(i);
|
||||||
|
}
|
||||||
|
constructedFrame.add(decksFrame, "w 50%-5px, growy, pushy");
|
||||||
|
constructedFrame.setOpaque(false);
|
||||||
|
decksFrame.setOpaque(false);
|
||||||
|
|
||||||
|
// Start Button
|
||||||
|
pnlStart.setOpaque(false);
|
||||||
|
pnlStart.add(btnStart, "align center");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void populate() {
|
||||||
|
for (final FDeckChooser fdc : deckChoosers) {
|
||||||
|
fdc.populate();
|
||||||
|
fdc.getDecksComboBox().addListener(new IDecksComboBoxListener() {
|
||||||
|
@Override
|
||||||
|
public void deckTypeSelected(DecksComboBoxEvent ev) {
|
||||||
|
playerPanelWithFocus.focusOnAvatar();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
populateDeckPanel(GameType.Constructed);
|
||||||
|
populateVanguardLists();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPlayerInFreeSlot(final String name) {
|
||||||
|
if (activePlayersNum >= MAX_PLAYERS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final PlayerPanel pp : getPlayerPanels()) {
|
||||||
|
if (pp.isVisible() && pp.isOpen()) {
|
||||||
|
addPlayer(pp.getIndex());
|
||||||
|
pp.setPlayerName(name);
|
||||||
|
pp.setRemote(true);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void addPlayer() {
|
||||||
|
if (activePlayersNum >= MAX_PLAYERS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int freeIndex = -1;
|
||||||
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||||
|
if (!playerPanels.get(i).isVisible()) {
|
||||||
|
freeIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addPlayer(freeIndex);
|
||||||
|
}
|
||||||
|
private void addPlayer(final int slot) {
|
||||||
|
playerPanels.get(slot).setVisible(true);
|
||||||
|
|
||||||
|
activePlayersNum++;
|
||||||
|
addPlayerBtn.setEnabled(activePlayersNum < MAX_PLAYERS);
|
||||||
|
|
||||||
|
playerPanels.get(slot).setVisible(true);
|
||||||
|
playerPanels.get(slot).focusOnAvatar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void removePlayer(final int playerIndex) {
|
||||||
|
if (activePlayersNum < playerIndex) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
activePlayersNum--;
|
||||||
|
final FPanel player = playerPanels.get(playerIndex);
|
||||||
|
player.setVisible(false);
|
||||||
|
addPlayerBtn.setEnabled(true);
|
||||||
|
|
||||||
|
//find closest player still in game and give focus
|
||||||
|
int min = MAX_PLAYERS;
|
||||||
|
final List<Integer> participants = getParticipants();
|
||||||
|
if (!participants.isEmpty()) {
|
||||||
|
int closest = 2;
|
||||||
|
|
||||||
|
for (final int participantIndex : getParticipants()) {
|
||||||
|
final int diff = Math.abs(playerIndex - participantIndex);
|
||||||
|
|
||||||
|
if (diff < min) {
|
||||||
|
min = diff;
|
||||||
|
closest = participantIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
changePlayerFocus(closest);
|
||||||
|
playerPanels.get(closest).focusOnAvatar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Builds the actual deck panel layouts for each player.
|
||||||
|
* These are added to a list which can be referenced to populate the deck panel appropriately. */
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
private void buildDeckPanel(final int playerIndex) {
|
||||||
|
String sectionConstraints = "insets 0, gap 0, wrap";
|
||||||
|
String labelConstraints = "gaptop 10px, gapbottom 5px";
|
||||||
|
|
||||||
|
// Main deck
|
||||||
|
final FDeckChooser mainChooser = new FDeckChooser(null, isPlayerAI(playerIndex));
|
||||||
|
mainChooser.initialize();
|
||||||
|
mainChooser.getLstDecks().setSelectCommand(new UiCommand() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
VLobby.this.onDeckClicked(playerIndex, mainChooser.getSelectedDeckType(), mainChooser.getLstDecks().getSelectedItems());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
deckChoosers.add(mainChooser);
|
||||||
|
|
||||||
|
// Scheme deck list
|
||||||
|
FPanel schemeDeckPanel = new FPanel();
|
||||||
|
schemeDeckPanel.setBorderToggle(false);
|
||||||
|
schemeDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
||||||
|
schemeDeckPanel.add(new FLabel.Builder().text("Select Scheme deck:").build(), labelConstraints);
|
||||||
|
FList<Object> schemeDeckList = new FList<Object>();
|
||||||
|
schemeDeckList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
|
||||||
|
FScrollPane scrSchemes = new FScrollPane(schemeDeckList, true,
|
||||||
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
schemeDeckPanel.add(scrSchemes, "grow, push");
|
||||||
|
schemeDeckLists.add(schemeDeckList);
|
||||||
|
schemeDeckPanels.add(schemeDeckPanel);
|
||||||
|
|
||||||
|
// Commander deck list
|
||||||
|
FPanel commanderDeckPanel = new FPanel();
|
||||||
|
commanderDeckPanel.setBorderToggle(false);
|
||||||
|
commanderDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
||||||
|
commanderDeckPanel.add(new FLabel.Builder().text("Select Commander deck:").build(), labelConstraints);
|
||||||
|
FList<Object> commanderDeckList = new FList<Object>();
|
||||||
|
commanderDeckList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
|
||||||
|
FScrollPane scrCommander = new FScrollPane(commanderDeckList, true,
|
||||||
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
commanderDeckPanel.add(scrCommander, "grow, push");
|
||||||
|
commanderDeckLists.add(commanderDeckList);
|
||||||
|
commanderDeckPanels.add(commanderDeckPanel);
|
||||||
|
|
||||||
|
// Planar deck list
|
||||||
|
FPanel planarDeckPanel = new FPanel();
|
||||||
|
planarDeckPanel.setBorderToggle(false);
|
||||||
|
planarDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
||||||
|
planarDeckPanel.add(new FLabel.Builder().text("Select Planar deck:").build(), labelConstraints);
|
||||||
|
FList<Object> planarDeckList = new FList<Object>();
|
||||||
|
planarDeckList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
|
||||||
|
FScrollPane scrPlanes = new FScrollPane(planarDeckList, true,
|
||||||
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
planarDeckPanel.add(scrPlanes, "grow, push");
|
||||||
|
planarDeckLists.add(planarDeckList);
|
||||||
|
planarDeckPanels.add(planarDeckPanel);
|
||||||
|
|
||||||
|
// Vanguard avatar list
|
||||||
|
FPanel vgdDeckPanel = new FPanel();
|
||||||
|
vgdDeckPanel.setBorderToggle(false);
|
||||||
|
|
||||||
|
FList<Object> vgdAvatarList = new FList<Object>();
|
||||||
|
vgdAvatarList.setListData(isPlayerAI(playerIndex) ? aiListData : humanListData);
|
||||||
|
vgdAvatarList.setSelectedIndex(0);
|
||||||
|
vgdAvatarList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
|
vgdAvatarList.addListSelectionListener(vgdLSListener);
|
||||||
|
FScrollPane scrAvatars = new FScrollPane(vgdAvatarList, true,
|
||||||
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
|
||||||
|
CardDetailPanel vgdDetail = new CardDetailPanel();
|
||||||
|
vgdAvatarDetails.add(vgdDetail);
|
||||||
|
|
||||||
|
vgdDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
||||||
|
vgdDeckPanel.add(new FLabel.Builder().text("Select a Vanguard avatar:").build(), labelConstraints);
|
||||||
|
vgdDeckPanel.add(scrAvatars, "grow, push");
|
||||||
|
vgdDeckPanel.add(vgdDetail, "h 200px, pushx, growx, hidemode 3");
|
||||||
|
vgdAvatarLists.add(vgdAvatarList);
|
||||||
|
vgdPanels.add(vgdDeckPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onDeckClicked(int iPlayer, DeckType type, Collection<DeckProxy> selectedDecks) {
|
||||||
|
String text = type.toString() + ": " + Lang.joinHomogenous(selectedDecks, DeckProxy.FN_GET_NAME);
|
||||||
|
playerPanels.get(iPlayer).setDeckSelectorButtonText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Populates the deck panel with the focused player's deck choices. */
|
||||||
|
private void populateDeckPanel(final GameType forGameType) {
|
||||||
|
decksFrame.removeAll();
|
||||||
|
|
||||||
|
if (playerPanelWithFocus.isOpen() || playerPanelWithFocus.isRemote()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GameType.Constructed == forGameType) {
|
||||||
|
decksFrame.add(deckChoosers.get(playerWithFocus), "grow, push");
|
||||||
|
if (deckChoosers.get(playerWithFocus).getSelectedDeckType().toString().contains("Random")) {
|
||||||
|
final String strCheckboxConstraints = "h 30px!, gap 0 20px 0 0";
|
||||||
|
decksFrame.add(cbSingletons, strCheckboxConstraints);
|
||||||
|
decksFrame.add(cbArtifacts, strCheckboxConstraints);
|
||||||
|
}
|
||||||
|
} else if (GameType.Archenemy == forGameType || GameType.ArchenemyRumble == forGameType) {
|
||||||
|
if (isPlayerArchenemy(playerWithFocus)) {
|
||||||
|
decksFrame.add(schemeDeckPanels.get(playerWithFocus), "grow, push");
|
||||||
|
} else {
|
||||||
|
populateDeckPanel(GameType.Constructed);
|
||||||
|
}
|
||||||
|
} else if (GameType.Commander == forGameType || GameType.TinyLeaders == forGameType) {
|
||||||
|
decksFrame.add(commanderDeckPanels.get(playerWithFocus), "grow, push");
|
||||||
|
} else if (GameType.Planechase == forGameType) {
|
||||||
|
decksFrame.add(planarDeckPanels.get(playerWithFocus), "grow, push");
|
||||||
|
} else if (GameType.Vanguard == forGameType) {
|
||||||
|
updateVanguardList(playerWithFocus);
|
||||||
|
decksFrame.add(vgdPanels.get(playerWithFocus), "grow, push");
|
||||||
|
}
|
||||||
|
refreshPanels(false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return {@link javax.swing.JButton} */
|
||||||
|
public JButton getBtnStart() {
|
||||||
|
return this.btnStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LblHeader getLblTitle() { return lblTitle; }
|
||||||
|
public JPanel getConstructedFrame() { return constructedFrame; }
|
||||||
|
public JPanel getPanelStart() { return pnlStart; }
|
||||||
|
public List<FDeckChooser> getDeckChoosers() { return Collections.unmodifiableList(deckChoosers); }
|
||||||
|
|
||||||
|
/** Gets the random deck checkbox for Singletons. */
|
||||||
|
public FCheckBox getCbSingletons() { return cbSingletons; }
|
||||||
|
|
||||||
|
/** Gets the random deck checkbox for Artifacts. */
|
||||||
|
public FCheckBox getCbArtifacts() { return cbArtifacts; }
|
||||||
|
|
||||||
|
public FCheckBox getVntArchenemy() { return vntArchenemy; }
|
||||||
|
public FCheckBox getVntArchenemyRumble() { return vntArchenemyRumble; }
|
||||||
|
public FCheckBox getVntCommander() { return vntCommander; }
|
||||||
|
public FCheckBox getVntMomirBasic() { return vntMomirBasic; }
|
||||||
|
public FCheckBox getVntPlanechase() { return vntPlanechase; }
|
||||||
|
public FCheckBox getVntTinyLeaders() { return vntTinyLeaders; }
|
||||||
|
public FCheckBox getVntVanguard() { return vntVanguard; }
|
||||||
|
|
||||||
|
public int getLastArchenemy() { return lastArchenemy; }
|
||||||
|
public void setLastArchenemy(final int archenemy) { lastArchenemy = archenemy; }
|
||||||
|
|
||||||
|
public final List<PlayerPanel> getPlayerPanels() {
|
||||||
|
return playerPanels;
|
||||||
|
}
|
||||||
|
public final PlayerPanel getPlayerPanelWithFocus() {
|
||||||
|
return playerPanelWithFocus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final FDeckChooser getDeckChooser(int playernum) {
|
||||||
|
return deckChoosers.get(playernum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getTeams() { return Collections.unmodifiableList(teams); }
|
||||||
|
public List<Integer> getArchenemyTeams() { return Collections.unmodifiableList(archenemyTeams); }
|
||||||
|
public GameType getCurrentGameMode() { return currentGameMode; }
|
||||||
|
public void setCurrentGameMode(final GameType mode) { currentGameMode = mode; }
|
||||||
|
|
||||||
|
public boolean isPlayerAI(int playernum) {
|
||||||
|
return playerPanels.get(playernum).isAi();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getAiOptions(int playernum) {
|
||||||
|
if (playerPanels.get(playernum).isSimulatedAi()) {
|
||||||
|
Map<String, String> options = new HashMap<String, String>();
|
||||||
|
options.put("UseSimulation", "True");
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumPlayers() {
|
||||||
|
return activePlayersNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final List<Integer> getParticipants() {
|
||||||
|
final List<Integer> participants = new ArrayList<Integer>(activePlayersNum);
|
||||||
|
for (final PlayerPanel panel : playerPanels) {
|
||||||
|
if (panel.isVisible()) {
|
||||||
|
participants.add(playerPanels.indexOf(panel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return participants;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Revalidates the player and deck sections. Necessary after adding or hiding any panels. */
|
||||||
|
private void refreshPanels(boolean refreshPlayerFrame, boolean refreshDeckFrame) {
|
||||||
|
if (refreshPlayerFrame) {
|
||||||
|
playersScroll.validate();
|
||||||
|
playersScroll.repaint();
|
||||||
|
}
|
||||||
|
if (refreshDeckFrame) {
|
||||||
|
decksFrame.validate();
|
||||||
|
decksFrame.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changePlayerFocus(int newFocusOwner) {
|
||||||
|
changePlayerFocus(newFocusOwner, appliedVariants.contains(currentGameMode) ? currentGameMode : GameType.Constructed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void changePlayerFocus(int newFocusOwner, GameType gType) {
|
||||||
|
playerPanelWithFocus.setFocused(false);
|
||||||
|
playerWithFocus = newFocusOwner;
|
||||||
|
playerPanelWithFocus = playerPanels.get(playerWithFocus);
|
||||||
|
playerPanelWithFocus.setFocused(true);
|
||||||
|
|
||||||
|
playersScroll.getViewport().scrollRectToVisible(playerPanelWithFocus.getBounds());
|
||||||
|
populateDeckPanel(gType);
|
||||||
|
|
||||||
|
refreshPanels(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Saves avatar prefs for players one and two. */
|
||||||
|
void updateAvatarPrefs() {
|
||||||
|
int pOneIndex = playerPanels.get(0).getAvatarIndex();
|
||||||
|
int pTwoIndex = playerPanels.get(1).getAvatarIndex();
|
||||||
|
|
||||||
|
prefs.setPref(FPref.UI_AVATARS, pOneIndex + "," + pTwoIndex);
|
||||||
|
prefs.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Updates the avatars from preferences on update. */
|
||||||
|
public void updatePlayersFromPrefs() {
|
||||||
|
ForgePreferences prefs = FModel.getPreferences();
|
||||||
|
|
||||||
|
// Avatar
|
||||||
|
String[] avatarPrefs = prefs.getPref(FPref.UI_AVATARS).split(",");
|
||||||
|
for (int i = 0; i < avatarPrefs.length; i++) {
|
||||||
|
int avatarIndex = Integer.parseInt(avatarPrefs[i]);
|
||||||
|
playerPanels.get(i).setAvatar(avatarIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name
|
||||||
|
String prefName = prefs.getPref(FPref.PLAYER_NAME);
|
||||||
|
playerPanels.get(0).setPlayerName(StringUtils.isBlank(prefName) ? "Human" : prefName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a pre-styled FLabel component with the specified title. */
|
||||||
|
FLabel newLabel(String title) {
|
||||||
|
return new FLabel.Builder().text(title).fontSize(14).fontStyle(Font.ITALIC).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Integer> getUsedAvatars() {
|
||||||
|
List<Integer> usedAvatars = Arrays.asList(-1,-1,-1,-1,-1,-1,-1,-1);
|
||||||
|
int i = 0;
|
||||||
|
for (PlayerPanel pp : playerPanels) {
|
||||||
|
usedAvatars.set(i++, pp.getAvatarIndex());
|
||||||
|
}
|
||||||
|
return usedAvatars;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String getNewName() {
|
||||||
|
final String title = "Get new random name";
|
||||||
|
final String message = "What type of name do you want to generate?";
|
||||||
|
final SkinImage icon = FOptionPane.QUESTION_ICON;
|
||||||
|
final String[] genderOptions = new String[]{ "Male", "Female", "Any" };
|
||||||
|
final String[] typeOptions = new String[]{ "Fantasy", "Generic", "Any" };
|
||||||
|
|
||||||
|
final int genderIndex = FOptionPane.showOptionDialog(message, title, icon, genderOptions, 2);
|
||||||
|
if (genderIndex < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final int typeIndex = FOptionPane.showOptionDialog(message, title, icon, typeOptions, 2);
|
||||||
|
if (typeIndex < 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String gender = genderOptions[genderIndex];
|
||||||
|
final String type = typeOptions[typeIndex];
|
||||||
|
|
||||||
|
String confirmMsg, newName;
|
||||||
|
List<String> usedNames = getPlayerNames();
|
||||||
|
do {
|
||||||
|
newName = NameGenerator.getRandomName(gender, type, usedNames);
|
||||||
|
confirmMsg = "Would you like to use the name \"" + newName + "\", or try again?";
|
||||||
|
} while (!FOptionPane.showConfirmDialog(confirmMsg, title, "Use this name", "Try again", true));
|
||||||
|
|
||||||
|
return newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> getPlayerNames() {
|
||||||
|
List<String> names = new ArrayList<String>();
|
||||||
|
for (PlayerPanel pp : playerPanels) {
|
||||||
|
names.add(pp.getPlayerName());
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlayerName(int i) {
|
||||||
|
return playerPanels.get(i).getPlayerName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPlayerAvatar(int i) {
|
||||||
|
return playerPanels.get(i).getAvatarIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnoughTeams() {
|
||||||
|
int lastTeam = -1;
|
||||||
|
final List<Integer> teamList = appliedVariants.contains(GameType.Archenemy) ? archenemyTeams : teams;
|
||||||
|
|
||||||
|
for (final int i : getParticipants()) {
|
||||||
|
if (lastTeam == -1) {
|
||||||
|
lastTeam = teamList.get(i);
|
||||||
|
} else if (lastTeam != teamList.get(i)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////
|
||||||
|
//========== Various listeners in build order
|
||||||
|
|
||||||
|
@SuppressWarnings("serial") private class VariantCheckBox extends FCheckBox {
|
||||||
|
private final GameType variantType;
|
||||||
|
|
||||||
|
private VariantCheckBox(GameType variantType0) {
|
||||||
|
super(variantType0.toString());
|
||||||
|
|
||||||
|
variantType = variantType0;
|
||||||
|
|
||||||
|
setToolTipText(variantType.getDescription());
|
||||||
|
|
||||||
|
addItemListener(new ItemListener() {
|
||||||
|
@Override
|
||||||
|
public void itemStateChanged(ItemEvent e) {
|
||||||
|
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||||
|
appliedVariants.add(variantType);
|
||||||
|
currentGameMode = variantType;
|
||||||
|
|
||||||
|
//ensure other necessary variants are unchecked
|
||||||
|
switch (variantType) {
|
||||||
|
case Archenemy:
|
||||||
|
vntArchenemyRumble.setSelected(false);
|
||||||
|
break;
|
||||||
|
case ArchenemyRumble:
|
||||||
|
vntArchenemy.setSelected(false);
|
||||||
|
break;
|
||||||
|
case Commander:
|
||||||
|
vntTinyLeaders.setSelected(false);
|
||||||
|
vntMomirBasic.setSelected(false);
|
||||||
|
break;
|
||||||
|
case TinyLeaders:
|
||||||
|
vntCommander.setSelected(false);
|
||||||
|
vntMomirBasic.setSelected(false);
|
||||||
|
break;
|
||||||
|
case Vanguard:
|
||||||
|
vntMomirBasic.setSelected(false);
|
||||||
|
break;
|
||||||
|
case MomirBasic:
|
||||||
|
vntCommander.setSelected(false);
|
||||||
|
vntVanguard.setSelected(false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appliedVariants.remove(variantType);
|
||||||
|
if (currentGameMode == variantType) {
|
||||||
|
currentGameMode = GameType.Constructed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerPanel pp : playerPanels) {
|
||||||
|
pp.toggleIsPlayerArchenemy();
|
||||||
|
}
|
||||||
|
changePlayerFocus(playerWithFocus, currentGameMode);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ActionListener nameListener = new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
FTextField nField = (FTextField)e.getSource();
|
||||||
|
nField.transferFocus();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/** This listener will look for a vanguard avatar being selected in the lists
|
||||||
|
/ and update the corresponding detail panel. */
|
||||||
|
private ListSelectionListener vgdLSListener = new ListSelectionListener() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
|
int index = vgdAvatarLists.indexOf(e.getSource());
|
||||||
|
Object obj = vgdAvatarLists.get(index).getSelectedValue();
|
||||||
|
PlayerPanel pp = playerPanels.get(index);
|
||||||
|
CardDetailPanel cdp = vgdAvatarDetails.get(index);
|
||||||
|
|
||||||
|
if (obj instanceof PaperCard) {
|
||||||
|
pp.setVanguardButtonText(((PaperCard) obj).getName());
|
||||||
|
cdp.setCard(CardView.getCardForUi((PaperCard) obj));
|
||||||
|
cdp.setVisible(true);
|
||||||
|
refreshPanels(false, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pp.setVanguardButtonText((String) obj);
|
||||||
|
cdp.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/////////////////////////////////////
|
||||||
|
//========== METHODS FOR VARIANTS
|
||||||
|
|
||||||
|
public Set<GameType> getAppliedVariants() {
|
||||||
|
return Collections.unmodifiableSet(appliedVariants);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTeam(final int playerIndex) {
|
||||||
|
return appliedVariants.contains(GameType.Archenemy) ? archenemyTeams.get(playerIndex) : teams.get(playerIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the list of planar deck lists. */
|
||||||
|
public List<FList<Object>> getPlanarDeckLists() {
|
||||||
|
return planarDeckLists;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the list of commander deck lists. */
|
||||||
|
public List<FList<Object>> getCommanderDeckLists() {
|
||||||
|
return commanderDeckLists;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the list of scheme deck lists. */
|
||||||
|
public List<FList<Object>> getSchemeDeckLists() {
|
||||||
|
return schemeDeckLists;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPlayerArchenemy(final int playernum) {
|
||||||
|
return playerPanels.get(playernum).isArchenemy();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the list of Vanguard avatar lists. */
|
||||||
|
public List<FList<Object>> getVanguardLists() {
|
||||||
|
return vgdAvatarLists;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return all the Vanguard avatars. */
|
||||||
|
public Iterable<PaperCard> getAllAvatars() {
|
||||||
|
if (vgdAllAvatars.isEmpty()) {
|
||||||
|
for (PaperCard c : FModel.getMagicDb().getVariantCards().getAllCards()) {
|
||||||
|
if (c.getRules().getType().isVanguard()) {
|
||||||
|
vgdAllAvatars.add(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vgdAllAvatars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the Vanguard avatars not flagged RemAIDeck. */
|
||||||
|
public List<PaperCard> getAllAiAvatars() {
|
||||||
|
return vgdAllAiAvatars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the Vanguard avatars not flagged RemRandomDeck. */
|
||||||
|
public List<PaperCard> getNonRandomHumanAvatars() {
|
||||||
|
return nonRandomHumanAvatars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the Vanguard avatars not flagged RemAIDeck or RemRandomDeck. */
|
||||||
|
public List<PaperCard> getNonRandomAiAvatars() {
|
||||||
|
return nonRandomAiAvatars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Populate vanguard lists. */
|
||||||
|
private void populateVanguardLists() {
|
||||||
|
humanListData.add("Use deck's default avatar (random if unavailable)");
|
||||||
|
humanListData.add("Random");
|
||||||
|
aiListData.add("Use deck's default avatar (random if unavailable)");
|
||||||
|
aiListData.add("Random");
|
||||||
|
for (PaperCard cp : getAllAvatars()) {
|
||||||
|
humanListData.add(cp);
|
||||||
|
if (!cp.getRules().getAiHints().getRemRandomDecks()) {
|
||||||
|
nonRandomHumanAvatars.add(cp);
|
||||||
|
}
|
||||||
|
if (!cp.getRules().getAiHints().getRemAIDecks()) {
|
||||||
|
aiListData.add(cp);
|
||||||
|
vgdAllAiAvatars.add(cp);
|
||||||
|
if (!cp.getRules().getAiHints().getRemRandomDecks()) {
|
||||||
|
nonRandomAiAvatars.add(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** update vanguard list. */
|
||||||
|
public void updateVanguardList(int playerIndex) {
|
||||||
|
FList<Object> vgdList = getVanguardLists().get(playerIndex);
|
||||||
|
Object lastSelection = vgdList.getSelectedValue();
|
||||||
|
vgdList.setListData(isPlayerAI(playerIndex) ? aiListData : humanListData);
|
||||||
|
if (null != lastSelection) {
|
||||||
|
vgdList.setSelectedValue(lastSelection, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-1 == vgdList.getSelectedIndex()) {
|
||||||
|
vgdList.setSelectedIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package forge.screens.home.online;
|
||||||
|
|
||||||
|
import forge.UiCommand;
|
||||||
|
import forge.gui.framework.ICDoc;
|
||||||
|
import forge.screens.home.CLobby;
|
||||||
|
|
||||||
|
public enum COnlineLobby implements ICDoc {
|
||||||
|
SINGLETON_INSTANCE;
|
||||||
|
|
||||||
|
private final VOnlineLobby view = VOnlineLobby.SINGLETON_INSTANCE;
|
||||||
|
private final CLobby lobby = new CLobby(view.getLobby());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.gui.home.ICSubmenu#initialize()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
lobby.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.gui.home.ICSubmenu#initialize()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void initialize() {
|
||||||
|
lobby.initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.gui.framework.ICDoc#getCommandOnSelect()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public UiCommand getCommandOnSelect() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,48 +1,93 @@
|
|||||||
package forge.screens.home.online;
|
package forge.screens.home.online;
|
||||||
|
|
||||||
import forge.UiCommand;
|
|
||||||
import forge.gui.framework.ICDoc;
|
|
||||||
import forge.menus.IMenuProvider;
|
|
||||||
import forge.menus.MenuUtil;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.swing.JMenu;
|
||||||
|
|
||||||
|
import forge.GuiBase;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.UiCommand;
|
||||||
|
import forge.game.GameRules;
|
||||||
|
import forge.game.GameType;
|
||||||
|
import forge.gui.FNetOverlay;
|
||||||
|
import forge.gui.framework.FScreen;
|
||||||
|
import forge.gui.framework.ICDoc;
|
||||||
|
import forge.menus.IMenuProvider;
|
||||||
|
import forge.menus.MenuUtil;
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.net.FGameClient;
|
||||||
|
import forge.net.FServerManager;
|
||||||
|
import forge.net.game.client.ILobbyListener;
|
||||||
|
import forge.net.game.server.RemoteClient;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
|
import forge.screens.home.sanctioned.ConstructedGameMenu;
|
||||||
|
|
||||||
public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
||||||
SINGLETON_INSTANCE;
|
SINGLETON_INSTANCE;
|
||||||
|
|
||||||
//private final VSubmenuOnlineLobby view = VSubmenuOnlineLobby.SINGLETON_INSTANCE;
|
final void host(final int portNumber) {
|
||||||
|
FServerManager.getInstance().startServer(portNumber);
|
||||||
@Override
|
FServerManager.getInstance().registerLobbyListener(new ILobbyListener() {
|
||||||
public void update() {
|
@Override public final void logout(final RemoteClient client) {
|
||||||
MenuUtil.setMenuProvider(this);
|
}
|
||||||
|
@Override public final void login(final RemoteClient client) {
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
VOnlineLobby.SINGLETON_INSTANCE.getLobby().addPlayerInFreeSlot(client.getUsername());
|
||||||
@Override
|
}
|
||||||
public void run() {
|
@Override public final void message(final String source, final String message) {
|
||||||
|
FNetOverlay.SINGLETON_INSTANCE.addMessage(source, message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
FServerManager.getInstance().hostGame(new GameRules(GameType.Constructed));
|
||||||
|
|
||||||
|
Singletons.getControl().setCurrentScreen(FScreen.ONLINE_LOBBY);
|
||||||
|
FNetOverlay.SINGLETON_INSTANCE.showUp("Hosting game");
|
||||||
|
}
|
||||||
|
|
||||||
|
final void join(final String hostname, final int port) {
|
||||||
|
final FGameClient client = new FGameClient(FModel.getPreferences().getPref(FPref.PLAYER_NAME), "0", GuiBase.getInterface().getNewGuiGame());
|
||||||
|
FNetOverlay.SINGLETON_INSTANCE.setGameClient(client);
|
||||||
|
client.connect(hostname, port);
|
||||||
|
|
||||||
|
Singletons.getControl().setCurrentScreen(FScreen.ONLINE_LOBBY);
|
||||||
|
FNetOverlay.SINGLETON_INSTANCE.showUp(String.format("Connected to %s:%s", hostname, port));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register() {
|
public void register() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.gui.home.ICSubmenu#initialize()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void update() {
|
||||||
|
MenuUtil.setMenuProvider(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.gui.home.ICSubmenu#initialize()
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.gui.framework.ICDoc#getCommandOnSelect()
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public UiCommand getCommandOnSelect() {
|
public UiCommand getCommandOnSelect() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.gui.menubar.IMenuProvider#getMenus()
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<JMenu> getMenus() {
|
public List<JMenu> getMenus() {
|
||||||
List<JMenu> menus = new ArrayList<JMenu>();
|
List<JMenu> menus = new ArrayList<JMenu>();
|
||||||
|
menus.add(ConstructedGameMenu.getMenu());
|
||||||
return menus;
|
return menus;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package forge.screens.home.online;
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
import forge.deckchooser.DecksComboBoxEvent;
|
||||||
|
import forge.deckchooser.FDeckChooser;
|
||||||
|
import forge.deckchooser.IDecksComboBoxListener;
|
||||||
|
import forge.gui.framework.DragCell;
|
||||||
|
import forge.gui.framework.DragTab;
|
||||||
|
import forge.gui.framework.EDocID;
|
||||||
|
import forge.gui.framework.FScreen;
|
||||||
|
import forge.gui.framework.IVDoc;
|
||||||
|
import forge.gui.framework.IVTopLevelUI;
|
||||||
|
import forge.screens.home.VLobby;
|
||||||
|
import forge.toolbox.FPanel;
|
||||||
|
import forge.util.gui.SOptionPane;
|
||||||
|
import forge.view.FView;
|
||||||
|
|
||||||
|
public enum VOnlineLobby implements IVDoc<COnlineLobby>, IVTopLevelUI {
|
||||||
|
SINGLETON_INSTANCE;
|
||||||
|
|
||||||
|
private DragCell parentCell;
|
||||||
|
private final DragTab tab = new DragTab("Lobby");
|
||||||
|
|
||||||
|
// General variables
|
||||||
|
private final VLobby lobby;
|
||||||
|
|
||||||
|
private VOnlineLobby() {
|
||||||
|
this.lobby = new VLobby(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
VLobby getLobby() {
|
||||||
|
return lobby;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void populate() {
|
||||||
|
final JPanel outerContainer = FView.SINGLETON_INSTANCE.getPnlInsets();
|
||||||
|
outerContainer.removeAll();
|
||||||
|
final FPanel container = new FPanel(new MigLayout("insets 0, gap 0, wrap 1, ax right"));
|
||||||
|
outerContainer.add(container);
|
||||||
|
lobby.getLblTitle().setText("Online Multiplayer: Lobby");
|
||||||
|
container.add(lobby.getLblTitle(), "w 80%, h 40px!, gap 0 0 15px 15px, span 2, al right, pushx");
|
||||||
|
|
||||||
|
for (final FDeckChooser fdc : lobby.getDeckChoosers()) {
|
||||||
|
fdc.populate();
|
||||||
|
fdc.getDecksComboBox().addListener(new IDecksComboBoxListener() {
|
||||||
|
@Override public final void deckTypeSelected(final DecksComboBoxEvent ev) {
|
||||||
|
lobby.getPlayerPanelWithFocus().focusOnAvatar();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
container.add(lobby.getConstructedFrame(), "gap 20px 20px 20px 0px, push, grow");
|
||||||
|
container.add(lobby.getPanelStart(), "gap 0 0 3.5%! 3.5%!, ax center");
|
||||||
|
|
||||||
|
if (container.isShowing()) {
|
||||||
|
container.validate();
|
||||||
|
container.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
lobby.changePlayerFocus(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EDocID getDocumentID() {
|
||||||
|
return EDocID.ONLINE_LOBBY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DragTab getTabLabel() {
|
||||||
|
return tab;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public COnlineLobby getLayoutControl() {
|
||||||
|
return COnlineLobby.SINGLETON_INSTANCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParentCell(final DragCell cell0) {
|
||||||
|
parentCell = cell0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DragCell getParentCell() {
|
||||||
|
return parentCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void instantiate() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onSwitching(final FScreen fromScreen, final FScreen toScreen) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onClosing(final FScreen screen) {
|
||||||
|
return SOptionPane.showConfirmDialog("Leave lobby?", "Leave");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,65 +1,85 @@
|
|||||||
package forge.screens.home.online;
|
package forge.screens.home.online;
|
||||||
|
|
||||||
import javax.swing.JButton;
|
import java.awt.event.ActionEvent;
|
||||||
import javax.swing.JPanel;
|
import java.awt.event.ActionListener;
|
||||||
import net.miginfocom.swing.MigLayout;
|
|
||||||
|
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import net.miginfocom.swing.MigLayout;
|
||||||
import forge.gui.framework.DragCell;
|
import forge.gui.framework.DragCell;
|
||||||
import forge.gui.framework.DragTab;
|
import forge.gui.framework.DragTab;
|
||||||
import forge.gui.framework.EDocID;
|
import forge.gui.framework.EDocID;
|
||||||
|
import forge.properties.ForgeConstants;
|
||||||
import forge.screens.home.EMenuGroup;
|
import forge.screens.home.EMenuGroup;
|
||||||
import forge.screens.home.IVSubmenu;
|
import forge.screens.home.IVSubmenu;
|
||||||
import forge.screens.home.LblHeader;
|
|
||||||
import forge.screens.home.StartButton;
|
|
||||||
import forge.screens.home.VHomeUI;
|
import forge.screens.home.VHomeUI;
|
||||||
import forge.toolbox.FSkin;
|
import forge.toolbox.FButton;
|
||||||
|
import forge.toolbox.FLabel;
|
||||||
|
import forge.toolbox.FPanel;
|
||||||
|
import forge.toolbox.FTextField;
|
||||||
|
|
||||||
public enum VSubmenuOnlineLobby implements IVSubmenu<CSubmenuOnlineLobby> {
|
public enum VSubmenuOnlineLobby implements IVSubmenu<CSubmenuOnlineLobby> {
|
||||||
SINGLETON_INSTANCE;
|
SINGLETON_INSTANCE;
|
||||||
|
|
||||||
private DragCell parentCell;
|
private DragCell parentCell;
|
||||||
private final DragTab tab = new DragTab("Lobby");
|
private final DragTab tab = new DragTab("Network Games");
|
||||||
|
|
||||||
// General variables
|
|
||||||
private final LblHeader lblTitle = new LblHeader("Online Multiplayer: Lobby");
|
|
||||||
|
|
||||||
private final StartButton btnStart = new StartButton();
|
|
||||||
private final JPanel pnlStart = new JPanel(new MigLayout("insets 0, gap 0, wrap 2"));
|
|
||||||
private final JPanel frame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); // Main content frame
|
|
||||||
|
|
||||||
private VSubmenuOnlineLobby() {
|
private VSubmenuOnlineLobby() {
|
||||||
lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
|
|
||||||
|
|
||||||
frame.setOpaque(false);
|
|
||||||
pnlStart.setOpaque(false);
|
|
||||||
pnlStart.add(btnStart, "align center");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void populate() {
|
public void populate() {
|
||||||
JPanel container = VHomeUI.SINGLETON_INSTANCE.getPnlDisplay();
|
final JPanel container = VHomeUI.SINGLETON_INSTANCE.getPnlDisplay();
|
||||||
|
|
||||||
container.removeAll();
|
container.removeAll();
|
||||||
container.setLayout(new MigLayout("insets 0, gap 0, wrap 1, ax right"));
|
container.setLayout(new MigLayout("fill", "[grow][grow]", "[grow]"));
|
||||||
container.add(lblTitle, "w 80%, h 40px!, gap 0 0 15px 15px, span 2, al right, pushx");
|
|
||||||
|
|
||||||
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(frame, "gap 20px 20px 20px 0px, push, grow");
|
final FPanel pnlHost = new FPanel(new MigLayout("insets 5px 10% 5px 10%, wrap 2", "[grow,l]10[grow,r]", "[grow,c][grow,c]"));
|
||||||
VHomeUI.SINGLETON_INSTANCE.getPnlDisplay().add(pnlStart, "gap 0 0 3.5%! 3.5%!, ax center");
|
container.add(pnlHost, "west, w 50%!, h 100%!");
|
||||||
|
|
||||||
if (container.isShowing()) {
|
final FLabel lblServerPort = new FLabel.Builder().text("Server port").build();
|
||||||
container.validate();
|
pnlHost.add(lblServerPort, "w 100!, h 50!");
|
||||||
container.repaint();
|
|
||||||
}
|
final FTextField txtServerPort = new FTextField.Builder().text(String.valueOf(ForgeConstants.SERVER_PORT_NUMBER)).build();
|
||||||
|
txtServerPort.setEditable(false);
|
||||||
|
pnlHost.add(txtServerPort, "wrap");
|
||||||
|
|
||||||
|
final FButton btnHost = new FButton("Host");
|
||||||
|
btnHost.addActionListener(new ActionListener() {
|
||||||
|
@Override public final void actionPerformed(final ActionEvent e) {
|
||||||
|
getLayoutControl().host(Integer.parseInt(txtServerPort.getText()));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
pnlHost.add(btnHost, "span 2, wrap, w 200!, h 50!");
|
||||||
|
|
||||||
public JButton getBtnStart() {
|
final FPanel pnlJoin = new FPanel(new MigLayout("insets 5px 10% 5px 10%, wrap 2", "[grow,l]10[grow,r]", "[grow,c][grow,c][grow,c]"));
|
||||||
return btnStart;
|
container.add(pnlJoin, "east, w 50%!, h 100%!");
|
||||||
|
|
||||||
|
final FLabel lblJoinHost = new FLabel.Builder().text("Hostname").build();
|
||||||
|
pnlJoin.add(lblJoinHost, "w 100!, h 50!");
|
||||||
|
|
||||||
|
final FTextField txtJoinHost = new FTextField.Builder().text("localhost").build();
|
||||||
|
pnlJoin.add(txtJoinHost, "wrap, w 250!");
|
||||||
|
|
||||||
|
final FLabel lblJoinPort = new FLabel.Builder().text("Host port").build();
|
||||||
|
pnlJoin.add(lblJoinPort, "w 100!, h 50!");
|
||||||
|
|
||||||
|
final FTextField txtJoinPort = new FTextField.Builder().text(String.valueOf(ForgeConstants.SERVER_PORT_NUMBER)).build();
|
||||||
|
txtJoinPort.setEditable(false);
|
||||||
|
pnlJoin.add(txtJoinPort, "wrap");
|
||||||
|
|
||||||
|
final FButton btnJoin = new FButton("Join");
|
||||||
|
btnJoin.addActionListener(new ActionListener() {
|
||||||
|
@Override public final void actionPerformed(final ActionEvent e) {
|
||||||
|
getLayoutControl().join(txtJoinHost.getText(), Integer.parseInt(txtJoinPort.getText()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
pnlJoin.add(btnJoin, "span 2, w 200!, h 50!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EMenuGroup getGroupEnum() {
|
public EMenuGroup getGroupEnum() {
|
||||||
return null; //EMenuGroup.ONLINE;
|
return EMenuGroup.ONLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -69,12 +89,12 @@ public enum VSubmenuOnlineLobby implements IVSubmenu<CSubmenuOnlineLobby> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EDocID getItemEnum() {
|
public EDocID getItemEnum() {
|
||||||
return EDocID.HOME_LOBBY;
|
return getDocumentID();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EDocID getDocumentID() {
|
public EDocID getDocumentID() {
|
||||||
return EDocID.HOME_LOBBY;
|
return EDocID.HOME_NETWORK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,46 +1,15 @@
|
|||||||
package forge.screens.home.sanctioned;
|
package forge.screens.home.sanctioned;
|
||||||
|
|
||||||
import forge.GuiBase;
|
|
||||||
import forge.LobbyPlayer;
|
|
||||||
import forge.UiCommand;
|
|
||||||
import forge.deck.CardPool;
|
|
||||||
import forge.deck.Deck;
|
|
||||||
import forge.deck.DeckFormat;
|
|
||||||
import forge.deck.DeckSection;
|
|
||||||
import forge.deck.DeckType;
|
|
||||||
import forge.deck.DeckgenUtil;
|
|
||||||
import forge.game.GameType;
|
|
||||||
import forge.game.player.RegisteredPlayer;
|
|
||||||
import forge.gui.GuiDialog;
|
|
||||||
import forge.gui.framework.ICDoc;
|
|
||||||
import forge.interfaces.IGuiGame;
|
|
||||||
import forge.item.PaperCard;
|
|
||||||
import forge.match.HostedMatch;
|
|
||||||
import forge.menus.IMenuProvider;
|
|
||||||
import forge.menus.MenuUtil;
|
|
||||||
import forge.model.CardCollections;
|
|
||||||
import forge.model.FModel;
|
|
||||||
import forge.player.GamePlayerUtil;
|
|
||||||
import forge.properties.ForgePreferences;
|
|
||||||
import forge.properties.ForgePreferences.FPref;
|
|
||||||
import forge.toolbox.FList;
|
|
||||||
import forge.toolbox.FOptionPane;
|
|
||||||
import forge.util.Aggregates;
|
|
||||||
import forge.util.storage.IStorage;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import com.beust.jcommander.internal.Maps;
|
|
||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.ActionListener;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Vector;
|
|
||||||
|
|
||||||
//import forge.gui.home.variant.VSubmenuVanguard;
|
import javax.swing.JMenu;
|
||||||
|
|
||||||
|
import forge.UiCommand;
|
||||||
|
import forge.gui.framework.ICDoc;
|
||||||
|
import forge.menus.IMenuProvider;
|
||||||
|
import forge.menus.MenuUtil;
|
||||||
|
import forge.screens.home.CLobby;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls the constructed submenu in the home UI.
|
* Controls the constructed submenu in the home UI.
|
||||||
@@ -53,6 +22,7 @@ public enum CSubmenuConstructed implements ICDoc, IMenuProvider {
|
|||||||
SINGLETON_INSTANCE;
|
SINGLETON_INSTANCE;
|
||||||
|
|
||||||
private final VSubmenuConstructed view = VSubmenuConstructed.SINGLETON_INSTANCE;
|
private final VSubmenuConstructed view = VSubmenuConstructed.SINGLETON_INSTANCE;
|
||||||
|
private final CLobby lobby = new CLobby(view.getLobby());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void register() {
|
public void register() {
|
||||||
@@ -64,85 +34,7 @@ public enum CSubmenuConstructed implements ICDoc, IMenuProvider {
|
|||||||
@Override
|
@Override
|
||||||
public void update() {
|
public void update() {
|
||||||
MenuUtil.setMenuProvider(this);
|
MenuUtil.setMenuProvider(this);
|
||||||
|
lobby.update();
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
|
||||||
@Override public void run() {
|
|
||||||
final CardCollections cColl = FModel.getDecks();
|
|
||||||
FList<Object> deckList;
|
|
||||||
Vector<Object> listData;
|
|
||||||
Object val;
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
// Commander: reinit deck list and restore last selections (if any)
|
|
||||||
deckList = view.getCommanderDeckLists().get(i);
|
|
||||||
listData = new Vector<Object>();
|
|
||||||
listData.add("Generate");
|
|
||||||
if (cColl.getCommander().size() > 0) {
|
|
||||||
listData.add("Random");
|
|
||||||
for (Deck comDeck : cColl.getCommander()) {
|
|
||||||
listData.add(comDeck);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val = deckList.getSelectedValue();
|
|
||||||
deckList.setListData(listData);
|
|
||||||
if (null != val) {
|
|
||||||
deckList.setSelectedValue(val, true);
|
|
||||||
}
|
|
||||||
if (-1 == deckList.getSelectedIndex()) {
|
|
||||||
deckList.setSelectedIndex(0);
|
|
||||||
} // End Commander
|
|
||||||
|
|
||||||
// Archenemy: reinit deck list and restore last selections (if any)
|
|
||||||
deckList = view.getSchemeDeckLists().get(i);
|
|
||||||
listData = new Vector<Object>();
|
|
||||||
listData.add("Use deck's scheme section (random if unavailable)");
|
|
||||||
listData.add("Generate");
|
|
||||||
if (cColl.getScheme().size() > 0) {
|
|
||||||
listData.add("Random");
|
|
||||||
for (Deck schemeDeck : cColl.getScheme()) {
|
|
||||||
listData.add(schemeDeck);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val = deckList.getSelectedValue();
|
|
||||||
deckList.setListData(listData);
|
|
||||||
if (null != val) {
|
|
||||||
deckList.setSelectedValue(val, true);
|
|
||||||
}
|
|
||||||
if (-1 == deckList.getSelectedIndex()) {
|
|
||||||
deckList.setSelectedIndex(0);
|
|
||||||
} // End Archenemy
|
|
||||||
|
|
||||||
// Planechase: reinit deck lists and restore last selections (if any)
|
|
||||||
deckList = view.getPlanarDeckLists().get(i);
|
|
||||||
listData = new Vector<Object>();
|
|
||||||
|
|
||||||
listData.add("Use deck's planes section (random if unavailable)");
|
|
||||||
listData.add("Generate");
|
|
||||||
if (cColl.getPlane().size() > 0) {
|
|
||||||
listData.add("Random");
|
|
||||||
for (Deck planarDeck : cColl.getPlane()) {
|
|
||||||
listData.add(planarDeck);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val = deckList.getSelectedValue();
|
|
||||||
deckList.setListData(listData);
|
|
||||||
if (null != val) {
|
|
||||||
deckList.setSelectedValue(val, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (-1 == deckList.getSelectedIndex()) {
|
|
||||||
deckList.setSelectedIndex(0);
|
|
||||||
} // End Planechase
|
|
||||||
|
|
||||||
view.updateVanguardList(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
// General updates when switching back to this view
|
|
||||||
view.updatePlayersFromPrefs();
|
|
||||||
view.getBtnStart().requestFocusInWindow();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
@@ -150,248 +42,7 @@ public enum CSubmenuConstructed implements ICDoc, IMenuProvider {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
view.getDeckChooser(0).initialize(FPref.CONSTRUCTED_P1_DECK_STATE, DeckType.PRECONSTRUCTED_DECK);
|
lobby.initialize();
|
||||||
view.getDeckChooser(1).initialize(FPref.CONSTRUCTED_P2_DECK_STATE, DeckType.COLOR_DECK);
|
|
||||||
view.getDeckChooser(2).initialize(FPref.CONSTRUCTED_P3_DECK_STATE, DeckType.COLOR_DECK);
|
|
||||||
view.getDeckChooser(3).initialize(FPref.CONSTRUCTED_P4_DECK_STATE, DeckType.COLOR_DECK);
|
|
||||||
view.getDeckChooser(4).initialize(FPref.CONSTRUCTED_P5_DECK_STATE, DeckType.COLOR_DECK);
|
|
||||||
view.getDeckChooser(5).initialize(FPref.CONSTRUCTED_P6_DECK_STATE, DeckType.COLOR_DECK);
|
|
||||||
view.getDeckChooser(6).initialize(FPref.CONSTRUCTED_P7_DECK_STATE, DeckType.COLOR_DECK);
|
|
||||||
view.getDeckChooser(7).initialize(FPref.CONSTRUCTED_P8_DECK_STATE, DeckType.COLOR_DECK);
|
|
||||||
|
|
||||||
// Start button event handling
|
|
||||||
view.getBtnStart().addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent arg0) {
|
|
||||||
startGame(view.getAppliedVariants());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
final ForgePreferences prefs = FModel.getPreferences();
|
|
||||||
// Checkbox event handling
|
|
||||||
view.getCbSingletons().addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent arg0) {
|
|
||||||
prefs.setPref(FPref.DECKGEN_SINGLETONS, String.valueOf(view.getCbSingletons().isSelected()));
|
|
||||||
prefs.save();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
view.getCbArtifacts().addActionListener(new ActionListener() {
|
|
||||||
@Override
|
|
||||||
public void actionPerformed(final ActionEvent arg0) {
|
|
||||||
prefs.setPref(FPref.DECKGEN_ARTIFACTS, String.valueOf(view.getCbArtifacts().isSelected()));
|
|
||||||
prefs.save();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Pre-select checkboxes
|
|
||||||
view.getCbSingletons().setSelected(prefs.getPrefBoolean(FPref.DECKGEN_SINGLETONS));
|
|
||||||
view.getCbArtifacts().setSelected(prefs.getPrefBoolean(FPref.DECKGEN_ARTIFACTS));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Starts a match with the applied variants. */
|
|
||||||
private void startGame(final Set<GameType> variantTypes) {
|
|
||||||
if (!view.isEnoughTeams()) {
|
|
||||||
FOptionPane.showMessageDialog("There are not enough teams! Please adjust team allocations.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final int i : view.getParticipants()) {
|
|
||||||
if (view.getDeckChooser(i).getPlayer() == null) {
|
|
||||||
FOptionPane.showMessageDialog("Please specify a deck for " + view.getPlayerName(i));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} // Is it even possible anymore? I think current implementation assigns decks automatically.
|
|
||||||
|
|
||||||
GameType autoGenerateVariant = null;
|
|
||||||
boolean isCommanderMatch = false;
|
|
||||||
boolean isTinyLeadersMatch = false;
|
|
||||||
if (!variantTypes.isEmpty()) {
|
|
||||||
isTinyLeadersMatch = variantTypes.contains(GameType.TinyLeaders);
|
|
||||||
isCommanderMatch = isTinyLeadersMatch || variantTypes.contains(GameType.Commander);
|
|
||||||
if (!isCommanderMatch) {
|
|
||||||
for (GameType variant : variantTypes) {
|
|
||||||
if (variant.isAutoGenerated()) {
|
|
||||||
autoGenerateVariant = variant;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean checkLegality = FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY);
|
|
||||||
|
|
||||||
//Auto-generated decks don't need to be checked here
|
|
||||||
//Commander deck replaces regular deck and is checked later
|
|
||||||
if (checkLegality && autoGenerateVariant == null && !isCommanderMatch) {
|
|
||||||
for (final int i : view.getParticipants()) {
|
|
||||||
String name = view.getPlayerName(i);
|
|
||||||
String errMsg = GameType.Constructed.getDeckFormat().getDeckConformanceProblem(view.getDeckChooser(i).getPlayer().getDeck());
|
|
||||||
if (null != errMsg) {
|
|
||||||
FOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid Deck");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final List<RegisteredPlayer> players = new ArrayList<RegisteredPlayer>();
|
|
||||||
final Map<RegisteredPlayer, IGuiGame> guis = Maps.newHashMap();
|
|
||||||
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
|
||||||
for (final int i : view.getParticipants()) {
|
|
||||||
final String name = view.getPlayerName(i);
|
|
||||||
final boolean isAI = view.isPlayerAI(i);
|
|
||||||
final LobbyPlayer lobbyPlayer = isAI
|
|
||||||
? GamePlayerUtil.createAiPlayer(name, view.getPlayerAvatar(i), view.getAiOptions(i))
|
|
||||||
: GamePlayerUtil.getGuiPlayer(name, i);
|
|
||||||
RegisteredPlayer rp = view.getDeckChooser(i).getPlayer();
|
|
||||||
|
|
||||||
if (variantTypes.isEmpty()) {
|
|
||||||
rp.setTeamNumber(view.getTeam(i));
|
|
||||||
players.add(rp.setPlayer(lobbyPlayer));
|
|
||||||
} else {
|
|
||||||
Deck deck = null;
|
|
||||||
PaperCard vanguardAvatar = null;
|
|
||||||
if (isCommanderMatch) {
|
|
||||||
final Object selected = view.getCommanderDeckLists().get(i).getSelectedValue();
|
|
||||||
if (selected instanceof String) {
|
|
||||||
final String sel = (String) selected;
|
|
||||||
final IStorage<Deck> comDecks = FModel.getDecks().getCommander();
|
|
||||||
if (sel.equals("Random") && comDecks.size() > 0) {
|
|
||||||
deck = Aggregates.random(comDecks);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
deck = (Deck) selected;
|
|
||||||
}
|
|
||||||
GameType commanderGameType = isTinyLeadersMatch ? GameType.TinyLeaders : GameType.Commander;
|
|
||||||
if (deck == null) { //Can be null if player deselects the list selection or chose Generate
|
|
||||||
deck = DeckgenUtil.generateCommanderDeck(isAI, commanderGameType);
|
|
||||||
}
|
|
||||||
if (checkLegality) {
|
|
||||||
String errMsg = commanderGameType.getDeckFormat().getDeckConformanceProblem(deck);
|
|
||||||
if (null != errMsg) {
|
|
||||||
FOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid " + commanderGameType + " Deck");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (autoGenerateVariant != null) {
|
|
||||||
deck = autoGenerateVariant.autoGenerateDeck(rp);
|
|
||||||
CardPool avatarPool = deck.get(DeckSection.Avatar);
|
|
||||||
if (avatarPool != null) {
|
|
||||||
vanguardAvatar = avatarPool.get(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialise variables for other variants
|
|
||||||
deck = deck == null ? rp.getDeck() : deck;
|
|
||||||
Iterable<PaperCard> schemes = null;
|
|
||||||
final boolean playerIsArchenemy = view.isPlayerArchenemy(i);
|
|
||||||
Iterable<PaperCard> planes = null;
|
|
||||||
|
|
||||||
//Archenemy
|
|
||||||
if (variantTypes.contains(GameType.ArchenemyRumble)
|
|
||||||
|| (variantTypes.contains(GameType.Archenemy) && playerIsArchenemy)) {
|
|
||||||
Object selected = view.getSchemeDeckLists().get(i).getSelectedValue();
|
|
||||||
CardPool schemePool = null;
|
|
||||||
if (selected instanceof String) {
|
|
||||||
String sel = (String) selected;
|
|
||||||
if (sel.contains("Use deck's scheme section")) {
|
|
||||||
if (deck.has(DeckSection.Schemes)) {
|
|
||||||
schemePool = deck.get(DeckSection.Schemes);
|
|
||||||
} else {
|
|
||||||
sel = "Random";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IStorage<Deck> sDecks = FModel.getDecks().getScheme();
|
|
||||||
if (sel.equals("Random") && sDecks.size() != 0) {
|
|
||||||
schemePool = Aggregates.random(sDecks).get(DeckSection.Schemes);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
schemePool = ((Deck) selected).get(DeckSection.Schemes);
|
|
||||||
}
|
|
||||||
if (schemePool == null) { //Can be null if player deselects the list selection or chose Generate
|
|
||||||
schemePool = DeckgenUtil.generateSchemePool();
|
|
||||||
}
|
|
||||||
if (checkLegality) {
|
|
||||||
String errMsg = DeckFormat.getSchemeSectionConformanceProblem(schemePool);
|
|
||||||
if (null != errMsg) {
|
|
||||||
FOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid Scheme Deck");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
schemes = schemePool.toFlatList();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Planechase
|
|
||||||
if (variantTypes.contains(GameType.Planechase)) {
|
|
||||||
Object selected = view.getPlanarDeckLists().get(i).getSelectedValue();
|
|
||||||
CardPool planePool = null;
|
|
||||||
if (selected instanceof String) {
|
|
||||||
String sel = (String) selected;
|
|
||||||
if (sel.contains("Use deck's planes section")) {
|
|
||||||
if (deck.has(DeckSection.Planes)) {
|
|
||||||
planePool = deck.get(DeckSection.Planes);
|
|
||||||
} else {
|
|
||||||
sel = "Random";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
IStorage<Deck> pDecks = FModel.getDecks().getPlane();
|
|
||||||
if (sel.equals("Random") && pDecks.size() != 0) {
|
|
||||||
planePool = Aggregates.random(pDecks).get(DeckSection.Planes);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
planePool = ((Deck) selected).get(DeckSection.Planes);
|
|
||||||
}
|
|
||||||
if (planePool == null) { //Can be null if player deselects the list selection or chose Generate
|
|
||||||
planePool = DeckgenUtil.generatePlanarPool();
|
|
||||||
}
|
|
||||||
if (checkLegality) {
|
|
||||||
String errMsg = DeckFormat.getPlaneSectionConformanceProblem(planePool);
|
|
||||||
if (null != errMsg) {
|
|
||||||
FOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid Planar Deck");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
planes = planePool.toFlatList();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Vanguard
|
|
||||||
if (variantTypes.contains(GameType.Vanguard)) {
|
|
||||||
Object selected = view.getVanguardLists().get(i).getSelectedValue();
|
|
||||||
if (selected instanceof String) {
|
|
||||||
String sel = (String) selected;
|
|
||||||
if (sel.contains("Use deck's default avatar") && deck.has(DeckSection.Avatar)) {
|
|
||||||
vanguardAvatar = deck.get(DeckSection.Avatar).get(0);
|
|
||||||
} else { //Only other string is "Random"
|
|
||||||
if (isAI) { //AI
|
|
||||||
vanguardAvatar = Aggregates.random(view.getNonRandomAiAvatars());
|
|
||||||
} else { //Human
|
|
||||||
vanguardAvatar = Aggregates.random(view.getNonRandomHumanAvatars());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
vanguardAvatar = (PaperCard)selected;
|
|
||||||
}
|
|
||||||
if (vanguardAvatar == null) { //ERROR! null if avatar deselected on list
|
|
||||||
GuiDialog.message("No Vanguard avatar selected for " + name
|
|
||||||
+ ". Please choose one or disable the Vanguard variant");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rp = RegisteredPlayer.forVariants(variantTypes, deck, schemes, playerIsArchenemy, planes, vanguardAvatar);
|
|
||||||
rp.setTeamNumber(view.getTeam(i));
|
|
||||||
players.add(rp.setPlayer(lobbyPlayer));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isAI) {
|
|
||||||
guis.put(rp, gui);
|
|
||||||
}
|
|
||||||
view.getDeckChooser(i).saveState();
|
|
||||||
}
|
|
||||||
|
|
||||||
final HostedMatch hostedMatch = GuiBase.getInterface().hostMatch();
|
|
||||||
hostedMatch.startMatch(GameType.Constructed, variantTypes, players, guis);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -282,4 +282,8 @@ public class GuiMobile implements IGuiBase {
|
|||||||
public HostedMatch hostMatch() {
|
public HostedMatch hostMatch() {
|
||||||
return Forge.hostedMatch = new HostedMatch();
|
return Forge.hostedMatch = new HostedMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void netMessage(final String origin, final String message) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,4 +51,5 @@ public interface IGuiBase {
|
|||||||
void showBazaar();
|
void showBazaar();
|
||||||
IGuiGame getNewGuiGame();
|
IGuiGame getNewGuiGame();
|
||||||
HostedMatch hostMatch();
|
HostedMatch hostMatch();
|
||||||
|
void netMessage(String origin, String message);
|
||||||
}
|
}
|
||||||
415
forge-gui/src/main/java/forge/match/NetGuiGame.java
Normal file
415
forge-gui/src/main/java/forge/match/NetGuiGame.java
Normal file
@@ -0,0 +1,415 @@
|
|||||||
|
package forge.match;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
import forge.LobbyPlayer;
|
||||||
|
import forge.UiCommand;
|
||||||
|
import forge.assets.FSkinProp;
|
||||||
|
import forge.deck.CardPool;
|
||||||
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameEntityView;
|
||||||
|
import forge.game.GameView;
|
||||||
|
import forge.game.card.CardView;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.DelayedReveal;
|
||||||
|
import forge.game.player.IHasIcon;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.interfaces.IButton;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.net.game.GuiGameEvent;
|
||||||
|
import forge.net.game.server.IToClient;
|
||||||
|
import forge.player.PlayerControllerHuman;
|
||||||
|
import forge.trackable.TrackableObject;
|
||||||
|
import forge.util.FCollectionView;
|
||||||
|
import forge.util.ITriggerEvent;
|
||||||
|
|
||||||
|
public class NetGuiGame extends AbstractGuiGame {
|
||||||
|
|
||||||
|
private final IToClient client;
|
||||||
|
public NetGuiGame(final IToClient client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void send(final String method) {
|
||||||
|
send(method, Collections.<TrackableObject>emptySet());
|
||||||
|
}
|
||||||
|
private void send(final String method, final TrackableObject object) {
|
||||||
|
send(method, Collections.singleton(object));
|
||||||
|
}
|
||||||
|
private void send(final String method, final Iterable<? extends TrackableObject> objects) {
|
||||||
|
client.send(new GuiGameEvent(method, objects));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setGameView(final GameView gameView) {
|
||||||
|
super.setGameView(gameView);
|
||||||
|
send("setGameView", gameView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean resetForNewGame() {
|
||||||
|
send("resetForNewGame");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void openView(final Iterable<PlayerView> myPlayers) {
|
||||||
|
send("openView", myPlayers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterGameEnd() {
|
||||||
|
send("afterGameEnd");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showCombat() {
|
||||||
|
send("showCombat");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showPromptMessage(PlayerView playerView, String message) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stopAtPhase(PlayerView playerTurn, PhaseType phase) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IButton getBtnOK(final PlayerView playerView) {
|
||||||
|
return new NetButton(playerView, "OK");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IButton getBtnCancel(final PlayerView playerView) {
|
||||||
|
return new NetButton(playerView, "Cancel");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusButton(IButton button) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flashIncorrectAction() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePhase() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateTurn(PlayerView player) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePlayerControl() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enableOverlay() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disableOverlay() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishGame() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object showManaPool(PlayerView player) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hideManaPool(PlayerView player, Object zoneToRestore) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStack() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateZones(List<Pair<PlayerView, ZoneType>> zonesToUpdate) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSingleCard(CardView card) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateManaPool(Iterable<PlayerView> manaPoolUpdate) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateLives(Iterable<PlayerView> livesUpdate) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPanelSelection(CardView hostCard) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hear(LobbyPlayer player, String message) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpellAbility getAbilityToPlay(List<SpellAbility> abilities,
|
||||||
|
ITriggerEvent triggerEvent) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<CardView, Integer> assignDamage(CardView attacker,
|
||||||
|
List<CardView> blockers, int damage, GameEntityView defender,
|
||||||
|
boolean overrideOrder) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void message(String message, String title) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showErrorDialog(String message, String title) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean showConfirmDialog(String message, String title,
|
||||||
|
String yesButtonText, String noButtonText, boolean defaultYes) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int showOptionDialog(String message, String title, FSkinProp icon,
|
||||||
|
String[] options, int defaultOption) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int showCardOptionDialog(CardView card, String message,
|
||||||
|
String title, FSkinProp icon, String[] options, int defaultOption) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String showInputDialog(String message, String title, FSkinProp icon,
|
||||||
|
String initialInput, String[] inputOptions) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean confirm(CardView c, String question, boolean defaultIsYes,
|
||||||
|
String[] options) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> getChoices(String message, int min, int max,
|
||||||
|
Collection<T> choices, T selected, Function<T, String> display) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> order(String title, String top, int remainingObjectsMin,
|
||||||
|
int remainingObjectsMax, List<T> sourceChoices,
|
||||||
|
List<T> destChoices, CardView referenceCard,
|
||||||
|
boolean sideboardingMode) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PaperCard> sideboard(CardPool sideboard, CardPool main) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GameEntityView chooseSingleEntityForEffect(String title,
|
||||||
|
FCollectionView<? extends GameEntity> optionList,
|
||||||
|
DelayedReveal delayedReveal, boolean isOptional,
|
||||||
|
PlayerControllerHuman controller) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCard(CardView card) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean openZones(Collection<ZoneType> zones,
|
||||||
|
Map<PlayerView, Object> players) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreOldZones(Map<PlayerView, Object> playersToRestoreZonesFor) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUiSetToSkipPhase(PlayerView playerTurn, PhaseType phase) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateCurrentPlayer(PlayerView player) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static class NetButton implements IButton {
|
||||||
|
|
||||||
|
private final PlayerView playerView;
|
||||||
|
private final String button;
|
||||||
|
private NetButton(final PlayerView playerView, final String button) {
|
||||||
|
this.playerView = playerView;
|
||||||
|
this.button = button;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean b0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisible() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisible(boolean b0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setText(String text0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelected() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelected(boolean b0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requestFocusInWindow() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCommand(UiCommand command0) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTextColor(FSkinProp color) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTextColor(int r, int g, int b) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
124
forge-gui/src/main/java/forge/net/FGameClient.java
Normal file
124
forge-gui/src/main/java/forge/net/FGameClient.java
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
package forge.net;
|
||||||
|
|
||||||
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
import io.netty.handler.codec.serialization.ClassResolvers;
|
||||||
|
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||||
|
import io.netty.handler.codec.serialization.ObjectEncoder;
|
||||||
|
import forge.GuiBase;
|
||||||
|
import forge.game.GameView;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
|
import forge.interfaces.IGuiGame;
|
||||||
|
import forge.net.game.GuiGameEvent;
|
||||||
|
import forge.net.game.LoginEvent;
|
||||||
|
import forge.net.game.MessageEvent;
|
||||||
|
import forge.net.game.NetEvent;
|
||||||
|
import forge.net.game.client.IToServer;
|
||||||
|
|
||||||
|
public class FGameClient implements IToServer {
|
||||||
|
private final IGuiGame clientGui;
|
||||||
|
public FGameClient(final String username, final String roomKey, final IGuiGame clientGui) {
|
||||||
|
this.clientGui = clientGui;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
|
||||||
|
|
||||||
|
private Channel channel;
|
||||||
|
public void connect(final String host, final int port) {
|
||||||
|
final EventLoopGroup group = new NioEventLoopGroup();
|
||||||
|
try {
|
||||||
|
final Bootstrap b = new Bootstrap()
|
||||||
|
.group(group)
|
||||||
|
.channel(NioSocketChannel.class)
|
||||||
|
.handler(new ChannelInitializer<SocketChannel>() {
|
||||||
|
@Override
|
||||||
|
public void initChannel(final SocketChannel ch) throws Exception {
|
||||||
|
final ChannelPipeline pipeline = ch.pipeline();
|
||||||
|
pipeline.addLast(
|
||||||
|
new ObjectEncoder(),
|
||||||
|
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
|
||||||
|
new MessageHandler(),
|
||||||
|
new GameClientHandler());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start the connection attempt.
|
||||||
|
channel = b.connect(host, port).sync().channel();
|
||||||
|
final ChannelFuture ch = channel.closeFuture();
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override public void run() {
|
||||||
|
try {
|
||||||
|
ch.sync();
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
group.shutdownGracefully();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void send(final NetEvent event) {
|
||||||
|
channel.writeAndFlush(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class GameClientHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
/**
|
||||||
|
* Creates a client-side handler.
|
||||||
|
*/
|
||||||
|
public GameClientHandler() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelActive(final ChannelHandlerContext ctx) {
|
||||||
|
send(new LoginEvent("elcnesh"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Override
|
||||||
|
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
|
||||||
|
System.out.println("Client received: " + msg);
|
||||||
|
if (msg instanceof GuiGameEvent) {
|
||||||
|
final GuiGameEvent event = (GuiGameEvent) msg;
|
||||||
|
switch (event.getMethod()) {
|
||||||
|
case "setGameView":
|
||||||
|
clientGui.setGameView((GameView) event.getObject());
|
||||||
|
break;
|
||||||
|
case "openView":
|
||||||
|
clientGui.openView((Iterable<PlayerView>) event.getObjects());
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) {
|
||||||
|
cause.printStackTrace();
|
||||||
|
ctx.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MessageHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
@Override
|
||||||
|
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||||
|
if (msg instanceof MessageEvent) {
|
||||||
|
final MessageEvent event = (MessageEvent) msg;
|
||||||
|
GuiBase.getInterface().netMessage(event.getSource(), event.getMessage());
|
||||||
|
}
|
||||||
|
super.channelRead(ctx, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
208
forge-gui/src/main/java/forge/net/FServerManager.java
Normal file
208
forge-gui/src/main/java/forge/net/FServerManager.java
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
package forge.net;
|
||||||
|
|
||||||
|
import forge.game.GameRules;
|
||||||
|
import forge.net.game.LoginEvent;
|
||||||
|
import forge.net.game.LogoutEvent;
|
||||||
|
import forge.net.game.MessageEvent;
|
||||||
|
import forge.net.game.NetEvent;
|
||||||
|
import forge.net.game.RegisterDeckEvent;
|
||||||
|
import forge.net.game.client.ILobbyListener;
|
||||||
|
import forge.net.game.server.RemoteClient;
|
||||||
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
import io.netty.channel.EventLoopGroup;
|
||||||
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
import io.netty.handler.codec.serialization.ClassResolvers;
|
||||||
|
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||||
|
import io.netty.handler.codec.serialization.ObjectEncoder;
|
||||||
|
import io.netty.handler.logging.LogLevel;
|
||||||
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
public final class FServerManager {
|
||||||
|
private static FServerManager instance = null;
|
||||||
|
|
||||||
|
private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
||||||
|
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||||
|
private final Map<Integer, NetGame> games = Maps.newTreeMap();
|
||||||
|
private int id = 0;
|
||||||
|
private final Map<Channel, RemoteClient> clients = Maps.newTreeMap();
|
||||||
|
private final List<ILobbyListener> lobbyListeners = Lists.newArrayListWithExpectedSize(1);
|
||||||
|
|
||||||
|
private FServerManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private int nextId() {
|
||||||
|
return id++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FServerManager getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new FServerManager();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startServer(final int port) {
|
||||||
|
try {
|
||||||
|
final ServerBootstrap b = new ServerBootstrap()
|
||||||
|
.group(bossGroup, workerGroup)
|
||||||
|
.channel(NioServerSocketChannel.class)
|
||||||
|
.handler(new LoggingHandler(LogLevel.INFO))
|
||||||
|
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||||
|
@Override
|
||||||
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
|
ChannelPipeline p = ch.pipeline();
|
||||||
|
p.addLast(
|
||||||
|
new ObjectEncoder(),
|
||||||
|
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
|
||||||
|
new MessageHandler(),
|
||||||
|
new RegisterClientHandler(),
|
||||||
|
new ToLobbyListenersHandler(),
|
||||||
|
new DeregisterClientHandler(),
|
||||||
|
new GameServerHandler());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Bind and start to accept incoming connections.
|
||||||
|
final ChannelFuture ch = b.bind(port).sync().channel().closeFuture();
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override public void run() {
|
||||||
|
try {
|
||||||
|
ch.sync();
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
} catch (final InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopServer() {
|
||||||
|
bossGroup.shutdownGracefully();
|
||||||
|
workerGroup.shutdownGracefully();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void broadcast(final NetEvent event) {
|
||||||
|
for (final RemoteClient client : clients.values()) {
|
||||||
|
client.send(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerLobbyListener(final ILobbyListener lobbyListener) {
|
||||||
|
lobbyListeners.add(lobbyListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NetGame hostGame(final GameRules rules) {
|
||||||
|
final int id = nextId();
|
||||||
|
final NetGame game = new NetGame(rules);
|
||||||
|
games.put(id, game);
|
||||||
|
return game;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finalize() throws Throwable {
|
||||||
|
super.finalize();
|
||||||
|
stopServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MessageHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
@Override public final void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||||
|
final RemoteClient client = clients.get(ctx.channel());
|
||||||
|
if (msg instanceof MessageEvent) {
|
||||||
|
broadcast(new MessageEvent(client.getUsername(), ((MessageEvent) msg).getMessage()));
|
||||||
|
}
|
||||||
|
super.channelRead(ctx, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class GameServerHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
@Override
|
||||||
|
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
|
||||||
|
System.out.println("Server received: " + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) {
|
||||||
|
cause.printStackTrace();
|
||||||
|
ctx.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RegisterClientHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
@Override
|
||||||
|
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
|
||||||
|
final RemoteClient client = new RemoteClient(ctx.channel());
|
||||||
|
clients.put(ctx.channel(), client);
|
||||||
|
games.get(0).addClient(client);
|
||||||
|
System.out.println("User connected to server at " + ctx.channel().remoteAddress());
|
||||||
|
super.channelActive(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||||
|
final RemoteClient client = clients.get(ctx.channel());
|
||||||
|
if (msg instanceof LoginEvent) {
|
||||||
|
client.setUsername(((LoginEvent) msg).getUsername());
|
||||||
|
} else if (msg instanceof RegisterDeckEvent) {
|
||||||
|
games.get(0).registerDeck(client, ((RegisterDeckEvent) msg).getDeck());
|
||||||
|
}
|
||||||
|
super.channelRead(ctx, msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ToLobbyListenersHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
@Override public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||||
|
final RemoteClient client = clients.get(ctx.channel());
|
||||||
|
if (msg instanceof LoginEvent) {
|
||||||
|
final LoginEvent event = (LoginEvent) msg;
|
||||||
|
for (final ILobbyListener lobbyListener : lobbyListeners) {
|
||||||
|
lobbyListener.login(client);
|
||||||
|
}
|
||||||
|
broadcast(event);
|
||||||
|
} else if (msg instanceof MessageEvent) {
|
||||||
|
final MessageEvent event = (MessageEvent) msg;
|
||||||
|
for (final ILobbyListener lobbyListener : lobbyListeners) {
|
||||||
|
lobbyListener.message(client.getUsername(), event.getMessage());
|
||||||
|
}
|
||||||
|
broadcast(event);
|
||||||
|
}
|
||||||
|
super.channelRead(ctx, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
|
||||||
|
final RemoteClient client = clients.get(ctx.channel());
|
||||||
|
for (final ILobbyListener lobbyListener : lobbyListeners) {
|
||||||
|
lobbyListener.logout(client);
|
||||||
|
}
|
||||||
|
super.channelInactive(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DeregisterClientHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
@Override
|
||||||
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||||
|
final RemoteClient client = clients.remove(ctx.channel());
|
||||||
|
// TODO remove client from games
|
||||||
|
broadcast(new LogoutEvent(client.getUsername()));
|
||||||
|
super.channelInactive(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
forge-gui/src/main/java/forge/net/NetGame.java
Normal file
69
forge-gui/src/main/java/forge/net/NetGame.java
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package forge.net;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import forge.ai.LobbyPlayerAi;
|
||||||
|
import forge.deck.Deck;
|
||||||
|
import forge.game.GameRules;
|
||||||
|
import forge.game.player.RegisteredPlayer;
|
||||||
|
import forge.interfaces.IGuiGame;
|
||||||
|
import forge.match.HostedMatch;
|
||||||
|
import forge.match.NetGuiGame;
|
||||||
|
import forge.net.game.server.RemoteClient;
|
||||||
|
import forge.player.LobbyPlayerHuman;
|
||||||
|
|
||||||
|
public final class NetGame {
|
||||||
|
|
||||||
|
private final Map<RemoteClient, NetPlayer> clients = Maps.newHashMap();
|
||||||
|
private final GameRules rules;
|
||||||
|
private final HostedMatch match = new HostedMatch();
|
||||||
|
public NetGame(final GameRules rules) {
|
||||||
|
this.rules = rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addClient(final RemoteClient client) {
|
||||||
|
clients.put(client, new NetPlayer(client, new NetGuiGame(client)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startMatch() {
|
||||||
|
final List<RegisteredPlayer> registeredPlayers = Lists.newArrayListWithCapacity(clients.size());
|
||||||
|
final Map<RegisteredPlayer, IGuiGame> guis = Maps.newHashMap();
|
||||||
|
for (final NetPlayer np : clients.values()) {
|
||||||
|
if (np.player == null) {
|
||||||
|
System.err.println("No deck registered for player " + np.client.getUsername());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
registeredPlayers.add(np.player);
|
||||||
|
guis.put(np.player, np.gui);
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
|
if (registeredPlayers.size() == 1) {
|
||||||
|
RegisteredPlayer r = new RegisteredPlayer(new Deck());
|
||||||
|
registeredPlayers.add(r);
|
||||||
|
r.setPlayer(new LobbyPlayerAi("AI", new HashMap<String, String>()));
|
||||||
|
}
|
||||||
|
match.startMatch(rules, null, registeredPlayers, guis);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerDeck(final RemoteClient client, final Deck deck) {
|
||||||
|
final RegisteredPlayer r = new RegisteredPlayer(deck);
|
||||||
|
clients.get(client).player = r;
|
||||||
|
r.setPlayer(new LobbyPlayerHuman(client.getUsername()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class NetPlayer {
|
||||||
|
private final RemoteClient client;
|
||||||
|
private RegisteredPlayer player = null;
|
||||||
|
private final IGuiGame gui;
|
||||||
|
private NetPlayer(final RemoteClient client, final IGuiGame gui) {
|
||||||
|
this.client = client;
|
||||||
|
this.gui = gui;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
forge-gui/src/main/java/forge/net/package-info.java
Normal file
1
forge-gui/src/main/java/forge/net/package-info.java
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package forge.net;
|
||||||
128
forge-gui/src/main/java/forge/player/NetGameController.java
Normal file
128
forge-gui/src/main/java/forge/player/NetGameController.java
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package forge.player;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import forge.game.card.CardView;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.interfaces.IDevModeCheats;
|
||||||
|
import forge.interfaces.IGameController;
|
||||||
|
import forge.match.NextGameDecision;
|
||||||
|
import forge.net.game.client.IToServer;
|
||||||
|
import forge.trackable.TrackableObject;
|
||||||
|
import forge.util.ITriggerEvent;
|
||||||
|
|
||||||
|
public class NetGameController implements IGameController {
|
||||||
|
|
||||||
|
private final IToServer server;
|
||||||
|
public NetGameController(final IToServer server) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void send(final String method) {
|
||||||
|
send(method, Collections.<TrackableObject>emptySet());
|
||||||
|
}
|
||||||
|
private void send(final String method, final TrackableObject object) {
|
||||||
|
send(method, Collections.singleton(object));
|
||||||
|
}
|
||||||
|
private void send(final String method, final Iterable<? extends TrackableObject> objects) {
|
||||||
|
//server.send(new (method, objects));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mayLookAtAllCards() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canPlayUnlimitedLands() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void concede() {
|
||||||
|
send("concede");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void alphaStrike() {
|
||||||
|
send("alphaStrike");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useMana(byte color) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectButtonOk() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectButtonCancel() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean passPriority() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean passPriorityUntilEndOfTurn() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectPlayer(PlayerView playerView, ITriggerEvent triggerEvent) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean selectCard(CardView cardView,
|
||||||
|
List<CardView> otherCardViewsToSelect, ITriggerEvent triggerEvent) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectAbility(SpellAbility sa) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryUndoLastAction() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IDevModeCheats cheat() {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nextGameDecision(NextGameDecision decision) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getActivateDescription(CardView card) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -28,6 +28,12 @@
|
|||||||
<artifactId>gson</artifactId>
|
<artifactId>gson</artifactId>
|
||||||
<version>2.2.4</version>
|
<version>2.2.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.netty</groupId>
|
||||||
|
<artifactId>netty-all</artifactId>
|
||||||
|
<version>4.0.25.Final</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
<artifactId>jetty-websocket</artifactId>
|
<artifactId>jetty-websocket</artifactId>
|
||||||
|
|||||||
31
forge-net/src/main/java/forge/net/client/GameServlet.java
Normal file
31
forge-net/src/main/java/forge/net/client/GameServlet.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package forge.net.client;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.websocket.WebSocket;
|
||||||
|
import org.eclipse.jetty.websocket.WebSocketServlet;
|
||||||
|
|
||||||
|
import forge.net.IClientSocket;
|
||||||
|
import forge.net.NetServer;
|
||||||
|
import forge.net.NetServer.ClientSocket;
|
||||||
|
|
||||||
|
public class GameServlet extends WebSocketServlet {
|
||||||
|
|
||||||
|
private final String prefix;
|
||||||
|
private final ClientSocket socket;
|
||||||
|
public GameServlet(final NetServer netServer, final String prefix) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
this.socket = netServer.new ClientSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IClientSocket getSocket() {
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WebSocket doWebSocketConnect(final HttpServletRequest request, final String protocol) {
|
||||||
|
System.out.printf("Connection from %s recieved%n", request.getRemoteAddr());
|
||||||
|
return socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
29
forge-net/src/main/java/forge/net/game/GuiGameEvent.java
Normal file
29
forge-net/src/main/java/forge/net/game/GuiGameEvent.java
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package forge.net.game;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
import forge.trackable.TrackableObject;
|
||||||
|
|
||||||
|
public final class GuiGameEvent implements NetEvent {
|
||||||
|
|
||||||
|
private final String method;
|
||||||
|
private final Iterable<? extends TrackableObject> objects;
|
||||||
|
|
||||||
|
public GuiGameEvent(final String method, final Iterable<? extends TrackableObject> objects) {
|
||||||
|
this.method = method;
|
||||||
|
this.objects = objects == null ? ImmutableSet.<TrackableObject>of() : objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TrackableObject getObject() {
|
||||||
|
return Iterables.getFirst(objects, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterable<? extends TrackableObject> getObjects() {
|
||||||
|
return objects;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
forge-net/src/main/java/forge/net/game/IRemote.java
Normal file
5
forge-net/src/main/java/forge/net/game/IRemote.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package forge.net.game;
|
||||||
|
|
||||||
|
public interface IRemote {
|
||||||
|
void send(NetEvent event);
|
||||||
|
}
|
||||||
14
forge-net/src/main/java/forge/net/game/LoginEvent.java
Normal file
14
forge-net/src/main/java/forge/net/game/LoginEvent.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package forge.net.game;
|
||||||
|
|
||||||
|
public class LoginEvent implements NetEvent {
|
||||||
|
private static final long serialVersionUID = -8865183377417377938L;
|
||||||
|
|
||||||
|
private final String username;
|
||||||
|
public LoginEvent(final String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
}
|
||||||
14
forge-net/src/main/java/forge/net/game/LogoutEvent.java
Normal file
14
forge-net/src/main/java/forge/net/game/LogoutEvent.java
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package forge.net.game;
|
||||||
|
|
||||||
|
public class LogoutEvent implements NetEvent {
|
||||||
|
private static final long serialVersionUID = -8262613254026625787L;
|
||||||
|
|
||||||
|
private final String username;
|
||||||
|
public LogoutEvent(final String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
forge-net/src/main/java/forge/net/game/MessageEvent.java
Normal file
23
forge-net/src/main/java/forge/net/game/MessageEvent.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package forge.net.game;
|
||||||
|
|
||||||
|
public class MessageEvent implements NetEvent {
|
||||||
|
private static final long serialVersionUID = 1700060210647684186L;
|
||||||
|
|
||||||
|
private final String source, message;
|
||||||
|
public MessageEvent(final String source, final String message) {
|
||||||
|
this.source = source;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSource() {
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
6
forge-net/src/main/java/forge/net/game/NetEvent.java
Normal file
6
forge-net/src/main/java/forge/net/game/NetEvent.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package forge.net.game;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public interface NetEvent extends Serializable {
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package forge.net.game;
|
||||||
|
|
||||||
|
import forge.deck.Deck;
|
||||||
|
|
||||||
|
public class RegisterDeckEvent implements NetEvent {
|
||||||
|
private static final long serialVersionUID = -6553476654530937343L;
|
||||||
|
|
||||||
|
private final Deck deck;
|
||||||
|
public RegisterDeckEvent(final Deck deck) {
|
||||||
|
this.deck = deck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Deck getDeck() {
|
||||||
|
return deck;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package forge.net.game.client;
|
||||||
|
|
||||||
|
import forge.net.game.server.RemoteClient;
|
||||||
|
|
||||||
|
public interface ILobbyListener {
|
||||||
|
void login(RemoteClient client);
|
||||||
|
void logout(RemoteClient client);
|
||||||
|
void message(String source, String message);
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package forge.net.game.client;
|
||||||
|
|
||||||
|
import forge.net.game.IRemote;
|
||||||
|
|
||||||
|
public interface IToServer extends IRemote {
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
package forge.net.game.client;
|
||||||
1
forge-net/src/main/java/forge/net/game/package-info.java
Normal file
1
forge-net/src/main/java/forge/net/game/package-info.java
Normal file
@@ -0,0 +1 @@
|
|||||||
|
package forge.net.game;
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package forge.net.game.server;
|
||||||
|
|
||||||
|
import forge.net.game.IRemote;
|
||||||
|
|
||||||
|
public interface IToClient extends IRemote {
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package forge.net.game.server;
|
||||||
|
|
||||||
|
import forge.net.game.NetEvent;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
|
||||||
|
public final class RemoteClient implements IToClient {
|
||||||
|
|
||||||
|
private final Channel channel;
|
||||||
|
private String username;
|
||||||
|
public RemoteClient(final Channel channel) {
|
||||||
|
this.channel = channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void send(final NetEvent event) {
|
||||||
|
channel.writeAndFlush(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
public void setUsername(final String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
package forge.net.game.server;
|
||||||
Reference in New Issue
Block a user