mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 12:48:00 +00:00
Refactor lobby and add network support.
- Lobby code has been revised completely to support network lobbies; code has been separated into model and view parts. - Added preliminary network game support; most of it should be working but hasn't been tested thoroughly. - Fixed issue where controlling another player wouldn't be recognised by the GUI. - Fixed issue where hand panels wouldn't display anymore. - Minor fixes/cleanup.
This commit is contained in:
@@ -29,7 +29,6 @@ import forge.download.GuiDownloader;
|
||||
import forge.error.BugReportDialog;
|
||||
import forge.gui.BoxedProductCardListViewer;
|
||||
import forge.gui.CardListViewer;
|
||||
import forge.gui.FNetOverlay;
|
||||
import forge.gui.GuiChoose;
|
||||
import forge.gui.framework.FScreen;
|
||||
import forge.interfaces.IGuiBase;
|
||||
@@ -280,9 +279,4 @@ public class GuiDesktop implements IGuiBase {
|
||||
return match;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void netMessage(final String origin, final String message) {
|
||||
FNetOverlay.SINGLETON_INSTANCE.showUp("");
|
||||
FNetOverlay.SINGLETON_INSTANCE.addMessage(origin, message);
|
||||
}
|
||||
}
|
||||
@@ -134,10 +134,15 @@ public enum FNetOverlay {
|
||||
getPanel().setBounds(x, y, w, height);
|
||||
getPanel().validate();
|
||||
}
|
||||
|
||||
SimpleDateFormat inFormat = new SimpleDateFormat("HH:mm:ss");
|
||||
public void addMessage(String origin, String message) {
|
||||
String toAdd = String.format("%n[%s] %s: %s", inFormat.format(new Date()), origin, message);
|
||||
|
||||
private final static SimpleDateFormat inFormat = new SimpleDateFormat("HH:mm:ss");
|
||||
public void addMessage(final String origin, final String message) {
|
||||
final String toAdd;
|
||||
if (origin == null) {
|
||||
toAdd = String.format("%n[%s] %s: %s", inFormat.format(new Date()), origin, message);
|
||||
} else {
|
||||
toAdd = String.format("%n[%s] %s", inFormat.format(new Date()), message);
|
||||
}
|
||||
txtLog.append(toAdd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,39 +2,17 @@ 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 {
|
||||
|
||||
@@ -93,7 +71,7 @@ public class CLobby {
|
||||
|
||||
// Planechase: reinit deck lists and restore last selections (if any)
|
||||
deckList = view.getPlanarDeckLists().get(i);
|
||||
listData = new Vector<Object>();
|
||||
listData = new Vector<Object>();
|
||||
|
||||
listData.add("Use deck's planes section (random if unavailable)");
|
||||
listData.add("Generate");
|
||||
@@ -101,7 +79,7 @@ public class CLobby {
|
||||
listData.add("Random");
|
||||
for (Deck planarDeck : cColl.getPlane()) {
|
||||
listData.add(planarDeck);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val = deckList.getSelectedValue();
|
||||
@@ -118,7 +96,6 @@ public class CLobby {
|
||||
}
|
||||
|
||||
// General updates when switching back to this view
|
||||
view.updatePlayersFromPrefs();
|
||||
view.getBtnStart().requestFocusInWindow();
|
||||
}
|
||||
});
|
||||
@@ -134,14 +111,6 @@ public class CLobby {
|
||||
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() {
|
||||
@@ -165,208 +134,4 @@ public class CLobby {
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@ import java.awt.event.ActionListener;
|
||||
import java.awt.event.FocusAdapter;
|
||||
import java.awt.event.FocusEvent;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.swing.ButtonGroup;
|
||||
import javax.swing.JCheckBoxMenuItem;
|
||||
@@ -17,7 +19,9 @@ import net.miginfocom.swing.MigLayout;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
import forge.AIOption;
|
||||
import forge.Singletons;
|
||||
import forge.UiCommand;
|
||||
import forge.assets.FSkinProp;
|
||||
@@ -25,6 +29,7 @@ import forge.deck.DeckSection;
|
||||
import forge.game.GameType;
|
||||
import forge.gui.framework.FScreen;
|
||||
import forge.item.PaperCard;
|
||||
import forge.match.LobbySlot;
|
||||
import forge.model.FModel;
|
||||
import forge.net.game.LobbySlotType;
|
||||
import forge.properties.ForgePreferences;
|
||||
@@ -32,7 +37,6 @@ 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.VLobby.LobbyType;
|
||||
import forge.screens.home.sanctioned.AvatarSelector;
|
||||
import forge.toolbox.FComboBox;
|
||||
import forge.toolbox.FComboBoxWrapper;
|
||||
@@ -53,17 +57,16 @@ 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 LobbySlotType type;
|
||||
private final int index;
|
||||
private final LobbyType lobbyType;
|
||||
|
||||
private LobbySlotType type = LobbySlotType.LOCAL;
|
||||
private boolean editableForClient;
|
||||
private String playerName = StringUtils.EMPTY;
|
||||
private boolean mayEdit, mayControl, mayRemove;
|
||||
|
||||
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 final FTextField txtPlayerName = new FTextField.Builder().build();
|
||||
private FRadioButton radioHuman;
|
||||
private FRadioButton radioAi;
|
||||
private JCheckBoxMenuItem radioAiUseSimulation;
|
||||
@@ -78,7 +81,6 @@ public class PlayerPanel extends FPanel {
|
||||
|
||||
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;
|
||||
@@ -95,26 +97,25 @@ public class PlayerPanel extends FPanel {
|
||||
private final FLabel vgdLabel;
|
||||
|
||||
private final VLobby lobby;
|
||||
public PlayerPanel(final VLobby lobby, final int index, final LobbyType lobbyType) {
|
||||
public PlayerPanel(final VLobby lobby, final boolean allowNetworking, final int index, final LobbySlot slot, final boolean mayEdit, final boolean mayControl) {
|
||||
super();
|
||||
|
||||
this.lobby = lobby;
|
||||
this.index = index;
|
||||
this.mayEdit = mayEdit;
|
||||
this.mayControl = mayControl;
|
||||
|
||||
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.lobbyType = lobbyType;
|
||||
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
|
||||
closeBtn = createCloseButton();
|
||||
if (index >= 2 || lobbyType == LobbyType.SERVER) {
|
||||
this.add(closeBtn, "w 20, h 20, pos (container.w-20) 0");
|
||||
}
|
||||
this.add(closeBtn, "w 20, h 20, pos (container.w-20) 0");
|
||||
|
||||
createAvatar();
|
||||
this.add(avatarLabel, "spany 2, width 80px, height 80px");
|
||||
@@ -132,12 +133,18 @@ public class PlayerPanel extends FPanel {
|
||||
|
||||
this.add(lobby.newLabel("Team:"), "w 40px, h 30px");
|
||||
populateTeamsComboBoxes();
|
||||
|
||||
// Set these before action listeners are added
|
||||
this.setTeam(slot == null ? index : slot.getTeam());
|
||||
this.setIsArchenemy(slot != null && slot.isArchenemy());
|
||||
|
||||
teamComboBox.addActionListener(teamListener);
|
||||
aeTeamComboBox.addActionListener(teamListener);
|
||||
teamComboBox.addTo(this, variantBtnConstraints + ", pushx, growx, gaptop 5px");
|
||||
aeTeamComboBox.addTo(this, variantBtnConstraints + ", pushx, growx, gaptop 5px");
|
||||
if (lobbyType == LobbyType.SERVER) {
|
||||
this.add(radioOpen, "gapleft 1px");
|
||||
|
||||
if (allowNetworking) {
|
||||
this.add(radioOpen, "cell 4 1, ax left, sx 2, wrap");
|
||||
}
|
||||
|
||||
this.add(deckLabel, variantBtnConstraints + ", cell 0 2, sx 2, ax right");
|
||||
@@ -161,7 +168,6 @@ public class PlayerPanel extends FPanel {
|
||||
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) {
|
||||
@@ -169,46 +175,62 @@ public class PlayerPanel extends FPanel {
|
||||
}
|
||||
});
|
||||
|
||||
this.type = slot == null ? LobbySlotType.LOCAL : slot.getType();
|
||||
this.setPlayerName(slot == null ? "" : slot.getName());
|
||||
this.setAvatar(slot == null ? 0 : slot.getAvatarIndex());
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
void update() {
|
||||
if (type != LobbySlotType.REMOTE) {
|
||||
if (radioHuman.isSelected()) {
|
||||
type = LobbySlotType.LOCAL;
|
||||
} else if (radioAi.isSelected()) {
|
||||
type = LobbySlotType.AI;
|
||||
} else if (radioOpen.isSelected()) {
|
||||
type = LobbySlotType.OPEN;
|
||||
}
|
||||
avatarLabel.setEnabled(mayEdit);
|
||||
avatarLabel.setIcon(FSkin.getAvatars().get(Integer.valueOf(type == LobbySlotType.OPEN ? -1 : avatarIndex)));
|
||||
avatarLabel.repaintSelf();
|
||||
|
||||
txtPlayerName.setEnabled(mayEdit);
|
||||
txtPlayerName.setText(type == LobbySlotType.OPEN ? StringUtils.EMPTY : playerName);
|
||||
nameRandomiser.setEnabled(mayEdit);
|
||||
deckLabel.setVisible(mayEdit);
|
||||
deckBtn.setVisible(mayEdit);
|
||||
|
||||
closeBtn.setVisible(mayRemove);
|
||||
|
||||
if (mayRemove) {
|
||||
radioHuman.setEnabled(mayControl);
|
||||
radioAi.setEnabled(mayControl);
|
||||
radioOpen.setEnabled(mayControl);
|
||||
} else {
|
||||
radioHuman.setVisible(mayControl);
|
||||
radioAi.setVisible(mayControl);
|
||||
radioOpen.setVisible(mayControl);
|
||||
}
|
||||
|
||||
final boolean isEditable = lobbyType == LobbyType.LOCAL || type == LobbySlotType.LOCAL ||
|
||||
(lobbyType == LobbyType.SERVER && (type == LobbySlotType.LOCAL || type == LobbySlotType.AI)) ||
|
||||
(lobbyType == LobbyType.CLIENT && editableForClient);
|
||||
avatarLabel.setEnabled(isEditable);
|
||||
txtPlayerName.setEnabled(isEditable);
|
||||
nameRandomiser.setEnabled(isEditable);
|
||||
deckLabel.setVisible(isEditable);
|
||||
deckBtn.setVisible(isEditable);
|
||||
radioHuman.setSelected(type == LobbySlotType.LOCAL);
|
||||
radioAi.setSelected(type == LobbySlotType.AI);
|
||||
radioOpen.setSelected(type == LobbySlotType.OPEN);
|
||||
|
||||
final boolean hasSlotControls = lobbyType == LobbyType.LOCAL || (lobbyType == LobbyType.SERVER && type != LobbySlotType.REMOTE);
|
||||
closeBtn.setVisible(hasSlotControls);
|
||||
radioAi.setVisible(hasSlotControls);
|
||||
radioHuman.setVisible(hasSlotControls);
|
||||
radioOpen.setVisible(hasSlotControls && lobbyType == LobbyType.SERVER);
|
||||
updateVariantControlsVisibility();
|
||||
}
|
||||
|
||||
private final FMouseAdapter radioMouseAdapter = new FMouseAdapter() {
|
||||
@Override public final void onLeftClick(final MouseEvent e) {
|
||||
avatarLabel.requestFocusInWindow();
|
||||
lobby.updateVanguardList(index);
|
||||
update();
|
||||
}
|
||||
private final FMouseAdapter radioMouseAdapter(final FRadioButton source, final LobbySlotType type) {
|
||||
return new FMouseAdapter() {
|
||||
@Override public final void onLeftClick(final MouseEvent e) {
|
||||
if (!source.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
setType(type);
|
||||
lobby.firePlayerChangeListener(index);
|
||||
avatarLabel.requestFocusInWindow();
|
||||
lobby.updateVanguardList(index);
|
||||
lobby.update();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/** Listens to name text fields and gives the appropriate player focus.
|
||||
* Also saves the name preference when leaving player one's text field. */
|
||||
/**
|
||||
* 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) {
|
||||
@@ -226,7 +248,8 @@ public class PlayerPanel extends FPanel {
|
||||
prefs.setPref(FPref.PLAYER_NAME, newName);
|
||||
prefs.save();
|
||||
}
|
||||
lobby.firePlayerChangeListener();
|
||||
lobby.firePlayerChangeListener(index);
|
||||
lobby.update();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -247,10 +270,10 @@ public class PlayerPanel extends FPanel {
|
||||
|
||||
final FLabel avatar = (FLabel)e.getSource();
|
||||
|
||||
PlayerPanel.this.lobby.changePlayerFocus(index);
|
||||
lobby.changePlayerFocus(index);
|
||||
avatar.requestFocusInWindow();
|
||||
|
||||
final AvatarSelector aSel = new AvatarSelector(getPlayerName(), avatarIndex, PlayerPanel.this.lobby.getUsedAvatars());
|
||||
final AvatarSelector aSel = new AvatarSelector(playerName, avatarIndex, lobby.getUsedAvatars());
|
||||
for (final FLabel lbl : aSel.getSelectables()) {
|
||||
lbl.setCommand(new UiCommand() {
|
||||
@Override
|
||||
@@ -265,64 +288,35 @@ public class PlayerPanel extends FPanel {
|
||||
aSel.dispose();
|
||||
|
||||
if (index < 2) {
|
||||
PlayerPanel.this.lobby.updateAvatarPrefs();
|
||||
lobby.updateAvatarPrefs();
|
||||
}
|
||||
|
||||
lobby.firePlayerChangeListener();
|
||||
lobby.firePlayerChangeListener(index);
|
||||
}
|
||||
@Override public final void onRightClick(final MouseEvent e) {
|
||||
if (!avatarLabel.isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
PlayerPanel.this.lobby.changePlayerFocus(index);
|
||||
lobby.changePlayerFocus(index);
|
||||
avatarLabel.requestFocusInWindow();
|
||||
|
||||
setRandomAvatar();
|
||||
|
||||
if (index < 2) {
|
||||
PlayerPanel.this.lobby.updateAvatarPrefs();
|
||||
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;
|
||||
}
|
||||
}
|
||||
private void updateVariantControlsVisibility() {
|
||||
boolean isCommanderApplied = mayEdit && (lobby.hasVariant(GameType.Commander) || lobby.hasVariant(GameType.TinyLeaders));
|
||||
boolean isPlanechaseApplied = mayEdit && lobby.hasVariant(GameType.Planechase);
|
||||
boolean isVanguardApplied = mayEdit && lobby.hasVariant(GameType.Vanguard);
|
||||
boolean isArchenemyApplied = mayEdit && lobby.hasVariant(GameType.Archenemy);
|
||||
boolean archenemyVisiblity = mayEdit && lobby.hasVariant(GameType.ArchenemyRumble) || (isArchenemyApplied && isArchenemy());
|
||||
// Commander deck building replaces normal one, so hide it
|
||||
boolean isDeckBuildingAllowed = mayEdit && !isCommanderApplied && !lobby.hasVariant(GameType.MomirBasic);
|
||||
|
||||
deckLabel.setVisible(isDeckBuildingAllowed);
|
||||
deckBtn.setVisible(isDeckBuildingAllowed);
|
||||
@@ -336,7 +330,6 @@ public class PlayerPanel extends FPanel {
|
||||
|
||||
teamComboBox.setVisible(!isArchenemyApplied);
|
||||
aeTeamComboBox.setVisible(isArchenemyApplied);
|
||||
aeTeamComboBox.setEnabled(!(isArchenemyApplied && playerIsArchenemy));
|
||||
|
||||
pchDeckSelectorBtn.setVisible(isPlanechaseApplied);
|
||||
pchDeckEditor.setVisible(isPlanechaseApplied);
|
||||
@@ -367,30 +360,53 @@ public class PlayerPanel extends FPanel {
|
||||
return type == LobbySlotType.AI;
|
||||
}
|
||||
|
||||
public boolean isSimulatedAi() {
|
||||
public Set<AIOption> getAiOptions() {
|
||||
return isSimulatedAi()
|
||||
? ImmutableSet.of(AIOption.USE_SIMULATION)
|
||||
: Collections.<AIOption>emptySet();
|
||||
}
|
||||
private boolean isSimulatedAi() {
|
||||
return radioAi.isSelected() && radioAiUseSimulation.isSelected();
|
||||
}
|
||||
public void setUseAiSimulation(final boolean useSimulation) {
|
||||
radioAi.setSelected(useSimulation);
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
return type == LobbySlotType.LOCAL;
|
||||
}
|
||||
|
||||
public boolean isArchenemy() {
|
||||
return playerIsArchenemy;
|
||||
return aeTeamComboBox.getSelectedIndex() == 0;
|
||||
}
|
||||
|
||||
public void setRemote(final boolean remote) {
|
||||
if (remote) {
|
||||
type = LobbySlotType.REMOTE;
|
||||
} else {
|
||||
public void setType(final LobbySlotType type) {
|
||||
this.type = type;
|
||||
switch (type) {
|
||||
case LOCAL:
|
||||
radioHuman.setSelected(true);
|
||||
break;
|
||||
case AI:
|
||||
radioAi.setSelected(true);
|
||||
break;
|
||||
case OPEN:
|
||||
radioOpen.setSelected(true);
|
||||
type = LobbySlotType.OPEN;
|
||||
break;
|
||||
case REMOTE:
|
||||
break;
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
public void setEditableForClient(final boolean editable) {
|
||||
editableForClient = editable;
|
||||
public void setRemote(final boolean remote) {
|
||||
if (remote) {
|
||||
setType(LobbySlotType.REMOTE);
|
||||
radioHuman.setSelected(false);
|
||||
radioAi.setSelected(false);
|
||||
radioOpen.setSelected(false);
|
||||
} else {
|
||||
setType(LobbySlotType.OPEN);
|
||||
}
|
||||
}
|
||||
|
||||
public void setVanguardButtonText(String text) {
|
||||
@@ -408,77 +424,46 @@ public class PlayerPanel extends FPanel {
|
||||
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();
|
||||
@Override public final void actionPerformed(final ActionEvent e) {
|
||||
final FComboBox<Object> cb = (FComboBox<Object>) e.getSource();
|
||||
cb.requestFocusInWindow();
|
||||
Object selection = cb.getSelectedItem();
|
||||
final Object selection = cb.getSelectedItem();
|
||||
|
||||
if (null == selection) {
|
||||
return;
|
||||
if (null != selection) {
|
||||
lobby.changePlayerFocus(index);
|
||||
lobby.firePlayerChangeListener(index);
|
||||
}
|
||||
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
|
||||
// Archenemy buttons
|
||||
scmDeckSelectorBtn.setCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerPanel.this.lobby.setCurrentGameMode(PlayerPanel.this.lobby.getVntArchenemy().isSelected() ? GameType.Archenemy : GameType.ArchenemyRumble);
|
||||
@Override public final void run() {
|
||||
lobby.setCurrentGameMode(lobby.getVntArchenemy().isSelected() ? GameType.Archenemy : GameType.ArchenemyRumble);
|
||||
scmDeckSelectorBtn.requestFocusInWindow();
|
||||
PlayerPanel.this.lobby.changePlayerFocus(index, PlayerPanel.this.lobby.getCurrentGameMode());
|
||||
lobby.changePlayerFocus(index);
|
||||
}
|
||||
});
|
||||
|
||||
scmDeckEditor.setCommand(new UiCommand() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerPanel.this.lobby.setCurrentGameMode(PlayerPanel.this.lobby.getVntArchenemy().isSelected() ? GameType.Archenemy : GameType.ArchenemyRumble);
|
||||
lobby.setCurrentGameMode(lobby.getVntArchenemy().isSelected() ? GameType.Archenemy : GameType.ArchenemyRumble);
|
||||
Predicate<PaperCard> predSchemes = new Predicate<PaperCard>() {
|
||||
@Override
|
||||
public boolean apply(PaperCard arg0) {
|
||||
@Override public final boolean apply(final PaperCard arg0) {
|
||||
return arg0.getRules().getType().isScheme();
|
||||
}
|
||||
};
|
||||
@@ -493,16 +478,16 @@ public class PlayerPanel extends FPanel {
|
||||
cmdDeckSelectorBtn.setCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerPanel.this.lobby.setCurrentGameMode(PlayerPanel.this.lobby.getVntTinyLeaders().isSelected() ? GameType.TinyLeaders : GameType.Commander);
|
||||
lobby.setCurrentGameMode(lobby.getVntTinyLeaders().isSelected() ? GameType.TinyLeaders : GameType.Commander);
|
||||
cmdDeckSelectorBtn.requestFocusInWindow();
|
||||
PlayerPanel.this.lobby.changePlayerFocus(index, PlayerPanel.this.lobby.getCurrentGameMode());
|
||||
lobby.changePlayerFocus(index);
|
||||
}
|
||||
});
|
||||
|
||||
cmdDeckEditor.setCommand(new UiCommand() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerPanel.this.lobby.setCurrentGameMode(PlayerPanel.this.lobby.getVntTinyLeaders().isSelected() ? GameType.TinyLeaders : GameType.Commander);
|
||||
lobby.setCurrentGameMode(lobby.getVntTinyLeaders().isSelected() ? GameType.TinyLeaders : GameType.Commander);
|
||||
Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_COMMANDER);
|
||||
CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(new CEditorCommander(CDeckEditorUI.SINGLETON_INSTANCE.getCDetailPicture()));
|
||||
}
|
||||
@@ -512,16 +497,16 @@ public class PlayerPanel extends FPanel {
|
||||
pchDeckSelectorBtn.setCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Planechase);
|
||||
lobby.setCurrentGameMode(GameType.Planechase);
|
||||
pchDeckSelectorBtn.requestFocusInWindow();
|
||||
PlayerPanel.this.lobby.changePlayerFocus(index, GameType.Planechase);
|
||||
lobby.changePlayerFocus(index, GameType.Planechase);
|
||||
}
|
||||
});
|
||||
|
||||
pchDeckEditor.setCommand(new UiCommand() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Planechase);
|
||||
lobby.setCurrentGameMode(GameType.Planechase);
|
||||
Predicate<PaperCard> predPlanes = new Predicate<PaperCard>() {
|
||||
@Override
|
||||
public boolean apply(PaperCard arg0) {
|
||||
@@ -539,9 +524,9 @@ public class PlayerPanel extends FPanel {
|
||||
vgdSelectorBtn.setCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Vanguard);
|
||||
lobby.setCurrentGameMode(GameType.Vanguard);
|
||||
vgdSelectorBtn.requestFocusInWindow();
|
||||
PlayerPanel.this.lobby.changePlayerFocus(index, GameType.Vanguard);
|
||||
lobby.changePlayerFocus(index, GameType.Vanguard);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -550,18 +535,22 @@ public class PlayerPanel extends FPanel {
|
||||
* @param index
|
||||
*/
|
||||
private void createPlayerTypeOptions() {
|
||||
final boolean isServer = lobbyType == LobbyType.SERVER;
|
||||
radioHuman = new FRadioButton(isServer ? "Local" : "Human", index == 0);
|
||||
radioAi = new FRadioButton("AI", !isServer && index != 0);
|
||||
radioOpen = new FRadioButton("Open", isServer && index != 0);
|
||||
radioHuman = new FRadioButton("Human");
|
||||
radioAi = new FRadioButton("AI");
|
||||
radioOpen = new FRadioButton("Open");
|
||||
|
||||
final JPopupMenu menu = new JPopupMenu();
|
||||
radioAiUseSimulation = new JCheckBoxMenuItem("Use Simulation");
|
||||
menu.add(radioAiUseSimulation);
|
||||
radioAiUseSimulation.addActionListener(new ActionListener() {
|
||||
@Override public final void actionPerformed(final ActionEvent e) {
|
||||
lobby.firePlayerChangeListener(index);
|
||||
} });
|
||||
radioAi.setComponentPopupMenu(menu);
|
||||
|
||||
radioHuman.addMouseListener(radioMouseAdapter);
|
||||
radioAi.addMouseListener(radioMouseAdapter);
|
||||
radioOpen.addMouseListener(radioMouseAdapter);
|
||||
radioHuman.addMouseListener(radioMouseAdapter(radioHuman, LobbySlotType.LOCAL));
|
||||
radioAi.addMouseListener (radioMouseAdapter(radioAi, LobbySlotType.AI));
|
||||
radioOpen.addMouseListener (radioMouseAdapter(radioOpen, LobbySlotType.OPEN));
|
||||
|
||||
final ButtonGroup tempBtnGroup = new ButtonGroup();
|
||||
tempBtnGroup.add(radioHuman);
|
||||
@@ -576,9 +565,9 @@ public class PlayerPanel extends FPanel {
|
||||
deckBtn.setCommand(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Constructed);
|
||||
lobby.setCurrentGameMode(GameType.Constructed);
|
||||
deckBtn.requestFocusInWindow();
|
||||
PlayerPanel.this.lobby.changePlayerFocus(index, GameType.Constructed);
|
||||
lobby.changePlayerFocus(index, GameType.Constructed);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -594,7 +583,7 @@ public class PlayerPanel extends FPanel {
|
||||
newNameBtn.setCommand(new UiCommand() {
|
||||
@Override
|
||||
public void run() {
|
||||
String newName = PlayerPanel.this.lobby.getNewName();
|
||||
String newName = lobby.getNewName();
|
||||
if (null == newName) {
|
||||
return;
|
||||
}
|
||||
@@ -605,7 +594,7 @@ public class PlayerPanel extends FPanel {
|
||||
prefs.save();
|
||||
}
|
||||
txtPlayerName.requestFocus();
|
||||
PlayerPanel.this.lobby.changePlayerFocus(index);
|
||||
lobby.changePlayerFocus(index);
|
||||
}
|
||||
});
|
||||
newNameBtn.addFocusListener(nameFocusListener);
|
||||
@@ -640,10 +629,10 @@ public class PlayerPanel extends FPanel {
|
||||
.icon(FSkin.getIcon(FSkinProp.ICO_CLOSE)).hoverable(true).build();
|
||||
closeBtn.setCommand(new Runnable() {
|
||||
@Override public final void run() {
|
||||
if (type == LobbySlotType.REMOTE && !SOptionPane.showConfirmDialog(String.format("Really kick %s?", getPlayerName()), "Kick", false)) {
|
||||
if (type == LobbySlotType.REMOTE && !SOptionPane.showConfirmDialog(String.format("Really kick %s?", playerName), "Kick", false)) {
|
||||
return;
|
||||
}
|
||||
PlayerPanel.this.lobby.removePlayer(index);
|
||||
lobby.removePlayer(index);
|
||||
}
|
||||
});
|
||||
return closeBtn;
|
||||
@@ -654,9 +643,8 @@ public class PlayerPanel extends FPanel {
|
||||
if (index < currentPrefs.length) {
|
||||
avatarIndex = Integer.parseInt(currentPrefs[index]);
|
||||
avatarLabel.setIcon(FSkin.getAvatars().get(avatarIndex));
|
||||
}
|
||||
else {
|
||||
setRandomAvatar();
|
||||
} else {
|
||||
setRandomAvatar(false);
|
||||
}
|
||||
|
||||
avatarLabel.setToolTipText("L-click: Select avatar. R-click: Randomize avatar.");
|
||||
@@ -664,25 +652,22 @@ public class PlayerPanel extends FPanel {
|
||||
avatarLabel.addMouseListener(avatarMouseListener);
|
||||
}
|
||||
|
||||
/** Applies a random avatar, avoiding avatars already used.
|
||||
* @param playerIndex */
|
||||
public void setRandomAvatar() {
|
||||
/** Applies a random avatar, avoiding avatars already used. */
|
||||
private void setRandomAvatar() {
|
||||
setRandomAvatar(true);
|
||||
}
|
||||
private void setRandomAvatar(final boolean fireListeners) {
|
||||
int random = 0;
|
||||
|
||||
List<Integer> usedAvatars = lobby.getUsedAvatars();
|
||||
final List<Integer> usedAvatars = lobby.getUsedAvatars();
|
||||
do {
|
||||
random = MyRandom.getRandom().nextInt(FSkin.getAvatars().size());
|
||||
} while (usedAvatars.contains(random));
|
||||
setAvatar(random);
|
||||
|
||||
lobby.firePlayerChangeListener();
|
||||
}
|
||||
|
||||
public void setAvatar(int newAvatarIndex) {
|
||||
avatarIndex = newAvatarIndex;
|
||||
SkinImage icon = FSkin.getAvatars().get(newAvatarIndex);
|
||||
avatarLabel.setIcon(icon);
|
||||
avatarLabel.repaintSelf();
|
||||
if (fireListeners) {
|
||||
lobby.firePlayerChangeListener(index);
|
||||
}
|
||||
}
|
||||
|
||||
private final FSkin.LineSkinBorder focusedBorder = new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS).alphaColor(255), 3);
|
||||
@@ -690,18 +675,53 @@ public class PlayerPanel extends FPanel {
|
||||
|
||||
public void setFocused(boolean focused) {
|
||||
avatarLabel.setBorder(focused ? focusedBorder : defaultBorder);
|
||||
avatarLabel.setHoverable(focused);
|
||||
}
|
||||
|
||||
String getPlayerName() {
|
||||
return txtPlayerName.getText();
|
||||
}
|
||||
public void setPlayerName(final String string) {
|
||||
playerName = string;
|
||||
txtPlayerName.setText(string);
|
||||
}
|
||||
|
||||
public int getAvatarIndex() {
|
||||
return avatarIndex;
|
||||
}
|
||||
|
||||
public void setPlayerName(String string) {
|
||||
txtPlayerName.setText(string);
|
||||
public void setAvatar(final int newAvatarIndex) {
|
||||
avatarIndex = newAvatarIndex;
|
||||
final SkinImage icon = FSkin.getAvatars().get(newAvatarIndex);
|
||||
avatarLabel.setIcon(icon);
|
||||
avatarLabel.repaintSelf();
|
||||
}
|
||||
|
||||
public String getPlayerName() {
|
||||
return txtPlayerName.getText();
|
||||
public int getTeam() {
|
||||
return teamComboBox.getSelectedIndex();
|
||||
}
|
||||
public void setTeam(final int team) {
|
||||
teamComboBox.suppressActionListeners();
|
||||
teamComboBox.setSelectedIndex(team);
|
||||
teamComboBox.unsuppressActionListeners();
|
||||
}
|
||||
|
||||
public int getArchenemyTeam() {
|
||||
return aeTeamComboBox.getSelectedIndex();
|
||||
}
|
||||
public void setIsArchenemy(final boolean isArchenemy) {
|
||||
aeTeamComboBox.suppressActionListeners();
|
||||
aeTeamComboBox.setSelectedIndex(isArchenemy ? 0 : 1);
|
||||
aeTeamComboBox.unsuppressActionListeners();
|
||||
}
|
||||
|
||||
public void setMayEdit(final boolean mayEdit) {
|
||||
this.mayEdit = mayEdit;
|
||||
}
|
||||
|
||||
public void setMayControl(final boolean mayControl) {
|
||||
this.mayControl = mayControl;
|
||||
}
|
||||
|
||||
public void setMayRemove(final boolean mayRemove) {
|
||||
this.mayRemove = mayRemove;
|
||||
}
|
||||
}
|
||||
@@ -137,7 +137,7 @@ public enum VHomeUI implements IVTopLevelUI {
|
||||
allSubmenus.add(VSubmenuSealed.SINGLETON_INSTANCE);
|
||||
//allSubmenus.add(VSubmenuWinston.SINGLETON_INSTANCE);
|
||||
|
||||
allSubmenus.add(VSubmenuOnlineLobby.SINGLETON_INSTANCE);
|
||||
//allSubmenus.add(VSubmenuOnlineLobby.SINGLETON_INSTANCE);
|
||||
|
||||
allSubmenus.add(VSubmenuDuels.SINGLETON_INSTANCE);
|
||||
allSubmenus.add(VSubmenuChallenges.SINGLETON_INSTANCE);
|
||||
|
||||
@@ -6,14 +6,9 @@ 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;
|
||||
@@ -24,25 +19,31 @@ import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.AIOption;
|
||||
import forge.UiCommand;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.deck.DeckSection;
|
||||
import forge.deck.DeckType;
|
||||
import forge.deck.DeckgenUtil;
|
||||
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.interfaces.ILobby;
|
||||
import forge.interfaces.IPlayerChangeListener;
|
||||
import forge.interfaces.IUpdateable;
|
||||
import forge.item.PaperCard;
|
||||
import forge.match.GameLobby;
|
||||
import forge.match.LobbySlot;
|
||||
import forge.model.FModel;
|
||||
import forge.net.game.LobbySlotType;
|
||||
import forge.net.game.LobbyState;
|
||||
import forge.net.game.LobbyState.LobbyPlayerData;
|
||||
import forge.net.game.server.RemoteClient;
|
||||
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.toolbox.FCheckBox;
|
||||
@@ -55,39 +56,34 @@ import forge.toolbox.FScrollPanel;
|
||||
import forge.toolbox.FSkin;
|
||||
import forge.toolbox.FSkin.SkinImage;
|
||||
import forge.toolbox.FTextField;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.Lang;
|
||||
import forge.util.NameGenerator;
|
||||
import forge.util.storage.IStorage;
|
||||
|
||||
/**
|
||||
* 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 implements ILobby {
|
||||
public class VLobby implements IUpdateable {
|
||||
|
||||
static final int MAX_PLAYERS = 8;
|
||||
private static final ForgePreferences prefs = FModel.getPreferences();
|
||||
|
||||
public enum LobbyType { LOCAL, SERVER, CLIENT; }
|
||||
|
||||
// General variables
|
||||
private final LobbyType type;
|
||||
private int localPlayer = 0;
|
||||
private final GameLobby lobby;
|
||||
private IPlayerChangeListener playerChangeListener = null;
|
||||
private final LblHeader lblTitle = new LblHeader("Sanctioned Format: Constructed");
|
||||
private int activePlayersNum = 2;
|
||||
private int activePlayersNum = 0;
|
||||
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);
|
||||
@@ -96,6 +92,8 @@ public class VLobby implements ILobby {
|
||||
private final VariantCheckBox vntPlanechase = new VariantCheckBox(GameType.Planechase);
|
||||
private final VariantCheckBox vntArchenemy = new VariantCheckBox(GameType.Archenemy);
|
||||
private final VariantCheckBox vntArchenemyRumble = new VariantCheckBox(GameType.ArchenemyRumble);
|
||||
private final ImmutableList<VariantCheckBox> vntBoxes =
|
||||
ImmutableList.of(vntVanguard, vntMomirBasic, vntCommander, vntTinyLeaders, vntPlanechase, vntArchenemy, vntArchenemyRumble);
|
||||
|
||||
// Player frame elements
|
||||
private final JPanel playersFrame = new JPanel(new MigLayout("insets 0, gap 0 5, wrap, hidemode 3"));
|
||||
@@ -109,6 +107,7 @@ public class VLobby implements ILobby {
|
||||
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");
|
||||
private final Deck[] decks = new Deck[MAX_PLAYERS];
|
||||
|
||||
// Variants
|
||||
private final List<FList<Object>> schemeDeckLists = new ArrayList<FList<Object>>();
|
||||
@@ -132,8 +131,8 @@ public class VLobby implements ILobby {
|
||||
private final Vector<Object> aiListData = new Vector<Object>();
|
||||
|
||||
// CTR
|
||||
public VLobby(final LobbyType type) {
|
||||
this.type = type;
|
||||
public VLobby(final GameLobby lobby) {
|
||||
this.lobby = lobby;
|
||||
|
||||
lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
|
||||
|
||||
@@ -142,55 +141,23 @@ public class VLobby implements ILobby {
|
||||
|
||||
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);
|
||||
for (final VariantCheckBox vcb : vntBoxes) {
|
||||
variantsPanel.add(vcb);
|
||||
}
|
||||
|
||||
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, type);
|
||||
if (type == LobbyType.CLIENT) {
|
||||
player.setRemote(true);
|
||||
}
|
||||
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");
|
||||
|
||||
if (type != LobbyType.CLIENT) {
|
||||
if (lobby.hasControl()) {
|
||||
addPlayerBtn.setFocusable(true);
|
||||
addPlayerBtn.setCommand(new Runnable() {
|
||||
@Override public final void run() {
|
||||
addPlayer();
|
||||
lobby.addSlot();
|
||||
}
|
||||
});
|
||||
playersFrame.add(addPlayerBtn, "height 30px!, growx, pushx");
|
||||
@@ -209,9 +176,16 @@ public class VLobby implements ILobby {
|
||||
decksFrame.setOpaque(false);
|
||||
|
||||
// Start Button
|
||||
if (type != LobbyType.CLIENT) {
|
||||
if (lobby.hasControl()) {
|
||||
pnlStart.setOpaque(false);
|
||||
pnlStart.add(btnStart, "align center");
|
||||
|
||||
// Start button event handling
|
||||
btnStart.addActionListener(new ActionListener() {
|
||||
@Override public final void actionPerformed(final ActionEvent arg0) {
|
||||
lobby.startGame();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,143 +201,95 @@ public class VLobby implements ILobby {
|
||||
}
|
||||
populateDeckPanel(GameType.Constructed);
|
||||
populateVanguardLists();
|
||||
|
||||
}
|
||||
|
||||
private int addPlayerInFreeSlot(final String name) {
|
||||
if (activePlayersNum >= MAX_PLAYERS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (final PlayerPanel pp : getPlayerPanels()) {
|
||||
if (pp.isVisible() && (
|
||||
pp.getType() == LobbySlotType.OPEN || (pp.isLocal() && type == LobbyType.SERVER))) {
|
||||
final int index = pp.getIndex();
|
||||
addPlayer(index);
|
||||
pp.setPlayerName(name);
|
||||
System.out.println("Put player " + name + " in slot " + index);
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
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++;
|
||||
public void update() {
|
||||
activePlayersNum = lobby.getNumberOfSlots();
|
||||
addPlayerBtn.setEnabled(activePlayersNum < MAX_PLAYERS);
|
||||
|
||||
playerPanels.get(slot).setVisible(true);
|
||||
playerPanels.get(slot).focusOnAvatar();
|
||||
|
||||
firePlayerChangeListener();
|
||||
}
|
||||
|
||||
void removePlayer(final int playerIndex) {
|
||||
if (activePlayersNum <= playerIndex) {
|
||||
return;
|
||||
for (final VariantCheckBox vcb : vntBoxes) {
|
||||
vcb.setSelected(hasVariant(vcb.variant));
|
||||
vcb.setEnabled(lobby.hasControl());
|
||||
}
|
||||
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;
|
||||
final boolean allowNetworking = lobby.isAllowNetworking();
|
||||
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||
final boolean hasPanel = i < playerPanels.size();
|
||||
if (i < activePlayersNum) {
|
||||
// visible panels
|
||||
final LobbySlot slot = lobby.getSlot(i);
|
||||
final PlayerPanel panel;
|
||||
if (hasPanel) {
|
||||
panel = playerPanels.get(i);
|
||||
panel.setVisible(true);
|
||||
} else {
|
||||
panel = new PlayerPanel(this, allowNetworking, i, slot, lobby.mayEdit(i), lobby.hasControl());
|
||||
playerPanels.add(panel);
|
||||
String constraints = "pushx, growx, wrap, hidemode 3";
|
||||
if (i == 0) {
|
||||
constraints += ", gaptop 5px";
|
||||
playerPanelWithFocus = panel;
|
||||
playerPanelWithFocus.setFocused(true);
|
||||
}
|
||||
playersScroll.add(panel, constraints);
|
||||
}
|
||||
|
||||
panel.setType(slot.getType());
|
||||
panel.setPlayerName(slot.getName());
|
||||
panel.setAvatar(slot.getAvatarIndex());
|
||||
panel.setTeam(slot.getTeam());
|
||||
panel.setIsArchenemy(slot.isArchenemy());
|
||||
panel.setUseAiSimulation(slot.getAiOptions().contains(AIOption.USE_SIMULATION));
|
||||
panel.setMayEdit(lobby.mayEdit(i));
|
||||
panel.setMayControl(lobby.mayControl(i));
|
||||
panel.setMayRemove(lobby.mayRemove(i));
|
||||
panel.update();
|
||||
|
||||
deckChoosers.get(i).setIsAi(slot.getType() == LobbySlotType.AI);
|
||||
} else if (hasPanel) {
|
||||
playerPanels.get(i).setVisible(false);
|
||||
}
|
||||
|
||||
changePlayerFocus(closest);
|
||||
playerPanels.get(closest).focusOnAvatar();
|
||||
}
|
||||
firePlayerChangeListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int login(final RemoteClient client) {
|
||||
return addPlayerInFreeSlot(client.getUsername());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void logout(final RemoteClient client) {
|
||||
removePlayer(client.getIndex());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LobbyState getState() {
|
||||
final LobbyState state = new LobbyState();
|
||||
for (int i = 0; i < activePlayersNum; i++) {
|
||||
state.addPlayer(getData(i));
|
||||
if (playerWithFocus >= activePlayersNum) {
|
||||
playerWithFocus = activePlayersNum - 1;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
public void setState(final LobbyState state) {
|
||||
setLocalPlayer(state.getLocalPlayer());
|
||||
|
||||
final List<LobbyPlayerData> players = state.getPlayers();
|
||||
final int pSize = players.size();
|
||||
activePlayersNum = pSize;
|
||||
for (int i = 0; i < pSize; i++) {
|
||||
final LobbyPlayerData player = players.get(i);
|
||||
final PlayerPanel panel = playerPanels.get(i);
|
||||
|
||||
if (type == LobbyType.CLIENT) {
|
||||
panel.setRemote(i != localPlayer);
|
||||
panel.setEditableForClient(i == localPlayer);
|
||||
} else {
|
||||
panel.setRemote(player.getType() == LobbySlotType.REMOTE);
|
||||
panel.setEditableForClient(false);
|
||||
}
|
||||
panel.setPlayerName(player.getName());
|
||||
panel.setAvatar(player.getAvatarIndex());
|
||||
panel.setVisible(true);
|
||||
panel.update();
|
||||
}
|
||||
}
|
||||
|
||||
private void setLocalPlayer(final int index) {
|
||||
localPlayer = index;
|
||||
changePlayerFocus(playerWithFocus);
|
||||
refreshPanels(true, true);
|
||||
}
|
||||
|
||||
public void setPlayerChangeListener(final IPlayerChangeListener listener) {
|
||||
this.playerChangeListener = listener;
|
||||
}
|
||||
|
||||
void firePlayerChangeListener() {
|
||||
void firePlayerChangeListener(final int index) {
|
||||
if (playerChangeListener != null) {
|
||||
playerChangeListener.update(getData(localPlayer));
|
||||
playerChangeListener.update(index, getSlot(index));
|
||||
}
|
||||
}
|
||||
void fireDeckChangeListener(final int index, final Deck deck) {
|
||||
decks[index] = deck;
|
||||
if (playerChangeListener != null) {
|
||||
playerChangeListener.update(index, UpdateLobbyPlayerEvent.deckUpdate(deck));
|
||||
}
|
||||
}
|
||||
void fireDeckSectionChangeListener(final int index, final DeckSection section, final CardPool cards) {
|
||||
decks[index].putSection(section, cards);
|
||||
if (playerChangeListener != null) {
|
||||
playerChangeListener.update(index, UpdateLobbyPlayerEvent.deckUpdate(section, cards));
|
||||
}
|
||||
}
|
||||
|
||||
private LobbyPlayerData getData(final int index) {
|
||||
void removePlayer(final int index) {
|
||||
lobby.removeSlot(index);
|
||||
}
|
||||
boolean hasVariant(final GameType variant) {
|
||||
return lobby.hasVariant(variant);
|
||||
}
|
||||
|
||||
private UpdateLobbyPlayerEvent getSlot(final int index) {
|
||||
final PlayerPanel panel = playerPanels.get(index);
|
||||
return new LobbyPlayerData(panel.getPlayerName(), panel.getAvatarIndex(), panel.getType());
|
||||
return UpdateLobbyPlayerEvent.create(panel.getType(), panel.getPlayerName(), panel.getAvatarIndex(), panel.getTeam(), panel.isArchenemy(), panel.getAiOptions());
|
||||
}
|
||||
|
||||
/** Builds the actual deck panel layouts for each player.
|
||||
@@ -374,53 +300,142 @@ public class VLobby implements ILobby {
|
||||
String labelConstraints = "gaptop 10px, gapbottom 5px";
|
||||
|
||||
// Main deck
|
||||
final FDeckChooser mainChooser = new FDeckChooser(null, isPlayerAI(playerIndex));
|
||||
final FDeckChooser mainChooser = new FDeckChooser(null, false);
|
||||
mainChooser.initialize();
|
||||
mainChooser.getLstDecks().setSelectCommand(new UiCommand() {
|
||||
@Override
|
||||
public void run() {
|
||||
@Override public final void run() {
|
||||
VLobby.this.onDeckClicked(playerIndex, mainChooser.getSelectedDeckType(), mainChooser.getLstDecks().getSelectedItems());
|
||||
}
|
||||
});
|
||||
deckChoosers.add(mainChooser);
|
||||
|
||||
// Scheme deck list
|
||||
FPanel schemeDeckPanel = new FPanel();
|
||||
final 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>();
|
||||
final FList<Object> schemeDeckList = new FList<Object>();
|
||||
schemeDeckList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||
schemeDeckList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override public final void valueChanged(final ListSelectionEvent e) {
|
||||
if (playerIndex >= activePlayersNum) {
|
||||
return;
|
||||
}
|
||||
|
||||
FScrollPane scrSchemes = new FScrollPane(schemeDeckList, true,
|
||||
final Object selected = schemeDeckList.getSelectedValue();
|
||||
final Deck deck = decks[playerIndex];
|
||||
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";
|
||||
}
|
||||
}
|
||||
final IStorage<Deck> sDecks = FModel.getDecks().getScheme();
|
||||
if (sel.equals("Random") && sDecks.size() != 0) {
|
||||
schemePool = Aggregates.random(sDecks).get(DeckSection.Schemes);
|
||||
}
|
||||
} else if (selected instanceof Deck) {
|
||||
schemePool = ((Deck) selected).get(DeckSection.Schemes);
|
||||
}
|
||||
if (schemePool == null) { //Can be null if player deselects the list selection or chose Generate
|
||||
schemePool = DeckgenUtil.generateSchemePool();
|
||||
}
|
||||
fireDeckSectionChangeListener(playerIndex, DeckSection.Schemes, schemePool);
|
||||
getDeckChooser(playerIndex).saveState();
|
||||
}
|
||||
});
|
||||
|
||||
final 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();
|
||||
final 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>();
|
||||
final FList<Object> commanderDeckList = new FList<Object>();
|
||||
commanderDeckList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||
commanderDeckList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override public final void valueChanged(final ListSelectionEvent e) {
|
||||
if (playerIndex >= activePlayersNum) {
|
||||
return;
|
||||
}
|
||||
|
||||
FScrollPane scrCommander = new FScrollPane(commanderDeckList, true,
|
||||
final Object selected = commanderDeckList.getSelectedValue();
|
||||
Deck deck = null;
|
||||
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 if (selected instanceof Deck) {
|
||||
deck = (Deck) selected;
|
||||
}
|
||||
final GameType commanderGameType = hasVariant(GameType.TinyLeaders) ? GameType.TinyLeaders : GameType.Commander;
|
||||
if (deck == null) { //Can be null if player deselects the list selection or chose Generate
|
||||
deck = DeckgenUtil.generateCommanderDeck(isPlayerAI(playerIndex), commanderGameType);
|
||||
}
|
||||
fireDeckChangeListener(playerIndex, deck);
|
||||
getDeckChooser(playerIndex).saveState();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
final 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();
|
||||
final 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>();
|
||||
final FList<Object> planarDeckList = new FList<Object>();
|
||||
planarDeckList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||
planarDeckList.addListSelectionListener(new ListSelectionListener() {
|
||||
@Override public final void valueChanged(final ListSelectionEvent e) {
|
||||
if (playerIndex >= activePlayersNum) {
|
||||
return;
|
||||
}
|
||||
|
||||
FScrollPane scrPlanes = new FScrollPane(planarDeckList, true,
|
||||
final Object selected = planarDeckList.getSelectedValue();
|
||||
final Deck deck = decks[playerIndex];
|
||||
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";
|
||||
}
|
||||
}
|
||||
final IStorage<Deck> pDecks = FModel.getDecks().getPlane();
|
||||
if (sel.equals("Random") && pDecks.size() != 0) {
|
||||
planePool = Aggregates.random(pDecks).get(DeckSection.Planes);
|
||||
}
|
||||
} else if (selected instanceof Deck) {
|
||||
planePool = ((Deck) selected).get(DeckSection.Planes);
|
||||
}
|
||||
if (planePool == null) { //Can be null if player deselects the list selection or chose Generate
|
||||
planePool = DeckgenUtil.generatePlanarPool();
|
||||
}
|
||||
fireDeckSectionChangeListener(playerIndex, DeckSection.Planes, planePool);
|
||||
getDeckChooser(playerIndex).saveState();
|
||||
}
|
||||
});
|
||||
|
||||
final FScrollPane scrPlanes = new FScrollPane(planarDeckList, true,
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
planarDeckPanel.add(scrPlanes, "grow, push");
|
||||
planarDeckLists.add(planarDeckList);
|
||||
@@ -430,15 +445,15 @@ public class VLobby implements ILobby {
|
||||
FPanel vgdDeckPanel = new FPanel();
|
||||
vgdDeckPanel.setBorderToggle(false);
|
||||
|
||||
FList<Object> vgdAvatarList = new FList<Object>();
|
||||
final 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,
|
||||
final FScrollPane scrAvatars = new FScrollPane(vgdAvatarList, true,
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
|
||||
CardDetailPanel vgdDetail = new CardDetailPanel();
|
||||
final CardDetailPanel vgdDetail = new CardDetailPanel();
|
||||
vgdAvatarDetails.add(vgdDetail);
|
||||
|
||||
vgdDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
||||
@@ -449,16 +464,19 @@ public class VLobby implements ILobby {
|
||||
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);
|
||||
protected void onDeckClicked(final int iPlayer, final DeckType type, final Collection<DeckProxy> selectedDecks) {
|
||||
if (iPlayer < activePlayersNum && lobby.mayEdit(iPlayer)) {
|
||||
final String text = type.toString() + ": " + Lang.joinHomogenous(selectedDecks, DeckProxy.FN_GET_NAME);
|
||||
playerPanels.get(iPlayer).setDeckSelectorButtonText(text);
|
||||
fireDeckChangeListener(iPlayer, selectedDecks.iterator().next().getDeck());
|
||||
}
|
||||
}
|
||||
|
||||
/** Populates the deck panel with the focused player's deck choices. */
|
||||
private void populateDeckPanel(final GameType forGameType) {
|
||||
decksFrame.removeAll();
|
||||
|
||||
if (playerPanelWithFocus.getType() == LobbySlotType.OPEN || playerPanelWithFocus.getType() == LobbySlotType.REMOTE) {
|
||||
if (!lobby.mayEdit(playerWithFocus)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -487,7 +505,7 @@ public class VLobby implements ILobby {
|
||||
}
|
||||
|
||||
/** @return {@link javax.swing.JButton} */
|
||||
public JButton getBtnStart() {
|
||||
JButton getBtnStart() {
|
||||
return this.btnStart;
|
||||
}
|
||||
|
||||
@@ -497,18 +515,18 @@ public class VLobby implements ILobby {
|
||||
public List<FDeckChooser> getDeckChoosers() { return Collections.unmodifiableList(deckChoosers); }
|
||||
|
||||
/** Gets the random deck checkbox for Singletons. */
|
||||
public FCheckBox getCbSingletons() { return cbSingletons; }
|
||||
FCheckBox getCbSingletons() { return cbSingletons; }
|
||||
|
||||
/** Gets the random deck checkbox for Artifacts. */
|
||||
public FCheckBox getCbArtifacts() { return cbArtifacts; }
|
||||
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; }
|
||||
FCheckBox getVntArchenemy() { return vntArchenemy; }
|
||||
FCheckBox getVntArchenemyRumble() { return vntArchenemyRumble; }
|
||||
FCheckBox getVntCommander() { return vntCommander; }
|
||||
FCheckBox getVntMomirBasic() { return vntMomirBasic; }
|
||||
FCheckBox getVntPlanechase() { return vntPlanechase; }
|
||||
FCheckBox getVntTinyLeaders() { return vntTinyLeaders; }
|
||||
FCheckBox getVntVanguard() { return vntVanguard; }
|
||||
|
||||
public int getLastArchenemy() { return lastArchenemy; }
|
||||
public void setLastArchenemy(final int archenemy) { lastArchenemy = archenemy; }
|
||||
@@ -524,38 +542,22 @@ public class VLobby implements ILobby {
|
||||
return deckChoosers.get(playernum);
|
||||
}
|
||||
|
||||
public List<Integer> getTeams() { return teams; }
|
||||
public List<Integer> getArchenemyTeams() { return archenemyTeams; }
|
||||
public GameType getCurrentGameMode() { return currentGameMode; }
|
||||
public void setCurrentGameMode(final GameType mode) { currentGameMode = mode; }
|
||||
|
||||
public boolean isPlayerAI(int playernum) {
|
||||
return playerPanels.get(playernum).isAi();
|
||||
GameType getCurrentGameMode() {
|
||||
return lobby.getGameType();
|
||||
}
|
||||
void setCurrentGameMode(final GameType mode) {
|
||||
lobby.setGameType(mode);
|
||||
update();
|
||||
}
|
||||
|
||||
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 boolean isPlayerAI(final int playernum) {
|
||||
return playernum < activePlayersNum ? playerPanels.get(playernum).isAi() : false;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -569,7 +571,7 @@ public class VLobby implements ILobby {
|
||||
}
|
||||
|
||||
public void changePlayerFocus(int newFocusOwner) {
|
||||
changePlayerFocus(newFocusOwner, appliedVariants.contains(currentGameMode) ? currentGameMode : GameType.Constructed);
|
||||
changePlayerFocus(newFocusOwner, lobby.getGameType());
|
||||
}
|
||||
|
||||
void changePlayerFocus(int newFocusOwner, GameType gType) {
|
||||
@@ -593,32 +595,15 @@ public class VLobby implements ILobby {
|
||||
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());
|
||||
final List<Integer> usedAvatars = Lists.newArrayListWithCapacity(MAX_PLAYERS);
|
||||
for (final PlayerPanel pp : playerPanels) {
|
||||
usedAvatars.add(pp.getAvatarIndex());
|
||||
}
|
||||
return usedAvatars;
|
||||
}
|
||||
@@ -660,92 +645,30 @@ public class VLobby implements ILobby {
|
||||
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;
|
||||
private final GameType variant;
|
||||
private VariantCheckBox(final GameType variantType) {
|
||||
super(variantType.toString());
|
||||
this.variant = variantType;
|
||||
|
||||
setToolTipText(variantType.getDescription());
|
||||
|
||||
addItemListener(new ItemListener() {
|
||||
@Override
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
@Override public final void itemStateChanged(final 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;
|
||||
}
|
||||
lobby.applyVariant(variantType);
|
||||
} else {
|
||||
lobby.removeVariant(variantType);
|
||||
}
|
||||
else {
|
||||
appliedVariants.remove(variantType);
|
||||
if (currentGameMode == variantType) {
|
||||
currentGameMode = GameType.Constructed;
|
||||
}
|
||||
}
|
||||
|
||||
for (PlayerPanel pp : playerPanels) {
|
||||
pp.toggleIsPlayerArchenemy();
|
||||
}
|
||||
changePlayerFocus(playerWithFocus, currentGameMode);
|
||||
VLobby.this.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
ActionListener nameListener = new ActionListener() {
|
||||
final ActionListener nameListener = new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
FTextField nField = (FTextField)e.getSource();
|
||||
@@ -756,24 +679,44 @@ public class VLobby implements ILobby {
|
||||
/** 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 final void valueChanged(final ListSelectionEvent e) {
|
||||
final int index = vgdAvatarLists.indexOf(e.getSource());
|
||||
if (index >= activePlayersNum) {
|
||||
return;
|
||||
}
|
||||
final Object selected = vgdAvatarLists.get(index).getSelectedValue();
|
||||
final PlayerPanel pp = playerPanels.get(index);
|
||||
final CardDetailPanel cdp = vgdAvatarDetails.get(index);
|
||||
|
||||
@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));
|
||||
final PaperCard vanguardAvatar;
|
||||
final Deck deck = decks[index];
|
||||
if (selected instanceof PaperCard) {
|
||||
pp.setVanguardButtonText(((PaperCard) selected).getName());
|
||||
cdp.setCard(CardView.getCardForUi((PaperCard) selected));
|
||||
cdp.setVisible(true);
|
||||
refreshPanels(false, true);
|
||||
}
|
||||
else {
|
||||
pp.setVanguardButtonText((String) obj);
|
||||
|
||||
vanguardAvatar = (PaperCard)selected;
|
||||
} else {
|
||||
String sel = (String) selected;
|
||||
pp.setVanguardButtonText(sel);
|
||||
cdp.setVisible(false);
|
||||
|
||||
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 (playerPanels.get(index).isAi()) { //AI
|
||||
vanguardAvatar = Aggregates.random(getNonRandomAiAvatars());
|
||||
} else { //Human
|
||||
vanguardAvatar = Aggregates.random(getNonRandomHumanAvatars());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final CardPool avatarOnce = new CardPool();
|
||||
avatarOnce.add(vanguardAvatar);
|
||||
fireDeckSectionChangeListener(index, DeckSection.Avatar, avatarOnce);
|
||||
getDeckChooser(index).saveState();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -781,14 +724,6 @@ public class VLobby implements ILobby {
|
||||
/////////////////////////////////////
|
||||
//========== 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;
|
||||
|
||||
@@ -8,74 +8,102 @@ 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.interfaces.IGuiGame;
|
||||
import forge.interfaces.ILobbyListener;
|
||||
import forge.interfaces.IPlayerChangeListener;
|
||||
import forge.interfaces.IUpdateable;
|
||||
import forge.match.GameLobby.GameLobbyData;
|
||||
import forge.menus.IMenuProvider;
|
||||
import forge.menus.MenuUtil;
|
||||
import forge.model.FModel;
|
||||
import forge.net.ClientGameLobby;
|
||||
import forge.net.FGameClient;
|
||||
import forge.net.FServerManager;
|
||||
import forge.net.game.LobbyState;
|
||||
import forge.net.game.LobbyState.LobbyPlayerData;
|
||||
import forge.net.game.LoginEvent;
|
||||
import forge.net.game.client.ILobbyListener;
|
||||
import forge.net.ServerGameLobby;
|
||||
import forge.net.game.IRemote;
|
||||
import forge.net.game.IdentifiableNetEvent;
|
||||
import forge.net.game.MessageEvent;
|
||||
import forge.net.game.NetEvent;
|
||||
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.screens.home.VLobby;
|
||||
import forge.screens.home.VLobby.LobbyType;
|
||||
import forge.screens.home.sanctioned.ConstructedGameMenu;
|
||||
|
||||
public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
||||
SINGLETON_INSTANCE;
|
||||
|
||||
final void host(final int portNumber) {
|
||||
final VLobby lobby = VOnlineLobby.SINGLETON_INSTANCE.setLobby(LobbyType.SERVER);
|
||||
final FServerManager server = FServerManager.getInstance();
|
||||
final ServerGameLobby lobby = new ServerGameLobby();
|
||||
final VLobby view = VOnlineLobby.SINGLETON_INSTANCE.setLobby(lobby);
|
||||
|
||||
FServerManager.getInstance().startServer(portNumber);
|
||||
FServerManager.getInstance().setLobby(lobby);
|
||||
FServerManager.getInstance().hostGame(new GameRules(GameType.Constructed));
|
||||
server.startServer(portNumber);
|
||||
server.setLobby(lobby);
|
||||
|
||||
FNetOverlay.SINGLETON_INSTANCE.showUp("Hosting game");
|
||||
lobby.setPlayerChangeListener(new IPlayerChangeListener() {
|
||||
@Override public final void update(final LobbyPlayerData data) {
|
||||
FServerManager.getInstance().updateLobbyState();
|
||||
lobby.setListener(new IUpdateable() {
|
||||
@Override public final void update() {
|
||||
view.update();
|
||||
server.updateLobbyState();
|
||||
}
|
||||
});
|
||||
view.setPlayerChangeListener(new IPlayerChangeListener() {
|
||||
@Override public final void update(final int index, final UpdateLobbyPlayerEvent event) {
|
||||
server.updateSlot(index, event);
|
||||
server.updateLobbyState();
|
||||
}
|
||||
});
|
||||
|
||||
final FGameClient client = new FGameClient(FModel.getPreferences().getPref(FPref.PLAYER_NAME), "0", GuiBase.getInterface().getNewGuiGame());
|
||||
FNetOverlay.SINGLETON_INSTANCE.setGameClient(client);
|
||||
client.addLobbyListener(new ILobbyListener() {
|
||||
@Override public final void update(final LobbyState state) {
|
||||
lobby.setState(state);
|
||||
server.setLobbyListener(new ILobbyListener() {
|
||||
@Override public final void update(final GameLobbyData state, final int slot) {
|
||||
// NO-OP, lobby connected directly
|
||||
}
|
||||
@Override public final void message(final String source, final String message) {
|
||||
FNetOverlay.SINGLETON_INSTANCE.addMessage(source, message);
|
||||
}
|
||||
});
|
||||
client.connect("localhost", portNumber);
|
||||
FNetOverlay.SINGLETON_INSTANCE.setGameClient(new IRemote() {
|
||||
@Override public final void send(final NetEvent event) {
|
||||
if (event instanceof MessageEvent) {
|
||||
final MessageEvent message = (MessageEvent) event;
|
||||
FNetOverlay.SINGLETON_INSTANCE.addMessage(message.getSource(), message.getMessage());
|
||||
server.broadcast(event);
|
||||
}
|
||||
}
|
||||
@Override public final Object sendAndWait(final IdentifiableNetEvent event) {
|
||||
send(event);
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
view.update();
|
||||
|
||||
Singletons.getControl().setCurrentScreen(FScreen.ONLINE_LOBBY);
|
||||
FNetOverlay.SINGLETON_INSTANCE.showUp(String.format("Hosting on port %d", portNumber));
|
||||
}
|
||||
|
||||
final void join(final String hostname, final int port) {
|
||||
final FGameClient client = new FGameClient(FModel.getPreferences().getPref(FPref.PLAYER_NAME), "0", GuiBase.getInterface().getNewGuiGame());
|
||||
final IGuiGame gui = GuiBase.getInterface().getNewGuiGame();
|
||||
final FGameClient client = new FGameClient(FModel.getPreferences().getPref(FPref.PLAYER_NAME), "0", gui);
|
||||
FNetOverlay.SINGLETON_INSTANCE.setGameClient(client);
|
||||
final VLobby lobby = VOnlineLobby.SINGLETON_INSTANCE.setLobby(LobbyType.CLIENT);
|
||||
final ClientGameLobby lobby = new ClientGameLobby();
|
||||
final VLobby view = VOnlineLobby.SINGLETON_INSTANCE.setLobby(lobby);
|
||||
lobby.setListener(view);
|
||||
client.addLobbyListener(new ILobbyListener() {
|
||||
@Override public final void update(final LobbyState state) {
|
||||
lobby.setState(state);
|
||||
}
|
||||
@Override public final void message(final String source, final String message) {
|
||||
FNetOverlay.SINGLETON_INSTANCE.addMessage(source, message);
|
||||
}
|
||||
@Override public final void update(final GameLobbyData state, final int slot) {
|
||||
lobby.setLocalPlayer(slot);
|
||||
lobby.setData(state);
|
||||
}
|
||||
});
|
||||
lobby.setPlayerChangeListener(new IPlayerChangeListener() {
|
||||
@Override public final void update(final LobbyPlayerData data) {
|
||||
client.send(new LoginEvent(data.getName()));
|
||||
view.setPlayerChangeListener(new IPlayerChangeListener() {
|
||||
@Override public final void update(final int index, final UpdateLobbyPlayerEvent event) {
|
||||
client.send(event);
|
||||
}
|
||||
});
|
||||
client.connect(hostname, port);
|
||||
|
||||
@@ -12,8 +12,8 @@ import forge.gui.framework.EDocID;
|
||||
import forge.gui.framework.FScreen;
|
||||
import forge.gui.framework.IVDoc;
|
||||
import forge.gui.framework.IVTopLevelUI;
|
||||
import forge.match.GameLobby;
|
||||
import forge.screens.home.VLobby;
|
||||
import forge.screens.home.VLobby.LobbyType;
|
||||
import forge.toolbox.FPanel;
|
||||
import forge.util.gui.SOptionPane;
|
||||
import forge.view.FView;
|
||||
@@ -33,9 +33,9 @@ public enum VOnlineLobby implements IVDoc<COnlineLobby>, IVTopLevelUI {
|
||||
VLobby getLobby() {
|
||||
return lobby;
|
||||
}
|
||||
VLobby setLobby(final LobbyType type) {
|
||||
this.lobby = new VLobby(type);
|
||||
getLayoutControl().setLobby(lobby);
|
||||
VLobby setLobby(final GameLobby lobby) {
|
||||
this.lobby = new VLobby(lobby);
|
||||
getLayoutControl().setLobby(this.lobby);
|
||||
return this.lobby;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,9 @@ public enum VOnlineLobby implements IVDoc<COnlineLobby>, IVTopLevelUI {
|
||||
container.repaint();
|
||||
}
|
||||
|
||||
lobby.changePlayerFocus(0);
|
||||
if (!lobby.getPlayerPanels().isEmpty()) {
|
||||
lobby.changePlayerFocus(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,11 +9,14 @@ import forge.deckchooser.IDecksComboBoxListener;
|
||||
import forge.gui.framework.DragCell;
|
||||
import forge.gui.framework.DragTab;
|
||||
import forge.gui.framework.EDocID;
|
||||
import forge.interfaces.IPlayerChangeListener;
|
||||
import forge.match.GameLobby;
|
||||
import forge.match.LocalLobby;
|
||||
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||
import forge.screens.home.EMenuGroup;
|
||||
import forge.screens.home.IVSubmenu;
|
||||
import forge.screens.home.VLobby;
|
||||
import forge.screens.home.VHomeUI;
|
||||
import forge.screens.home.VLobby.LobbyType;
|
||||
import forge.screens.home.VLobby;
|
||||
|
||||
/**
|
||||
* Assembles Swing components of constructed submenu singleton.
|
||||
@@ -28,12 +31,22 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
||||
private DragCell parentCell;
|
||||
private final DragTab tab = new DragTab("Constructed Mode");
|
||||
|
||||
private final VLobby lobby = new VLobby(LobbyType.LOCAL);
|
||||
private final GameLobby lobby = new LocalLobby();
|
||||
private final VLobby vLobby = new VLobby(lobby);
|
||||
private VSubmenuConstructed() {
|
||||
lobby.setListener(vLobby);
|
||||
|
||||
vLobby.setPlayerChangeListener(new IPlayerChangeListener() {
|
||||
@Override public final void update(final int index, final UpdateLobbyPlayerEvent event) {
|
||||
lobby.applyToSlot(index, event);
|
||||
}
|
||||
});
|
||||
|
||||
vLobby.update();
|
||||
}
|
||||
|
||||
public VLobby getLobby() {
|
||||
return lobby;
|
||||
return vLobby;
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
@@ -112,25 +125,27 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
||||
|
||||
container.removeAll();
|
||||
container.setLayout(new MigLayout("insets 0, gap 0, wrap 1, ax right"));
|
||||
container.add(lobby.getLblTitle(), "w 80%, h 40px!, gap 0 0 15px 15px, span 2, al right, pushx");
|
||||
container.add(vLobby.getLblTitle(), "w 80%, h 40px!, gap 0 0 15px 15px, span 2, al right, pushx");
|
||||
|
||||
for (final FDeckChooser fdc : lobby.getDeckChoosers()) {
|
||||
for (final FDeckChooser fdc : vLobby.getDeckChoosers()) {
|
||||
fdc.populate();
|
||||
fdc.getDecksComboBox().addListener(new IDecksComboBoxListener() {
|
||||
@Override public final void deckTypeSelected(final DecksComboBoxEvent ev) {
|
||||
lobby.getPlayerPanelWithFocus().focusOnAvatar();
|
||||
vLobby.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");
|
||||
container.add(vLobby.getConstructedFrame(), "gap 20px 20px 20px 0px, push, grow");
|
||||
container.add(vLobby.getPanelStart(), "gap 0 0 3.5%! 3.5%!, ax center");
|
||||
|
||||
if (container.isShowing()) {
|
||||
container.validate();
|
||||
container.repaint();
|
||||
}
|
||||
|
||||
lobby.changePlayerFocus(0);
|
||||
if (!vLobby.getPlayerPanels().isEmpty()) {
|
||||
vLobby.changePlayerFocus(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,6 @@ import forge.control.KeyboardShortcuts;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deckchooser.FDeckViewer;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameEntityView;
|
||||
import forge.game.GameView;
|
||||
import forge.game.card.CardView;
|
||||
@@ -61,9 +60,8 @@ import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.IHasIcon;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityView;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.FNetOverlay;
|
||||
import forge.gui.GuiChoose;
|
||||
import forge.gui.GuiDialog;
|
||||
import forge.gui.GuiUtils;
|
||||
@@ -78,9 +76,9 @@ import forge.interfaces.IButton;
|
||||
import forge.item.InventoryItem;
|
||||
import forge.item.PaperCard;
|
||||
import forge.match.AbstractGuiGame;
|
||||
import forge.match.MatchButtonType;
|
||||
import forge.menus.IMenuProvider;
|
||||
import forge.model.FModel;
|
||||
import forge.player.PlayerControllerHuman;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.screens.match.controllers.CAntes;
|
||||
@@ -103,6 +101,7 @@ import forge.toolbox.FSkin.SkinImage;
|
||||
import forge.toolbox.MouseTriggerEvent;
|
||||
import forge.toolbox.special.PhaseIndicator;
|
||||
import forge.toolbox.special.PhaseLabel;
|
||||
import forge.trackable.TrackableCollection;
|
||||
import forge.util.FCollectionView;
|
||||
import forge.util.ITriggerEvent;
|
||||
import forge.util.gui.SOptionPane;
|
||||
@@ -183,6 +182,21 @@ public final class CMatchUI
|
||||
public void setGameView(final GameView gameView) {
|
||||
super.setGameView(gameView);
|
||||
screen.setTabCaption(gameView.getTitle());
|
||||
if (sortedPlayers != null) {
|
||||
for (final PlayerView pv : sortedPlayers) {
|
||||
pv.copy(gameView.getPlayers());
|
||||
}
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
for (final VField f : getFieldViews()) {
|
||||
f.getTabletop().setupPlayZone();
|
||||
}
|
||||
for (final VHand h : getHandViews()) {
|
||||
h.getLayoutControl().updateHand();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -248,7 +262,7 @@ public final class CMatchUI
|
||||
view.getLblAvatar().getResizeTimer().start();
|
||||
}
|
||||
|
||||
public 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.setLocalPlayers(myPlayers);
|
||||
allHands = sortedPlayers.size() == getLocalPlayerCount();
|
||||
@@ -356,7 +370,7 @@ public final class CMatchUI
|
||||
@Override
|
||||
public final boolean stopAtPhase(final PlayerView turn, final PhaseType phase) {
|
||||
final VField vf = getFieldViewFor(turn);
|
||||
final PhaseLabel label = vf.getPhaseIndicator() .getLabelFor(phase);
|
||||
final PhaseLabel label = vf.getPhaseIndicator().getLabelFor(phase);
|
||||
return label == null || label.getEnabled();
|
||||
}
|
||||
|
||||
@@ -541,12 +555,6 @@ public final class CMatchUI
|
||||
return panels;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resetForNewGame() {
|
||||
FloatingCardArea.closeAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IButton getBtnOK(final PlayerView playerView) {
|
||||
return view.getBtnOK();
|
||||
@@ -558,13 +566,15 @@ public final class CMatchUI
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusButton(final IButton button) {
|
||||
public void focusButton(final MatchButtonType button) {
|
||||
// ensure we don't steal focus from an overlay
|
||||
if (!SOverlayUtils.overlayHasFocus()) {
|
||||
FThreads.invokeInEdtLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
((FButton)button).requestFocusInWindow();
|
||||
@Override public final void run() {
|
||||
final FButton btn = button == MatchButtonType.OK
|
||||
? getCPrompt().getView().getBtnOK()
|
||||
: getCPrompt().getView().getBtnCancel();
|
||||
btn.requestFocusInWindow();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -579,7 +589,7 @@ public final class CMatchUI
|
||||
public void updatePhase() {
|
||||
final PlayerView p = getGameView().getPlayerTurn();
|
||||
final PhaseType ph = getGameView().getPhase();
|
||||
PhaseLabel lbl = getFieldViewFor(p).getPhaseIndicator().getLabelFor(ph);
|
||||
final PhaseLabel lbl = p == null ? null : getFieldViewFor(p).getPhaseIndicator().getLabelFor(ph);
|
||||
|
||||
resetAllPhaseButtons();
|
||||
if (lbl != null) {
|
||||
@@ -629,7 +639,11 @@ public final class CMatchUI
|
||||
|
||||
@Override
|
||||
public void updateStack() {
|
||||
getCStack().update();
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
getCStack().update();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -664,7 +678,7 @@ public final class CMatchUI
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpellAbility getAbilityToPlay(List<SpellAbility> abilities, ITriggerEvent triggerEvent) {
|
||||
public SpellAbilityView getAbilityToPlay(final List<SpellAbilityView> abilities, final ITriggerEvent triggerEvent) {
|
||||
if (triggerEvent == null) {
|
||||
if (abilities.isEmpty()) {
|
||||
return null;
|
||||
@@ -691,7 +705,7 @@ public final class CMatchUI
|
||||
boolean enabled;
|
||||
boolean hasEnabled = false;
|
||||
int shortcut = KeyEvent.VK_1; //use number keys as shortcuts for abilities 1-9
|
||||
for (final SpellAbility ab : abilities) {
|
||||
for (final SpellAbilityView ab : abilities) {
|
||||
enabled = ab.canPlay();
|
||||
if (enabled) {
|
||||
hasEnabled = true;
|
||||
@@ -763,12 +777,7 @@ public final class CMatchUI
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hear(LobbyPlayer player, String message) {
|
||||
FNetOverlay.SINGLETON_INSTANCE.addMessage(player.getName(), message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openView(final Iterable<PlayerView> myPlayers) {
|
||||
public void openView(final TrackableCollection<PlayerView> myPlayers) {
|
||||
final GameView gameView = getGameView();
|
||||
gameView.getGameLog().addObserver(getCLog());
|
||||
|
||||
@@ -841,16 +850,14 @@ public final class CMatchUI
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameEntityView chooseSingleEntityForEffect(final String title, final FCollectionView<? extends GameEntity> optionList, final DelayedReveal delayedReveal, final boolean isOptional, final PlayerControllerHuman controller) {
|
||||
public GameEntityView chooseSingleEntityForEffect(final String title, final Collection<? extends GameEntityView> optionList, final DelayedReveal delayedReveal, final boolean isOptional) {
|
||||
if (delayedReveal != null) {
|
||||
delayedReveal.reveal(controller); //TODO: Merge this into search dialog
|
||||
reveal(delayedReveal.getMessagePrefix(), delayedReveal.getCards()); //TODO: Merge this into search dialog
|
||||
}
|
||||
controller.tempShow(optionList);
|
||||
final List<GameEntityView> gameEntityViews = GameEntityView.getEntityCollection(optionList);
|
||||
if (isOptional) {
|
||||
return oneOrNone(title, gameEntityViews);
|
||||
return oneOrNone(title, optionList);
|
||||
}
|
||||
return one(title, gameEntityViews);
|
||||
return one(title, optionList);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.screens.match;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
@@ -91,21 +92,49 @@ public class VMatchUI implements IVTopLevelUI {
|
||||
}
|
||||
}
|
||||
|
||||
// Add extra hands to existing hand panel.
|
||||
for (int i = 1; i < lstHands.size(); i++) {
|
||||
// If already in layout, no need to add again.
|
||||
if (lstHands.get(i).getParentCell() == null) { // if i == 0, we get NPE in two lines
|
||||
DragCell cellWithHand = lstHands.get(0).getParentCell();
|
||||
cellWithHand.addDoc(lstHands.get(i));
|
||||
// Determine (an) existing hand panel
|
||||
DragCell cellWithHands = null;
|
||||
for (final EDocID handId : EDocID.Hands) {
|
||||
cellWithHands = handId.getDoc().getParentCell();
|
||||
if (cellWithHands != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cellWithHands == null) {
|
||||
// Default to a cell we know exists
|
||||
cellWithHands = EDocID.REPORT_LOG.getDoc().getParentCell();
|
||||
}
|
||||
for (final EDocID handId : EDocID.Hands) {
|
||||
final DragCell parentCell = handId.getDoc().getParentCell();
|
||||
VHand myVHand = null;
|
||||
for (final VHand vHand : lstHands) {
|
||||
if (handId.equals(vHand.getDocumentID())) {
|
||||
myVHand = vHand;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Remove any hand panels that aren't needed anymore
|
||||
for (int i = EDocID.Hands.length - 1; i >= lstHands.size(); i--) {
|
||||
DragCell cellWithHand = EDocID.Hands[i].getDoc().getParentCell();
|
||||
if (cellWithHand != null) {
|
||||
cellWithHand.removeDoc(EDocID.Hands[i].getDoc());
|
||||
EDocID.Hands[i].setDoc(new VEmptyDoc(EDocID.Hands[i]));
|
||||
if (myVHand == null) {
|
||||
// Hand not present, remove cell if necessary
|
||||
if (parentCell != null) {
|
||||
parentCell.removeDoc(handId.getDoc());
|
||||
handId.setDoc(new VEmptyDoc(handId));
|
||||
}
|
||||
} else {
|
||||
// Hand present, add it if necessary
|
||||
if (parentCell == null) {
|
||||
final EDocID fieldDoc = EDocID.Fields[Arrays.asList(EDocID.Hands).indexOf(handId)];
|
||||
if (fieldDoc.getDoc().getParentCell() != null) {
|
||||
fieldDoc.getDoc().getParentCell().addDoc(myVHand);
|
||||
continue;
|
||||
}
|
||||
final EDocID commandDoc = EDocID.Commands[Arrays.asList(EDocID.Hands).indexOf(handId)];
|
||||
if (commandDoc.getDoc().getParentCell() != null) {
|
||||
commandDoc.getDoc().getParentCell().addDoc(myVHand);
|
||||
continue;
|
||||
}
|
||||
cellWithHands.addDoc(myVHand);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ package forge.screens.match.controllers;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.google.common.collect.Iterators;
|
||||
import com.google.common.primitives.Ints;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.UiCommand;
|
||||
@@ -130,7 +131,8 @@ public class CDock implements ICDoc {
|
||||
public void initialize() {
|
||||
final String temp = FModel.getPreferences()
|
||||
.getPref(FPref.UI_TARGETING_OVERLAY);
|
||||
setArcState(ArcState.values()[Integer.valueOf(temp)]);
|
||||
final Integer arcState = Ints.tryParse(temp);
|
||||
setArcState(ArcState.values()[arcState == null ? 0 : arcState.intValue()]);
|
||||
refreshArcStateDisplay();
|
||||
|
||||
view.getBtnConcede().setCommand(new UiCommand() {
|
||||
|
||||
@@ -32,7 +32,7 @@ import forge.UiCommand;
|
||||
import forge.game.GameView;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityView;
|
||||
import forge.gui.framework.ICDoc;
|
||||
import forge.gui.framework.SDisplayUtil;
|
||||
import forge.screens.match.CMatchUI;
|
||||
@@ -120,7 +120,7 @@ public class CPrompt implements ICDoc {
|
||||
return matchUI.getGameController().selectCard(cardView, otherCardViewsToSelect, triggerEvent);
|
||||
}
|
||||
|
||||
public void selectAbility(final SpellAbility sa) {
|
||||
public void selectAbility(final SpellAbilityView sa) {
|
||||
matchUI.getGameController().selectAbility(sa);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
package forge.toolbox;
|
||||
|
||||
import forge.interfaces.IComboBox;
|
||||
import forge.toolbox.FComboBox.TextAlignment;
|
||||
import forge.toolbox.FSkin.SkinFont;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Container;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.ComboBoxModel;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.ListCellRenderer;
|
||||
|
||||
import com.google.common.collect.ObjectArrays;
|
||||
|
||||
import forge.interfaces.IComboBox;
|
||||
import forge.toolbox.FComboBox.TextAlignment;
|
||||
import forge.toolbox.FSkin.SkinFont;
|
||||
|
||||
/**
|
||||
* Wrapper for combo box with extra logic (either FComboBoxWrapper or FComboBoxPanel should be used instead of FComboBox so skinning works)
|
||||
*
|
||||
@@ -28,6 +32,7 @@ public class FComboBoxWrapper<E> implements IComboBox<E> {
|
||||
}
|
||||
|
||||
private FComboBox<E> comboBox;
|
||||
private ActionListener[] suppressedActionListeners = null;
|
||||
private Object constraints;
|
||||
|
||||
public FComboBoxWrapper() {
|
||||
@@ -111,6 +116,24 @@ public class FComboBoxWrapper<E> implements IComboBox<E> {
|
||||
comboBox.addItemListener(l);
|
||||
}
|
||||
|
||||
public void suppressActionListeners() {
|
||||
final ActionListener[] listeners = comboBox.getActionListeners();
|
||||
for (final ActionListener al : listeners) {
|
||||
comboBox.removeActionListener(al);
|
||||
}
|
||||
suppressedActionListeners = suppressedActionListeners == null
|
||||
? listeners
|
||||
: ObjectArrays.concat(suppressedActionListeners, listeners, ActionListener.class);
|
||||
}
|
||||
public void unsuppressActionListeners() {
|
||||
if (suppressedActionListeners != null) {
|
||||
for (final ActionListener al : suppressedActionListeners) {
|
||||
comboBox.addActionListener(al);
|
||||
}
|
||||
suppressedActionListeners = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void addKeyListener(KeyListener l) {
|
||||
comboBox.addKeyListener(l);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package forge.toolbox;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.Serializable;
|
||||
|
||||
import forge.util.ITriggerEvent;
|
||||
|
||||
//MouseEvent wrapper used for passing trigger to input classes
|
||||
public class MouseTriggerEvent implements ITriggerEvent {
|
||||
public class MouseTriggerEvent implements ITriggerEvent, Serializable {
|
||||
private static final long serialVersionUID = -4746127117012991732L;
|
||||
|
||||
private final MouseEvent event;
|
||||
|
||||
public MouseTriggerEvent(MouseEvent event0) {
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
package forge.gamesimulationtests.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.collect.ArrayListMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
@@ -27,6 +35,7 @@ import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardShields;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.combat.CombatUtil;
|
||||
@@ -39,8 +48,13 @@ import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.player.PlayerController;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.replacement.ReplacementEffect;
|
||||
import forge.game.spellability.*;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.Spell;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.spellability.TargetChoices;
|
||||
import forge.game.trigger.Trigger;
|
||||
import forge.game.trigger.WrappedAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -48,18 +62,17 @@ import forge.gamesimulationtests.util.card.CardSpecification;
|
||||
import forge.gamesimulationtests.util.card.CardSpecificationHandler;
|
||||
import forge.gamesimulationtests.util.player.PlayerSpecification;
|
||||
import forge.gamesimulationtests.util.player.PlayerSpecificationHandler;
|
||||
import forge.gamesimulationtests.util.playeractions.*;
|
||||
import forge.player.HumanPlay;
|
||||
import forge.gamesimulationtests.util.playeractions.ActivateAbilityAction;
|
||||
import forge.gamesimulationtests.util.playeractions.CastSpellFromHandAction;
|
||||
import forge.gamesimulationtests.util.playeractions.DeclareAttackersAction;
|
||||
import forge.gamesimulationtests.util.playeractions.DeclareBlockersAction;
|
||||
import forge.gamesimulationtests.util.playeractions.PlayerActions;
|
||||
import forge.item.PaperCard;
|
||||
import forge.player.HumanPlay;
|
||||
import forge.util.FCollectionView;
|
||||
import forge.util.ITriggerEvent;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Default harmless implementation for tests.
|
||||
* Test-specific behaviour can easily be added by mocking (parts of) this class.
|
||||
@@ -166,7 +179,7 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
@Override
|
||||
public <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, DelayedReveal delayedReveal, SpellAbility sa, String title, boolean isOptional, Player targetedPlayer) {
|
||||
if (delayedReveal != null) {
|
||||
delayedReveal.reveal(this);
|
||||
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||
}
|
||||
return chooseItem(optionList);
|
||||
}
|
||||
@@ -224,6 +237,11 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
//nothing needs to be done here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reveal(Collection<CardView> cards, ZoneType zone, PlayerView owner, String messagePrefix) {
|
||||
//nothing needs to be done here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyOfValue(SpellAbility saSource, GameObject realtedTarget, String value) {
|
||||
//nothing needs to be done here
|
||||
@@ -628,7 +646,7 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
String selectPrompt, boolean isOptional, Player decider) {
|
||||
|
||||
if (delayedReveal != null) {
|
||||
delayedReveal.reveal(this);
|
||||
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||
}
|
||||
return ChangeZoneAi.chooseCardToHiddenOriginChangeZone(destination, origin, sa, fetchList, player, decider);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user