mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 19:28:01 +00:00
Update stability and fix issues in lobby and network games.
- Fix closing the lobby/client so that it notifies the clients/server. - Improve deck selection in lobby (no longer adds Planes to deck and saves) - Improve responsiveness of lobby over network - In 2-player game over network, always assign local player to slot 0 - Warn when starting a commander deck without a commander - Put poison counters next to life total (frees up space in the details panel)
This commit is contained in:
@@ -110,6 +110,7 @@ public enum FControl implements KeyEventDispatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* FControl.
|
* FControl.
|
||||||
|
|||||||
@@ -239,7 +239,8 @@ public class VLobby implements IUpdateable {
|
|||||||
isNewPanel = true;
|
isNewPanel = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
panel.setType(slot.getType());
|
final LobbySlotType type = slot.getType();
|
||||||
|
panel.setType(type);
|
||||||
panel.setPlayerName(slot.getName());
|
panel.setPlayerName(slot.getName());
|
||||||
panel.setAvatar(slot.getAvatarIndex());
|
panel.setAvatar(slot.getAvatarIndex());
|
||||||
panel.setTeam(slot.getTeam());
|
panel.setTeam(slot.getTeam());
|
||||||
@@ -253,7 +254,7 @@ public class VLobby implements IUpdateable {
|
|||||||
|
|
||||||
final FDeckChooser deckChooser = getDeckChooser(i);
|
final FDeckChooser deckChooser = getDeckChooser(i);
|
||||||
deckChooser.setIsAi(slot.getType() == LobbySlotType.AI);
|
deckChooser.setIsAi(slot.getType() == LobbySlotType.AI);
|
||||||
if (fullUpdate) {
|
if (fullUpdate && (type == LobbySlotType.LOCAL || type == LobbySlotType.AI)) {
|
||||||
selectDeck(i);
|
selectDeck(i);
|
||||||
}
|
}
|
||||||
if (isNewPanel) {
|
if (isNewPanel) {
|
||||||
@@ -298,7 +299,9 @@ public class VLobby implements IUpdateable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void fireDeckSectionChangeListener(final int index, final DeckSection section, final CardPool cards) {
|
private void fireDeckSectionChangeListener(final int index, final DeckSection section, final CardPool cards) {
|
||||||
decks[index].putSection(section, cards);
|
final Deck copy = new Deck(decks[index]);
|
||||||
|
copy.putSection(section, cards);
|
||||||
|
decks[index] = copy;
|
||||||
if (playerChangeListener != null) {
|
if (playerChangeListener != null) {
|
||||||
playerChangeListener.update(index, UpdateLobbyPlayerEvent.deckUpdate(section, cards));
|
playerChangeListener.update(index, UpdateLobbyPlayerEvent.deckUpdate(section, cards));
|
||||||
}
|
}
|
||||||
@@ -486,7 +489,7 @@ public class VLobby implements IUpdateable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void selectPlanarDeck(final int playerIndex) {
|
private void selectPlanarDeck(final int playerIndex) {
|
||||||
if (playerIndex >= activePlayersNum) {
|
if (playerIndex >= activePlayersNum || !hasVariant(GameType.Planechase)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import javax.swing.JMenu;
|
|||||||
import forge.GuiBase;
|
import forge.GuiBase;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.UiCommand;
|
import forge.UiCommand;
|
||||||
|
import forge.assets.FSkinProp;
|
||||||
import forge.gui.FNetOverlay;
|
import forge.gui.FNetOverlay;
|
||||||
import forge.gui.framework.FScreen;
|
import forge.gui.framework.FScreen;
|
||||||
import forge.gui.framework.ICDoc;
|
import forge.gui.framework.ICDoc;
|
||||||
@@ -31,6 +32,7 @@ import forge.net.game.UpdateLobbyPlayerEvent;
|
|||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.home.VLobby;
|
import forge.screens.home.VLobby;
|
||||||
import forge.screens.home.sanctioned.ConstructedGameMenu;
|
import forge.screens.home.sanctioned.ConstructedGameMenu;
|
||||||
|
import forge.util.gui.SOptionPane;
|
||||||
|
|
||||||
public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
||||||
SINGLETON_INSTANCE;
|
SINGLETON_INSTANCE;
|
||||||
@@ -64,6 +66,9 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
|||||||
@Override public final void message(final String source, final String message) {
|
@Override public final void message(final String source, final String message) {
|
||||||
FNetOverlay.SINGLETON_INSTANCE.addMessage(source, message);
|
FNetOverlay.SINGLETON_INSTANCE.addMessage(source, message);
|
||||||
}
|
}
|
||||||
|
@Override public final void close() {
|
||||||
|
// NO-OP, server can't receive close message
|
||||||
|
}
|
||||||
});
|
});
|
||||||
FNetOverlay.SINGLETON_INSTANCE.setGameClient(new IRemote() {
|
FNetOverlay.SINGLETON_INSTANCE.setGameClient(new IRemote() {
|
||||||
@Override public final void send(final NetEvent event) {
|
@Override public final void send(final NetEvent event) {
|
||||||
@@ -79,6 +84,7 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
view.populate();
|
||||||
view.update(true);
|
view.update(true);
|
||||||
|
|
||||||
Singletons.getControl().setCurrentScreen(FScreen.ONLINE_LOBBY);
|
Singletons.getControl().setCurrentScreen(FScreen.ONLINE_LOBBY);
|
||||||
@@ -88,6 +94,7 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
|||||||
final void join(final String hostname, final int port) {
|
final void join(final String hostname, final int port) {
|
||||||
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
||||||
final FGameClient client = new FGameClient(FModel.getPreferences().getPref(FPref.PLAYER_NAME), "0", gui);
|
final FGameClient client = new FGameClient(FModel.getPreferences().getPref(FPref.PLAYER_NAME), "0", gui);
|
||||||
|
VOnlineLobby.SINGLETON_INSTANCE.setClient(client);
|
||||||
FNetOverlay.SINGLETON_INSTANCE.setGameClient(client);
|
FNetOverlay.SINGLETON_INSTANCE.setGameClient(client);
|
||||||
final ClientGameLobby lobby = new ClientGameLobby();
|
final ClientGameLobby lobby = new ClientGameLobby();
|
||||||
final VLobby view = VOnlineLobby.SINGLETON_INSTANCE.setLobby(lobby);
|
final VLobby view = VOnlineLobby.SINGLETON_INSTANCE.setLobby(lobby);
|
||||||
@@ -100,6 +107,11 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
|||||||
lobby.setLocalPlayer(slot);
|
lobby.setLocalPlayer(slot);
|
||||||
lobby.setData(state);
|
lobby.setData(state);
|
||||||
}
|
}
|
||||||
|
@Override public final void close() {
|
||||||
|
SOptionPane.showMessageDialog("Connection to the host was interrupted.", "Error", FSkinProp.ICO_WARNING);
|
||||||
|
VOnlineLobby.SINGLETON_INSTANCE.setClient(null);
|
||||||
|
FScreen.ONLINE_LOBBY.close();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
view.setPlayerChangeListener(new IPlayerChangeListener() {
|
view.setPlayerChangeListener(new IPlayerChangeListener() {
|
||||||
@Override public final void update(final int index, final UpdateLobbyPlayerEvent event) {
|
@Override public final void update(final int index, final UpdateLobbyPlayerEvent event) {
|
||||||
@@ -109,7 +121,7 @@ public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
|||||||
client.connect(hostname, port);
|
client.connect(hostname, port);
|
||||||
|
|
||||||
Singletons.getControl().setCurrentScreen(FScreen.ONLINE_LOBBY);
|
Singletons.getControl().setCurrentScreen(FScreen.ONLINE_LOBBY);
|
||||||
FNetOverlay.SINGLETON_INSTANCE.showUp(String.format("Connected to %s:%s", hostname, port));
|
FNetOverlay.SINGLETON_INSTANCE.showUp(String.format("Connected to %s:%d", hostname, port));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import net.miginfocom.swing.MigLayout;
|
|||||||
import forge.deckchooser.DecksComboBoxEvent;
|
import forge.deckchooser.DecksComboBoxEvent;
|
||||||
import forge.deckchooser.FDeckChooser;
|
import forge.deckchooser.FDeckChooser;
|
||||||
import forge.deckchooser.IDecksComboBoxListener;
|
import forge.deckchooser.IDecksComboBoxListener;
|
||||||
|
import forge.gui.FNetOverlay;
|
||||||
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;
|
||||||
@@ -13,6 +14,8 @@ import forge.gui.framework.FScreen;
|
|||||||
import forge.gui.framework.IVDoc;
|
import forge.gui.framework.IVDoc;
|
||||||
import forge.gui.framework.IVTopLevelUI;
|
import forge.gui.framework.IVTopLevelUI;
|
||||||
import forge.match.GameLobby;
|
import forge.match.GameLobby;
|
||||||
|
import forge.net.FGameClient;
|
||||||
|
import forge.net.FServerManager;
|
||||||
import forge.screens.home.VLobby;
|
import forge.screens.home.VLobby;
|
||||||
import forge.toolbox.FPanel;
|
import forge.toolbox.FPanel;
|
||||||
import forge.util.gui.SOptionPane;
|
import forge.util.gui.SOptionPane;
|
||||||
@@ -26,6 +29,7 @@ public enum VOnlineLobby implements IVDoc<COnlineLobby>, IVTopLevelUI {
|
|||||||
|
|
||||||
// General variables
|
// General variables
|
||||||
private VLobby lobby;
|
private VLobby lobby;
|
||||||
|
private FGameClient client;
|
||||||
|
|
||||||
private VOnlineLobby() {
|
private VOnlineLobby() {
|
||||||
}
|
}
|
||||||
@@ -39,10 +43,15 @@ public enum VOnlineLobby implements IVDoc<COnlineLobby>, IVTopLevelUI {
|
|||||||
return this.lobby;
|
return this.lobby;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setClient(final FGameClient client) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void populate() {
|
public void populate() {
|
||||||
final JPanel outerContainer = FView.SINGLETON_INSTANCE.getPnlInsets();
|
final JPanel outerContainer = FView.SINGLETON_INSTANCE.getPnlInsets();
|
||||||
outerContainer.removeAll();
|
outerContainer.removeAll();
|
||||||
|
|
||||||
final FPanel container = new FPanel(new MigLayout("insets 0, gap 0, wrap 1, ax right"));
|
final FPanel container = new FPanel(new MigLayout("insets 0, gap 0, wrap 1, ax right"));
|
||||||
outerContainer.add(container);
|
outerContainer.add(container);
|
||||||
lobby.getLblTitle().setText("Online Multiplayer: Lobby");
|
lobby.getLblTitle().setText("Online Multiplayer: Lobby");
|
||||||
@@ -106,7 +115,23 @@ public enum VOnlineLobby implements IVDoc<COnlineLobby>, IVTopLevelUI {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onClosing(final FScreen screen) {
|
public boolean onClosing(final FScreen screen) {
|
||||||
return SOptionPane.showConfirmDialog("Leave lobby?", "Leave");
|
final FServerManager server = FServerManager.getInstance();
|
||||||
|
if (server.isHosting()) {
|
||||||
|
if (SOptionPane.showConfirmDialog("Leave lobby? Doing so will shut down all connections and stop hosting.", "Leave")) {
|
||||||
|
FServerManager.getInstance().stopServer();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (client == null || SOptionPane.showConfirmDialog("Leave lobby?", "Leave")) {
|
||||||
|
if (client != null) {
|
||||||
|
client.close();
|
||||||
|
client = null;
|
||||||
|
}
|
||||||
|
FNetOverlay.SINGLETON_INSTANCE.setGameClient(null);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ import forge.toolbox.MouseTriggerEvent;
|
|||||||
import forge.toolbox.special.PhaseIndicator;
|
import forge.toolbox.special.PhaseIndicator;
|
||||||
import forge.toolbox.special.PhaseLabel;
|
import forge.toolbox.special.PhaseLabel;
|
||||||
import forge.trackable.TrackableCollection;
|
import forge.trackable.TrackableCollection;
|
||||||
|
import forge.util.FCollection;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
import forge.util.gui.SOptionPane;
|
import forge.util.gui.SOptionPane;
|
||||||
@@ -260,11 +261,6 @@ public final class CMatchUI
|
|||||||
return FSkin.getAvatars().get(avatarIdx >= 0 ? avatarIdx : defaultIndex);
|
return FSkin.getAvatars().get(avatarIdx >= 0 ? avatarIdx : defaultIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAvatar(VField view, SkinImage img) {
|
|
||||||
view.getLblAvatar().setIcon(img);
|
|
||||||
view.getLblAvatar().getResizeTimer().start();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initMatch(final FCollectionView<PlayerView> sortedPlayers, final Iterable<PlayerView> myPlayers) {
|
private void initMatch(final FCollectionView<PlayerView> sortedPlayers, final Iterable<PlayerView> myPlayers) {
|
||||||
this.sortedPlayers = sortedPlayers;
|
this.sortedPlayers = sortedPlayers;
|
||||||
this.setLocalPlayers(myPlayers);
|
this.setLocalPlayers(myPlayers);
|
||||||
@@ -290,8 +286,7 @@ public final class CMatchUI
|
|||||||
commands.add(c);
|
commands.add(c);
|
||||||
myDocs.put(commandDoc, c);
|
myDocs.put(commandDoc, c);
|
||||||
|
|
||||||
//setAvatar(f, new ImageIcon(FSkin.getAvatars().get()));
|
f.setAvatar(getPlayerAvatar(p, Integer.parseInt(indices[i > 2 ? 1 : 0])));
|
||||||
setAvatar(f, getPlayerAvatar(p, Integer.parseInt(indices[i > 2 ? 1 : 0])));
|
|
||||||
f.getLayoutControl().initialize();
|
f.getLayoutControl().initialize();
|
||||||
c.getLayoutControl().initialize();
|
c.getLayoutControl().initialize();
|
||||||
i++;
|
i++;
|
||||||
@@ -436,7 +431,7 @@ public final class CMatchUI
|
|||||||
if (vHand != null) {
|
if (vHand != null) {
|
||||||
vHand.getLayoutControl().updateHand();
|
vHand.getLayoutControl().updateHand();
|
||||||
}
|
}
|
||||||
vf.getDetailsPanel().updateZones();
|
vf.updateZones();
|
||||||
vf.updateDetails();
|
vf.updateDetails();
|
||||||
FloatingCardArea.refresh(owner, zt);
|
FloatingCardArea.refresh(owner, zt);
|
||||||
break;
|
break;
|
||||||
@@ -448,7 +443,7 @@ public final class CMatchUI
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (vf != null) {
|
if (vf != null) {
|
||||||
vf.getDetailsPanel().updateZones();
|
vf.updateZones();
|
||||||
}
|
}
|
||||||
FloatingCardArea.refresh(owner, zt);
|
FloatingCardArea.refresh(owner, zt);
|
||||||
break;
|
break;
|
||||||
@@ -460,7 +455,7 @@ public final class CMatchUI
|
|||||||
@Override
|
@Override
|
||||||
public void updateManaPool(final Iterable<PlayerView> manaPoolUpdate) {
|
public void updateManaPool(final Iterable<PlayerView> manaPoolUpdate) {
|
||||||
for (final PlayerView p : manaPoolUpdate) {
|
for (final PlayerView p : manaPoolUpdate) {
|
||||||
getFieldViewFor(p).getDetailsPanel().updateManaPool();
|
getFieldViewFor(p).updateManaPool();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -795,7 +790,12 @@ public final class CMatchUI
|
|||||||
final GameView gameView = getGameView();
|
final GameView gameView = getGameView();
|
||||||
gameView.getGameLog().addObserver(getCLog());
|
gameView.getGameLog().addObserver(getCLog());
|
||||||
|
|
||||||
initMatch(gameView.getPlayers(), myPlayers);
|
// Sort players
|
||||||
|
FCollectionView<PlayerView> players = gameView.getPlayers();
|
||||||
|
if (players.size() == 2 && myPlayers.size() == 1 && myPlayers.get(0).equals(players.get(1))) {
|
||||||
|
players = new FCollection<PlayerView>(new PlayerView[] { players.get(1), players.get(0) });
|
||||||
|
}
|
||||||
|
initMatch(players, myPlayers);
|
||||||
|
|
||||||
actuateMatchPreferences();
|
actuateMatchPreferences();
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import javax.swing.border.Border;
|
|||||||
import javax.swing.border.LineBorder;
|
import javax.swing.border.LineBorder;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
|
import forge.assets.FSkinProp;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.framework.DragCell;
|
import forge.gui.framework.DragCell;
|
||||||
@@ -39,6 +40,7 @@ import forge.screens.match.controllers.CField;
|
|||||||
import forge.toolbox.FLabel;
|
import forge.toolbox.FLabel;
|
||||||
import forge.toolbox.FScrollPane;
|
import forge.toolbox.FScrollPane;
|
||||||
import forge.toolbox.FSkin;
|
import forge.toolbox.FSkin;
|
||||||
|
import forge.toolbox.FSkin.SkinImage;
|
||||||
import forge.toolbox.FSkin.SkinnedPanel;
|
import forge.toolbox.FSkin.SkinnedPanel;
|
||||||
import forge.toolbox.special.PhaseIndicator;
|
import forge.toolbox.special.PhaseIndicator;
|
||||||
import forge.toolbox.special.PlayerDetailsPanel;
|
import forge.toolbox.special.PlayerDetailsPanel;
|
||||||
@@ -50,6 +52,9 @@ import forge.view.arcane.PlayArea;
|
|||||||
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
||||||
*/
|
*/
|
||||||
public class VField implements IVDoc<CField> {
|
public class VField implements IVDoc<CField> {
|
||||||
|
private final static int LIFE_CRITICAL = 5;
|
||||||
|
private final static int POISON_CRITICAL = 8;
|
||||||
|
|
||||||
// Fields used with interface IVDoc
|
// Fields used with interface IVDoc
|
||||||
private final CField control;
|
private final CField control;
|
||||||
private DragCell parentCell;
|
private DragCell parentCell;
|
||||||
@@ -57,7 +62,7 @@ public class VField implements IVDoc<CField> {
|
|||||||
private final DragTab tab = new DragTab("Field");
|
private final DragTab tab = new DragTab("Field");
|
||||||
|
|
||||||
// Other fields
|
// Other fields
|
||||||
private PlayerView player = null;
|
private final PlayerView player;
|
||||||
|
|
||||||
// Top-level containers
|
// Top-level containers
|
||||||
private final FScrollPane scroller = new FScrollPane(false);
|
private final FScrollPane scroller = new FScrollPane(false);
|
||||||
@@ -69,6 +74,7 @@ public class VField implements IVDoc<CField> {
|
|||||||
// Avatar area
|
// Avatar area
|
||||||
private final FLabel lblAvatar = new FLabel.Builder().fontAlign(SwingConstants.CENTER).iconScaleFactor(1.0f).build();
|
private final FLabel lblAvatar = new FLabel.Builder().fontAlign(SwingConstants.CENTER).iconScaleFactor(1.0f).build();
|
||||||
private final FLabel lblLife = new FLabel.Builder().fontAlign(SwingConstants.CENTER).fontStyle(Font.BOLD).build();
|
private final FLabel lblLife = new FLabel.Builder().fontAlign(SwingConstants.CENTER).fontStyle(Font.BOLD).build();
|
||||||
|
private final FLabel lblPoison = new FLabel.Builder().fontAlign(SwingConstants.CENTER).fontStyle(Font.BOLD).icon(FSkin.getImage(FSkinProp.IMG_ZONE_POISON)).iconInBackground().build();
|
||||||
|
|
||||||
private final PhaseIndicator phaseIndicator = new PhaseIndicator();
|
private final PhaseIndicator phaseIndicator = new PhaseIndicator();
|
||||||
|
|
||||||
@@ -100,12 +106,13 @@ public class VField implements IVDoc<CField> {
|
|||||||
|
|
||||||
lblAvatar.setFocusable(false);
|
lblAvatar.setFocusable(false);
|
||||||
lblLife.setFocusable(false);
|
lblLife.setFocusable(false);
|
||||||
|
lblPoison.setFocusable(false);
|
||||||
|
|
||||||
avatarArea.setOpaque(false);
|
avatarArea.setOpaque(false);
|
||||||
avatarArea.setBackground(FSkin.getColor(FSkin.Colors.CLR_HOVER));
|
avatarArea.setBackground(FSkin.getColor(FSkin.Colors.CLR_HOVER));
|
||||||
avatarArea.setLayout(new MigLayout("insets 0, gap 0"));
|
avatarArea.setLayout(new MigLayout("insets 0, gap 0"));
|
||||||
avatarArea.add(lblAvatar, "w 100%-6px!, h 100%-23px!, wrap, gap 3 3 3 0");
|
avatarArea.add(lblAvatar, "w 100%-6px!, h 100%-23px!, wrap, gap 3 3 3 0");
|
||||||
avatarArea.add(lblLife, "w 100%!, h 20px!");
|
avatarArea.add(lblLife, "w 100%!, h 20px!, wrap");
|
||||||
|
|
||||||
// Player area hover effect
|
// Player area hover effect
|
||||||
avatarArea.addMouseListener(new MouseAdapter() {
|
avatarArea.addMouseListener(new MouseAdapter() {
|
||||||
@@ -170,10 +177,6 @@ public class VField implements IVDoc<CField> {
|
|||||||
return this.parentCell;
|
return this.parentCell;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerView getPlayer() {
|
|
||||||
return this.player;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PlayArea getTabletop() {
|
public PlayArea getTabletop() {
|
||||||
return this.tabletop;
|
return this.tabletop;
|
||||||
}
|
}
|
||||||
@@ -182,14 +185,6 @@ public class VField implements IVDoc<CField> {
|
|||||||
return this.avatarArea;
|
return this.avatarArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FLabel getLblAvatar() {
|
|
||||||
return this.lblAvatar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FLabel getLblLife() {
|
|
||||||
return this.lblLife;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PhaseIndicator getPhaseIndicator() {
|
public PhaseIndicator getPhaseIndicator() {
|
||||||
return phaseIndicator;
|
return phaseIndicator;
|
||||||
}
|
}
|
||||||
@@ -198,23 +193,67 @@ public class VField implements IVDoc<CField> {
|
|||||||
return detailsPanel;
|
return detailsPanel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isHighlighted() {
|
private boolean isHighlighted() {
|
||||||
return control.getMatchUI().isHighlighted(player);
|
return control.getMatchUI().isHighlighted(player);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setAvatar(final SkinImage avatar) {
|
||||||
|
lblAvatar.setIcon(avatar);
|
||||||
|
lblAvatar.getResizeTimer().start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateManaPool() {
|
||||||
|
detailsPanel.updateManaPool();
|
||||||
|
}
|
||||||
|
public void updateZones() {
|
||||||
|
detailsPanel.updateZones();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addLblPoison() {
|
||||||
|
if (lblPoison.isShowing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
avatarArea.remove(lblLife);
|
||||||
|
avatarArea.add(lblLife, "w 50%!, h 20px!, split 2");
|
||||||
|
avatarArea.add(lblPoison, "w 50%!, h 20px!, wrap");
|
||||||
|
}
|
||||||
|
private void removeLblPoison() {
|
||||||
|
if (!lblPoison.isShowing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
avatarArea.remove(lblPoison);
|
||||||
|
avatarArea.remove(lblLife);
|
||||||
|
avatarArea.add(lblLife, "w 100%!, h 20px!, wrap");
|
||||||
|
}
|
||||||
|
|
||||||
public void updateDetails() {
|
public void updateDetails() {
|
||||||
control.getMatchUI().getCPlayers().update();
|
control.getMatchUI().getCPlayers().update();
|
||||||
detailsPanel.updateDetails();
|
detailsPanel.updateDetails();
|
||||||
|
|
||||||
this.getLblLife().setText("" + player.getLife());
|
// Update life total
|
||||||
if (player.getLife() > 5) {
|
final int life = player.getLife();
|
||||||
this.getLblLife().setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
lblLife.setText(String.valueOf(life));
|
||||||
}
|
if (life > LIFE_CRITICAL) {
|
||||||
else {
|
lblLife.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
||||||
this.getLblLife().setForeground(Color.red);
|
} else {
|
||||||
|
lblLife.setForeground(Color.RED);
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean highlighted = isHighlighted();
|
// Update poison counters
|
||||||
|
final int poison = player.getPoisonCounters();
|
||||||
|
if (poison > 0) {
|
||||||
|
addLblPoison();
|
||||||
|
lblPoison.setText(String.valueOf(poison));
|
||||||
|
if (poison < POISON_CRITICAL) {
|
||||||
|
lblPoison.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
||||||
|
} else {
|
||||||
|
lblPoison.setForeground(Color.RED);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
removeLblPoison();
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean highlighted = isHighlighted();
|
||||||
this.avatarArea.setBorder(highlighted ? borderAvatarHighlighted : borderAvatarSimple );
|
this.avatarArea.setBorder(highlighted ? borderAvatarHighlighted : borderAvatarSimple );
|
||||||
this.avatarArea.setOpaque(highlighted);
|
this.avatarArea.setOpaque(highlighted);
|
||||||
this.avatarArea.setToolTipText(player.getDetailsHtml());
|
this.avatarArea.setToolTipText(player.getDetailsHtml());
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package forge.toolbox.special;
|
package forge.toolbox.special;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
import java.awt.Font;
|
import java.awt.Font;
|
||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
@@ -33,23 +34,23 @@ public class PlayerDetailsPanel extends JPanel {
|
|||||||
private final PlayerView player;
|
private final PlayerView player;
|
||||||
|
|
||||||
// Info labels
|
// Info labels
|
||||||
private final FLabel lblHand = new DetailLabel(FSkinProp.IMG_ZONE_HAND, "99", "Cards in hand");
|
private final DetailLabel lblHand = new DetailLabel(FSkinProp.IMG_ZONE_HAND, "Hand (%s/%s)");
|
||||||
private final FLabel lblGraveyard = new DetailLabel(FSkinProp.IMG_ZONE_GRAVEYARD, "99", "Cards in graveyard");
|
private final DetailLabel lblGraveyard = new DetailLabel(FSkinProp.IMG_ZONE_GRAVEYARD, "Graveyard (%s)");
|
||||||
private final FLabel lblLibrary = new DetailLabel(FSkinProp.IMG_ZONE_LIBRARY, "99", "Cards in library");
|
private final DetailLabel lblLibrary = new DetailLabel(FSkinProp.IMG_ZONE_LIBRARY, "Library (%s)");
|
||||||
private final FLabel lblExile = new DetailLabel(FSkinProp.IMG_ZONE_EXILE, "99", "Exiled cards");
|
private final DetailLabel lblExile = new DetailLabel(FSkinProp.IMG_ZONE_EXILE, "Exile (%s)");
|
||||||
private final FLabel lblFlashback = new DetailLabel(FSkinProp.IMG_ZONE_FLASHBACK, "99", "Flashback cards");
|
private final DetailLabel lblFlashback = new DetailLabel(FSkinProp.IMG_ZONE_FLASHBACK, "Flashback cards (%s)");
|
||||||
private final FLabel lblPoison = new DetailLabel(FSkinProp.IMG_ZONE_POISON, "99", "Poison counters");
|
private final DetailLabel lblPoison = new DetailLabel(FSkinProp.IMG_ZONE_POISON, "Poison counters (%s)");
|
||||||
private final List<Pair<DetailLabel, Byte>> manaLabels = new ArrayList<Pair<DetailLabel, Byte>>();
|
private final List<Pair<DetailLabel, Byte>> manaLabels = new ArrayList<Pair<DetailLabel, Byte>>();
|
||||||
|
|
||||||
public PlayerDetailsPanel(final PlayerView player0) {
|
public PlayerDetailsPanel(final PlayerView player0) {
|
||||||
player = player0;
|
player = player0;
|
||||||
|
|
||||||
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_B, "99", "Black mana"), MagicColor.BLACK));
|
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_W, "White mana (%s)"), MagicColor.WHITE));
|
||||||
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_U, "99", "Blue mana"), MagicColor.BLUE));
|
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_U, "Blue mana (%s)"), MagicColor.BLUE));
|
||||||
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_G, "99", "Green mana"), MagicColor.GREEN));
|
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_B, "Black mana (%s)"), MagicColor.BLACK));
|
||||||
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_R, "99", "Red mana"), MagicColor.RED));
|
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_R, "Red mana (%s)"), MagicColor.RED));
|
||||||
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_W, "99", "White mana"), MagicColor.WHITE));
|
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_G, "Green mana (%s)"), MagicColor.GREEN));
|
||||||
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_COLORLESS, "99", "Colorless mana"), (byte)0));
|
manaLabels.add(Pair.of(new DetailLabel(FSkinProp.IMG_MANA_COLORLESS, "Colorless mana (%s)"), MagicColor.COLORLESS));
|
||||||
|
|
||||||
setOpaque(false);
|
setOpaque(false);
|
||||||
setLayout(new MigLayout("insets 0, gap 0, wrap"));
|
setLayout(new MigLayout("insets 0, gap 0, wrap"));
|
||||||
@@ -105,74 +106,59 @@ public class PlayerDetailsPanel extends JPanel {
|
|||||||
add(row6, constraintsRow);
|
add(row6, constraintsRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Component getLblLibrary() {
|
||||||
|
return lblLibrary;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles observer update of player Zones - hand, graveyard, etc.
|
* Handles observer update of player Zones - hand, graveyard, etc.
|
||||||
*
|
*
|
||||||
* @param p0   {@link forge.game.player.Player}
|
* @param p0   {@link forge.game.player.Player}
|
||||||
*/
|
*/
|
||||||
public void updateZones() {
|
public void updateZones() {
|
||||||
getLblHand().setText("" + player.getHandSize());
|
final String handSize = String.valueOf(player.getHandSize()),
|
||||||
final String handMaxToolTip = player.hasUnlimitedHandSize()
|
graveyardSize = String.valueOf(player.getGraveyardSize()),
|
||||||
? "no maximum hand size" : String.valueOf(player.getMaxHandSize());
|
librarySize = String.valueOf(player.getLibrarySize()),
|
||||||
getLblHand().setToolTipText("Cards in hand (max: " + handMaxToolTip + ")");
|
flashbackSize = String.valueOf(player.getFlashbackSize()),
|
||||||
getLblGraveyard().setText("" + player.getGraveyardSize());
|
exileSize = String.valueOf(player.getExileSize());
|
||||||
getLblLibrary().setText("" + player.getLibrarySize());
|
lblHand.setText(handSize);
|
||||||
getLblFlashback().setText("" + player.getFlashbackSize());
|
lblHand.setToolTip(handSize, player.getMaxHandString());
|
||||||
getLblExile().setText("" + player.getExileSize());
|
lblGraveyard.setText(graveyardSize);
|
||||||
|
lblGraveyard.setToolTip(graveyardSize);
|
||||||
|
lblLibrary.setText(librarySize);
|
||||||
|
lblLibrary.setToolTip(librarySize);
|
||||||
|
lblFlashback.setText(flashbackSize);
|
||||||
|
lblFlashback.setToolTip(flashbackSize);
|
||||||
|
lblExile.setText(exileSize);
|
||||||
|
lblExile.setToolTip(exileSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles observer update of non-Zone details - life, poison, etc. Also
|
* Handles observer update of non-Zone details (poison).
|
||||||
* updates "players" panel in tabber for this player.
|
|
||||||
*
|
|
||||||
* @param p0   {@link forge.game.player.Player}
|
|
||||||
*/
|
*/
|
||||||
public void updateDetails() {
|
public void updateDetails() {
|
||||||
// Poison/life
|
// Poison
|
||||||
getLblPoison().setText("" + player.getPoisonCounters());
|
final int poison = player.getPoisonCounters();
|
||||||
if (player.getPoisonCounters() < 8) {
|
lblPoison.setText(String.valueOf(poison));
|
||||||
getLblPoison().setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
lblPoison.setToolTip(String.valueOf(poison));
|
||||||
}
|
if (poison < 8) {
|
||||||
else {
|
lblPoison.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT));
|
||||||
getLblPoison().setForeground(Color.red);
|
} else {
|
||||||
|
lblPoison.setForeground(Color.red);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles observer update of the mana pool.
|
* Handles observer update of the mana pool.
|
||||||
*
|
|
||||||
* @param p0   {@link forge.game.player.Player}
|
|
||||||
*/
|
*/
|
||||||
public void updateManaPool() {
|
public void updateManaPool() {
|
||||||
for (final Pair<DetailLabel, Byte> label : manaLabels) {
|
for (final Pair<DetailLabel, Byte> label : manaLabels) {
|
||||||
label.getKey().setText(Integer.toString(player.getMana(label.getRight())));
|
final String mana = String.valueOf(player.getMana(label.getRight().byteValue()));
|
||||||
|
label.getKey().setText(mana);
|
||||||
|
label.getKey().setToolTip(mana);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public FLabel getLblHand() {
|
|
||||||
return lblHand;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FLabel getLblLibrary() {
|
|
||||||
return lblLibrary;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FLabel getLblGraveyard() {
|
|
||||||
return lblGraveyard;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FLabel getLblExile() {
|
|
||||||
return lblExile;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FLabel getLblFlashback() {
|
|
||||||
return lblFlashback;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FLabel getLblPoison() {
|
|
||||||
return lblPoison;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setupMouseActions(final ForgeAction handAction, final ForgeAction libraryAction, final ForgeAction exileAction,
|
public void setupMouseActions(final ForgeAction handAction, final ForgeAction libraryAction, final ForgeAction exileAction,
|
||||||
final ForgeAction graveAction, final ForgeAction flashBackAction, final Function<Byte, Boolean> manaAction) {
|
final ForgeAction graveAction, final ForgeAction flashBackAction, final Function<Byte, Boolean> manaAction) {
|
||||||
// Detail label listeners
|
// Detail label listeners
|
||||||
@@ -212,7 +198,8 @@ public class PlayerDetailsPanel extends JPanel {
|
|||||||
@Override
|
@Override
|
||||||
public void onLeftClick(final MouseEvent e) {
|
public void onLeftClick(final MouseEvent e) {
|
||||||
//if shift key down, keep using mana until it runs out or no longer can be put towards the cost
|
//if shift key down, keep using mana until it runs out or no longer can be put towards the cost
|
||||||
while (manaAction.apply(labelPair.getRight()) && e.isShiftDown()) {}
|
final Byte mana = labelPair.getRight();
|
||||||
|
while (manaAction.apply(mana) && e.isShiftDown()) {}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -220,33 +207,39 @@ public class PlayerDetailsPanel extends JPanel {
|
|||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
private class DetailLabel extends FLabel {
|
private class DetailLabel extends FLabel {
|
||||||
private DetailLabel(FSkinProp p0, String s0, String s1) {
|
private final String tooltip;
|
||||||
super(new FLabel.Builder().icon(FSkin.getImage(p0))
|
private DetailLabel(final FSkinProp icon, final String tooltip) {
|
||||||
|
super(new FLabel.Builder().icon(FSkin.getImage(icon))
|
||||||
.opaque(false).fontSize(14).hoverable()
|
.opaque(false).fontSize(14).hoverable()
|
||||||
.fontStyle(Font.BOLD).iconInBackground()
|
.fontStyle(Font.BOLD).iconInBackground()
|
||||||
.text(s0).tooltip(s1).fontAlign(SwingConstants.RIGHT));
|
.fontAlign(SwingConstants.RIGHT));
|
||||||
|
|
||||||
|
this.tooltip = tooltip;
|
||||||
setFocusable(false);
|
setFocusable(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setText(String text0) {
|
public void setText(final String text0) {
|
||||||
super.setText(text0);
|
super.setText(text0);
|
||||||
autoSizeFont();
|
autoSizeFont();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setToolTip(final String... args) {
|
||||||
|
super.setToolTipText(String.format(tooltip, (Object[]) args));
|
||||||
|
}
|
||||||
|
|
||||||
protected void resetIcon() {
|
protected void resetIcon() {
|
||||||
super.resetIcon();
|
super.resetIcon();
|
||||||
autoSizeFont();
|
autoSizeFont();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void autoSizeFont() {
|
private void autoSizeFont() {
|
||||||
String text = getText();
|
final String text = getText();
|
||||||
if (StringUtils.isEmpty(text)) { return; }
|
if (StringUtils.isEmpty(text)) { return; }
|
||||||
|
|
||||||
Graphics g = getGraphics();
|
final Graphics g = getGraphics();
|
||||||
if (g == null) { return; }
|
if (g == null) { return; }
|
||||||
|
|
||||||
int max = getMaxTextWidth();
|
final int max = getMaxTextWidth();
|
||||||
|
|
||||||
SkinFont font = null;
|
SkinFont font = null;
|
||||||
for (int fontSize = 14; fontSize > 5; fontSize--) {
|
for (int fontSize = 14; fontSize > 5; fontSize--) {
|
||||||
|
|||||||
@@ -5,4 +5,5 @@ import forge.match.GameLobby.GameLobbyData;
|
|||||||
public interface ILobbyListener {
|
public interface ILobbyListener {
|
||||||
void message(String source, String message);
|
void message(String source, String message);
|
||||||
void update(GameLobbyData state, int slot);
|
void update(GameLobbyData state, int slot);
|
||||||
|
void close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public abstract class GameLobby {
|
|||||||
private final static int MAX_PLAYERS = 8;
|
private final static int MAX_PLAYERS = 8;
|
||||||
|
|
||||||
private GameLobbyData data = new GameLobbyData();
|
private GameLobbyData data = new GameLobbyData();
|
||||||
|
private GameType currentGameType = GameType.Constructed;
|
||||||
private int lastArchenemy = 0;
|
private int lastArchenemy = 0;
|
||||||
|
|
||||||
private IUpdateable listener;
|
private IUpdateable listener;
|
||||||
@@ -69,10 +70,10 @@ public abstract class GameLobby {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public GameType getGameType() {
|
public GameType getGameType() {
|
||||||
return data.currentGameMode;
|
return currentGameType;
|
||||||
}
|
}
|
||||||
public void setGameType(final GameType type) {
|
public void setGameType(final GameType type) {
|
||||||
data.currentGameMode = type;
|
currentGameType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasVariant(final GameType variant) {
|
public boolean hasVariant(final GameType variant) {
|
||||||
@@ -90,7 +91,7 @@ public abstract class GameLobby {
|
|||||||
}
|
}
|
||||||
public void applyToSlot(final int index, final UpdateLobbyPlayerEvent event) {
|
public void applyToSlot(final int index, final UpdateLobbyPlayerEvent event) {
|
||||||
final LobbySlot slot = getSlot(index);
|
final LobbySlot slot = getSlot(index);
|
||||||
if (slot == null) {
|
if (slot == null || event == null) {
|
||||||
throw new NullPointerException();
|
throw new NullPointerException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,10 +131,10 @@ public abstract class GameLobby {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract boolean hasControl();
|
public abstract boolean hasControl();
|
||||||
public abstract boolean mayEdit(final int index);
|
public abstract boolean mayEdit(int index);
|
||||||
public abstract boolean mayControl(final int index);
|
public abstract boolean mayControl(int index);
|
||||||
public abstract boolean mayRemove(final int index);
|
public abstract boolean mayRemove(int index);
|
||||||
protected abstract IGuiGame getGui(final int index);
|
protected abstract IGuiGame getGui(int index);
|
||||||
protected abstract void onGameStarted();
|
protected abstract void onGameStarted();
|
||||||
|
|
||||||
public void addSlot() {
|
public void addSlot() {
|
||||||
@@ -142,6 +143,9 @@ public abstract class GameLobby {
|
|||||||
addSlot(new LobbySlot(type, null, newIndex, newIndex, false, !allowNetworking, Collections.<AIOption>emptySet()));
|
addSlot(new LobbySlot(type, null, newIndex, newIndex, false, !allowNetworking, Collections.<AIOption>emptySet()));
|
||||||
}
|
}
|
||||||
protected final void addSlot(final LobbySlot slot) {
|
protected final void addSlot(final LobbySlot slot) {
|
||||||
|
if (slot == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
if (data.slots.size() >= MAX_PLAYERS) {
|
if (data.slots.size() >= MAX_PLAYERS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -197,7 +201,7 @@ public abstract class GameLobby {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void applyVariant(final GameType variant) {
|
public void applyVariant(final GameType variant) {
|
||||||
data.currentGameMode = variant;
|
setGameType(variant);
|
||||||
data.appliedVariants.add(variant);
|
data.appliedVariants.add(variant);
|
||||||
|
|
||||||
//ensure other necessary variants are unchecked
|
//ensure other necessary variants are unchecked
|
||||||
@@ -231,17 +235,21 @@ public abstract class GameLobby {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void removeVariant(final GameType variant) {
|
public void removeVariant(final GameType variant) {
|
||||||
data.appliedVariants.remove(variant);
|
final boolean changed = data.appliedVariants.remove(variant);
|
||||||
|
if (!changed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (data.appliedVariants.isEmpty()) {
|
if (data.appliedVariants.isEmpty()) {
|
||||||
data.appliedVariants.add(GameType.Constructed);
|
data.appliedVariants.add(GameType.Constructed);
|
||||||
}
|
}
|
||||||
if (variant == data.currentGameMode) {
|
if (variant == currentGameType) {
|
||||||
if (hasVariant(GameType.Commander)) {
|
if (hasVariant(GameType.Commander)) {
|
||||||
data.currentGameMode = GameType.Commander;
|
currentGameType = GameType.Commander;
|
||||||
} else if (hasVariant(GameType.TinyLeaders)) {
|
} else if (hasVariant(GameType.TinyLeaders)) {
|
||||||
data.currentGameMode = GameType.TinyLeaders;
|
currentGameType = GameType.TinyLeaders;
|
||||||
} else {
|
} else {
|
||||||
data.currentGameMode = GameType.Constructed;
|
currentGameType = GameType.Constructed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updateView(true);
|
updateView(true);
|
||||||
@@ -275,7 +283,7 @@ public abstract class GameLobby {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final List<LobbySlot> activeSlots = Lists.newArrayListWithCapacity(getNumberOfSlots());
|
final List<LobbySlot> activeSlots = Lists.newArrayListWithCapacity(getNumberOfSlots());
|
||||||
for (final LobbySlot slot : data.getSlots()) {
|
for (final LobbySlot slot : data.slots) {
|
||||||
if (slot.getType() != LobbySlotType.OPEN) {
|
if (slot.getType() != LobbySlotType.OPEN) {
|
||||||
activeSlots.add(slot);
|
activeSlots.add(slot);
|
||||||
}
|
}
|
||||||
@@ -290,6 +298,12 @@ public abstract class GameLobby {
|
|||||||
SOptionPane.showMessageDialog(String.format("Please specify a deck for %s", slot.getName()));
|
SOptionPane.showMessageDialog(String.format("Please specify a deck for %s", slot.getName()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (hasVariant(GameType.Commander) || hasVariant(GameType.TinyLeaders)) {
|
||||||
|
if (!slot.getDeck().has(DeckSection.Commander)) {
|
||||||
|
SOptionPane.showMessageDialog(String.format("%s doesn't have a commander", slot.getName()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final Set<GameType> variantTypes = data.appliedVariants;
|
final Set<GameType> variantTypes = data.appliedVariants;
|
||||||
@@ -391,7 +405,7 @@ public abstract class GameLobby {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
schemes = schemePool.toFlatList();
|
schemes = schemePool == null ? Collections.<PaperCard>emptyList() : schemePool.toFlatList();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Planechase
|
//Planechase
|
||||||
@@ -404,7 +418,7 @@ public abstract class GameLobby {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
planes = planePool.toFlatList();
|
planes = planePool == null ? Collections.<PaperCard>emptyList() : planePool.toFlatList();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Vanguard
|
//Vanguard
|
||||||
@@ -441,23 +455,12 @@ public abstract class GameLobby {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final static class GameLobbyData implements Serializable {
|
public final static class GameLobbyData implements Serializable {
|
||||||
private static final long serialVersionUID = -9038854736144187540L;
|
private static final long serialVersionUID = 9184758307999646864L;
|
||||||
|
|
||||||
private transient GameType currentGameMode = GameType.Constructed;
|
|
||||||
private final Set<GameType> appliedVariants = EnumSet.of(GameType.Constructed);
|
private final Set<GameType> appliedVariants = EnumSet.of(GameType.Constructed);
|
||||||
private final List<LobbySlot> slots = Lists.newArrayList();
|
private final List<LobbySlot> slots = Lists.newArrayList();
|
||||||
|
|
||||||
public GameType getCurrentGameMode() {
|
public GameLobbyData() {
|
||||||
return currentGameMode;
|
|
||||||
}
|
|
||||||
public void setCurrentGameMode(GameType currentGameMode) {
|
|
||||||
this.currentGameMode = currentGameMode;
|
|
||||||
}
|
|
||||||
public Set<GameType> getAppliedVariants() {
|
|
||||||
return Collections.unmodifiableSet(appliedVariants);
|
|
||||||
}
|
|
||||||
public List<LobbySlot> getSlots() {
|
|
||||||
return Collections.unmodifiableList(slots);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,10 +62,11 @@ public final class LobbySlot implements Serializable {
|
|||||||
setAiOptions(data.getAiOptions());
|
setAiOptions(data.getAiOptions());
|
||||||
changed = true;
|
changed = true;
|
||||||
}
|
}
|
||||||
|
final Deck oldDeck = getDeck();
|
||||||
if (data.getDeck() != null) {
|
if (data.getDeck() != null) {
|
||||||
setDeck(data.getDeck());
|
setDeck(data.getDeck());
|
||||||
} else if (getDeck() != null && data.getSection() != null && data.getCards() != null) {
|
} else if (oldDeck != null && data.getSection() != null && data.getCards() != null) {
|
||||||
getDeck().putSection(data.getSection(), data.getCards());
|
oldDeck.putSection(data.getSection(), data.getCards());
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,10 @@ public class FGameClient implements IToServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
channel.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void send(final NetEvent event) {
|
public void send(final NetEvent event) {
|
||||||
System.out.println("Client sent " + event);
|
System.out.println("Client sent " + event);
|
||||||
@@ -382,5 +386,13 @@ public class FGameClient implements IToServer {
|
|||||||
}
|
}
|
||||||
super.channelRead(ctx, msg);
|
super.channelRead(ctx, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
|
||||||
|
for (final ILobbyListener listener : lobbyListeners) {
|
||||||
|
listener.close();
|
||||||
|
}
|
||||||
|
super.channelInactive(ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ import com.google.common.collect.Maps;
|
|||||||
public final class FServerManager {
|
public final class FServerManager {
|
||||||
private static FServerManager instance = null;
|
private static FServerManager instance = null;
|
||||||
|
|
||||||
|
private boolean isHosting = false;
|
||||||
private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
||||||
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
|
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||||
private final Map<Channel, RemoteClient> clients = Maps.newTreeMap();
|
private final Map<Channel, RemoteClient> clients = Maps.newTreeMap();
|
||||||
@@ -102,6 +103,7 @@ public final class FServerManager {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}).start();
|
}).start();
|
||||||
|
isHosting = true;
|
||||||
} catch (final InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -110,6 +112,11 @@ public final class FServerManager {
|
|||||||
public void stopServer() {
|
public void stopServer() {
|
||||||
bossGroup.shutdownGracefully();
|
bossGroup.shutdownGracefully();
|
||||||
workerGroup.shutdownGracefully();
|
workerGroup.shutdownGracefully();
|
||||||
|
isHosting = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHosting() {
|
||||||
|
return isHosting;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(final NetEvent event) {
|
public void broadcast(final NetEvent event) {
|
||||||
|
|||||||
Reference in New Issue
Block a user