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:
23
.gitattributes
vendored
23
.gitattributes
vendored
@@ -164,6 +164,7 @@ forge-core/.settings/org.eclipse.jdt.core.prefs -text
|
|||||||
forge-core/.settings/org.eclipse.m2e.core.prefs -text
|
forge-core/.settings/org.eclipse.m2e.core.prefs -text
|
||||||
forge-core/pom.xml -text
|
forge-core/pom.xml -text
|
||||||
forge-core/pom.xml.releaseBackup -text
|
forge-core/pom.xml.releaseBackup -text
|
||||||
|
forge-core/src/main/java/forge/AIOption.java -text
|
||||||
forge-core/src/main/java/forge/CardStorageReader.java -text
|
forge-core/src/main/java/forge/CardStorageReader.java -text
|
||||||
forge-core/src/main/java/forge/FTrace.java -text
|
forge-core/src/main/java/forge/FTrace.java -text
|
||||||
forge-core/src/main/java/forge/ImageKeys.java -text
|
forge-core/src/main/java/forge/ImageKeys.java -text
|
||||||
@@ -17399,10 +17400,12 @@ forge-gui/src/main/java/forge/interfaces/IGuiBase.java -text
|
|||||||
forge-gui/src/main/java/forge/interfaces/IGuiGame.java -text
|
forge-gui/src/main/java/forge/interfaces/IGuiGame.java -text
|
||||||
forge-gui/src/main/java/forge/interfaces/IGuiTimer.java -text
|
forge-gui/src/main/java/forge/interfaces/IGuiTimer.java -text
|
||||||
forge-gui/src/main/java/forge/interfaces/ILobby.java -text
|
forge-gui/src/main/java/forge/interfaces/ILobby.java -text
|
||||||
|
forge-gui/src/main/java/forge/interfaces/ILobbyListener.java -text
|
||||||
forge-gui/src/main/java/forge/interfaces/IMayViewCards.java -text
|
forge-gui/src/main/java/forge/interfaces/IMayViewCards.java -text
|
||||||
forge-gui/src/main/java/forge/interfaces/IPlayerChangeListener.java -text
|
forge-gui/src/main/java/forge/interfaces/IPlayerChangeListener.java -text
|
||||||
forge-gui/src/main/java/forge/interfaces/IProgressBar.java -text
|
forge-gui/src/main/java/forge/interfaces/IProgressBar.java -text
|
||||||
forge-gui/src/main/java/forge/interfaces/ITextField.java -text
|
forge-gui/src/main/java/forge/interfaces/ITextField.java -text
|
||||||
|
forge-gui/src/main/java/forge/interfaces/IUpdateable.java -text
|
||||||
forge-gui/src/main/java/forge/interfaces/IWinLoseView.java -text
|
forge-gui/src/main/java/forge/interfaces/IWinLoseView.java -text
|
||||||
forge-gui/src/main/java/forge/itemmanager/BooleanExpression.java -text
|
forge-gui/src/main/java/forge/itemmanager/BooleanExpression.java -text
|
||||||
forge-gui/src/main/java/forge/itemmanager/ColumnDef.java -text
|
forge-gui/src/main/java/forge/itemmanager/ColumnDef.java -text
|
||||||
@@ -17436,9 +17439,12 @@ forge-gui/src/main/java/forge/limited/WinstonDraft.java -text
|
|||||||
forge-gui/src/main/java/forge/limited/WinstonDraftAI.java -text
|
forge-gui/src/main/java/forge/limited/WinstonDraftAI.java -text
|
||||||
forge-gui/src/main/java/forge/limited/package-info.java svneol=native#text/plain
|
forge-gui/src/main/java/forge/limited/package-info.java svneol=native#text/plain
|
||||||
forge-gui/src/main/java/forge/match/AbstractGuiGame.java -text
|
forge-gui/src/main/java/forge/match/AbstractGuiGame.java -text
|
||||||
|
forge-gui/src/main/java/forge/match/GameLobby.java -text
|
||||||
forge-gui/src/main/java/forge/match/HostedMatch.java -text
|
forge-gui/src/main/java/forge/match/HostedMatch.java -text
|
||||||
|
forge-gui/src/main/java/forge/match/LobbySlot.java -text
|
||||||
|
forge-gui/src/main/java/forge/match/LocalLobby.java -text
|
||||||
|
forge-gui/src/main/java/forge/match/MatchButtonType.java -text
|
||||||
forge-gui/src/main/java/forge/match/MatchConstants.java -text
|
forge-gui/src/main/java/forge/match/MatchConstants.java -text
|
||||||
forge-gui/src/main/java/forge/match/NetGuiGame.java -text
|
|
||||||
forge-gui/src/main/java/forge/match/NextGameDecision.java -text
|
forge-gui/src/main/java/forge/match/NextGameDecision.java -text
|
||||||
forge-gui/src/main/java/forge/match/input/Input.java -text
|
forge-gui/src/main/java/forge/match/input/Input.java -text
|
||||||
forge-gui/src/main/java/forge/match/input/InputAttack.java -text
|
forge-gui/src/main/java/forge/match/input/InputAttack.java -text
|
||||||
@@ -17470,9 +17476,13 @@ forge-gui/src/main/java/forge/model/MetaSet.java -text
|
|||||||
forge-gui/src/main/java/forge/model/MultipleForgeJarsFoundError.java -text
|
forge-gui/src/main/java/forge/model/MultipleForgeJarsFoundError.java -text
|
||||||
forge-gui/src/main/java/forge/model/UnOpenedMeta.java -text
|
forge-gui/src/main/java/forge/model/UnOpenedMeta.java -text
|
||||||
forge-gui/src/main/java/forge/model/package-info.java svneol=native#text/plain
|
forge-gui/src/main/java/forge/model/package-info.java svneol=native#text/plain
|
||||||
|
forge-gui/src/main/java/forge/net/ClientGameLobby.java -text
|
||||||
forge-gui/src/main/java/forge/net/FGameClient.java -text
|
forge-gui/src/main/java/forge/net/FGameClient.java -text
|
||||||
forge-gui/src/main/java/forge/net/FServerManager.java -text
|
forge-gui/src/main/java/forge/net/FServerManager.java -text
|
||||||
forge-gui/src/main/java/forge/net/NetGame.java -text
|
forge-gui/src/main/java/forge/net/LobbyUpdateEvent.java -text
|
||||||
|
forge-gui/src/main/java/forge/net/NetGameController.java -text
|
||||||
|
forge-gui/src/main/java/forge/net/NetGuiGame.java -text
|
||||||
|
forge-gui/src/main/java/forge/net/ServerGameLobby.java -text
|
||||||
forge-gui/src/main/java/forge/net/package-info.java -text
|
forge-gui/src/main/java/forge/net/package-info.java -text
|
||||||
forge-gui/src/main/java/forge/planarconquest/ConquestAction.java -text
|
forge-gui/src/main/java/forge/planarconquest/ConquestAction.java -text
|
||||||
forge-gui/src/main/java/forge/planarconquest/ConquestCommander.java -text
|
forge-gui/src/main/java/forge/planarconquest/ConquestCommander.java -text
|
||||||
@@ -17491,7 +17501,6 @@ forge-gui/src/main/java/forge/player/HumanCostDecision.java -text
|
|||||||
forge-gui/src/main/java/forge/player/HumanPlay.java -text
|
forge-gui/src/main/java/forge/player/HumanPlay.java -text
|
||||||
forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java -text
|
forge-gui/src/main/java/forge/player/HumanPlaySpellAbility.java -text
|
||||||
forge-gui/src/main/java/forge/player/LobbyPlayerHuman.java -text
|
forge-gui/src/main/java/forge/player/LobbyPlayerHuman.java -text
|
||||||
forge-gui/src/main/java/forge/player/NetGameController.java -text
|
|
||||||
forge-gui/src/main/java/forge/player/PlayerControllerHuman.java -text
|
forge-gui/src/main/java/forge/player/PlayerControllerHuman.java -text
|
||||||
forge-gui/src/main/java/forge/player/TargetSelection.java -text
|
forge-gui/src/main/java/forge/player/TargetSelection.java -text
|
||||||
forge-gui/src/main/java/forge/player/package-info.java -text
|
forge-gui/src/main/java/forge/player/package-info.java -text
|
||||||
@@ -17606,6 +17615,7 @@ forge-net/src/main/java/forge/net/IConnectionObserver.java -text
|
|||||||
forge-net/src/main/java/forge/net/Lobby.java -text
|
forge-net/src/main/java/forge/net/Lobby.java -text
|
||||||
forge-net/src/main/java/forge/net/LobbyPlayerRemote.java -text
|
forge-net/src/main/java/forge/net/LobbyPlayerRemote.java -text
|
||||||
forge-net/src/main/java/forge/net/NetServer.java -text
|
forge-net/src/main/java/forge/net/NetServer.java -text
|
||||||
|
forge-net/src/main/java/forge/net/ReplyPool.java -text
|
||||||
forge-net/src/main/java/forge/net/client/GameServlet.java -text
|
forge-net/src/main/java/forge/net/client/GameServlet.java -text
|
||||||
forge-net/src/main/java/forge/net/client/INetClient.java -text
|
forge-net/src/main/java/forge/net/client/INetClient.java -text
|
||||||
forge-net/src/main/java/forge/net/client/InvalidFieldInPacketException.java -text
|
forge-net/src/main/java/forge/net/client/InvalidFieldInPacketException.java -text
|
||||||
@@ -17618,15 +17628,14 @@ forge-net/src/main/java/forge/net/client/state/UnauthorizedClientState.java -tex
|
|||||||
forge-net/src/main/java/forge/net/client/state/package-info.java -text
|
forge-net/src/main/java/forge/net/client/state/package-info.java -text
|
||||||
forge-net/src/main/java/forge/net/game/GuiGameEvent.java -text
|
forge-net/src/main/java/forge/net/game/GuiGameEvent.java -text
|
||||||
forge-net/src/main/java/forge/net/game/IRemote.java -text
|
forge-net/src/main/java/forge/net/game/IRemote.java -text
|
||||||
|
forge-net/src/main/java/forge/net/game/IdentifiableNetEvent.java -text
|
||||||
forge-net/src/main/java/forge/net/game/LobbySlotType.java -text
|
forge-net/src/main/java/forge/net/game/LobbySlotType.java -text
|
||||||
forge-net/src/main/java/forge/net/game/LobbyState.java -text
|
|
||||||
forge-net/src/main/java/forge/net/game/LobbyUpdateEvent.java -text
|
|
||||||
forge-net/src/main/java/forge/net/game/LoginEvent.java -text
|
forge-net/src/main/java/forge/net/game/LoginEvent.java -text
|
||||||
forge-net/src/main/java/forge/net/game/LogoutEvent.java -text
|
forge-net/src/main/java/forge/net/game/LogoutEvent.java -text
|
||||||
forge-net/src/main/java/forge/net/game/MessageEvent.java -text
|
forge-net/src/main/java/forge/net/game/MessageEvent.java -text
|
||||||
forge-net/src/main/java/forge/net/game/NetEvent.java -text
|
forge-net/src/main/java/forge/net/game/NetEvent.java -text
|
||||||
forge-net/src/main/java/forge/net/game/RegisterDeckEvent.java -text
|
forge-net/src/main/java/forge/net/game/ReplyEvent.java -text
|
||||||
forge-net/src/main/java/forge/net/game/client/ILobbyListener.java -text
|
forge-net/src/main/java/forge/net/game/UpdateLobbyPlayerEvent.java -text
|
||||||
forge-net/src/main/java/forge/net/game/client/IToServer.java -text
|
forge-net/src/main/java/forge/net/game/client/IToServer.java -text
|
||||||
forge-net/src/main/java/forge/net/game/client/package-info.java -text
|
forge-net/src/main/java/forge/net/game/client/package-info.java -text
|
||||||
forge-net/src/main/java/forge/net/game/package-info.java -text
|
forge-net/src/main/java/forge/net/game/package-info.java -text
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package forge.ai;
|
package forge.ai;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import forge.AIOption;
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.player.IGameEntitiesFactory;
|
import forge.game.player.IGameEntitiesFactory;
|
||||||
@@ -15,9 +16,9 @@ public class LobbyPlayerAi extends LobbyPlayer implements IGameEntitiesFactory {
|
|||||||
private boolean allowCheatShuffle;
|
private boolean allowCheatShuffle;
|
||||||
private boolean useSimulation;
|
private boolean useSimulation;
|
||||||
|
|
||||||
public LobbyPlayerAi(String name, Map<String, String> options) {
|
public LobbyPlayerAi(String name, Set<AIOption> options) {
|
||||||
super(name);
|
super(name);
|
||||||
if (options != null && "True".equals(options.get("UseSimulation"))) {
|
if (options != null && options.contains(AIOption.USE_SIMULATION)) {
|
||||||
this.useSimulation = true;
|
this.useSimulation = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import forge.game.player.DelayedReveal;
|
|||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
import forge.game.player.PlayerController;
|
import forge.game.player.PlayerController;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.spellability.*;
|
import forge.game.spellability.*;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
@@ -141,7 +142,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
@Override
|
@Override
|
||||||
public <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, DelayedReveal delayedReveal, SpellAbility sa, String title, boolean isOptional, Player targetedPlayer) {
|
public <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, DelayedReveal delayedReveal, SpellAbility sa, String title, boolean isOptional, Player targetedPlayer) {
|
||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
delayedReveal.reveal(this);
|
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||||
}
|
}
|
||||||
ApiType api = sa.getApi();
|
ApiType api = sa.getApi();
|
||||||
if (null == api) {
|
if (null == api) {
|
||||||
@@ -240,6 +241,11 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
// We don't know how to reveal cards to AI
|
// We don't know how to reveal cards to AI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reveal(Collection<CardView> cards, ZoneType zone, PlayerView owner, String messagePrefix) {
|
||||||
|
// We don't know how to reveal cards to AI
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutablePair<CardCollection, CardCollection> arrangeForScry(CardCollection topN) {
|
public ImmutablePair<CardCollection, CardCollection> arrangeForScry(CardCollection topN) {
|
||||||
CardCollection toBottom = new CardCollection();
|
CardCollection toBottom = new CardCollection();
|
||||||
@@ -850,7 +856,7 @@ public class PlayerControllerAi extends PlayerController {
|
|||||||
String selectPrompt, boolean isOptional, Player decider) {
|
String selectPrompt, boolean isOptional, Player decider) {
|
||||||
|
|
||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
delayedReveal.reveal(this);
|
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||||
}
|
}
|
||||||
return ChangeZoneAi.chooseCardToHiddenOriginChangeZone(destination, origin, sa, fetchList, player, decider);
|
return ChangeZoneAi.chooseCardToHiddenOriginChangeZone(destination, origin, sa, fetchList, player, decider);
|
||||||
}
|
}
|
||||||
|
|||||||
5
forge-core/src/main/java/forge/AIOption.java
Normal file
5
forge-core/src/main/java/forge/AIOption.java
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
package forge;
|
||||||
|
|
||||||
|
public enum AIOption {
|
||||||
|
USE_SIMULATION;
|
||||||
|
}
|
||||||
@@ -41,6 +41,8 @@ import java.util.Set;
|
|||||||
* @version $Id: java 9708 2011-08-09 19:34:12Z jendave $
|
* @version $Id: java 9708 2011-08-09 19:34:12Z jendave $
|
||||||
*/
|
*/
|
||||||
public final class CardType implements Comparable<CardType>, CardTypeView {
|
public final class CardType implements Comparable<CardType>, CardTypeView {
|
||||||
|
private static final long serialVersionUID = 7612877255541109847L;
|
||||||
|
|
||||||
public static final CardTypeView EMPTY = new CardType();
|
public static final CardTypeView EMPTY = new CardType();
|
||||||
|
|
||||||
public enum CoreType {
|
public enum CoreType {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package forge.card;
|
package forge.card;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -8,7 +9,7 @@ import forge.card.CardType.CoreType;
|
|||||||
import forge.card.CardType.Supertype;
|
import forge.card.CardType.Supertype;
|
||||||
|
|
||||||
//Interface to expose only the desired functions of CardType without allowing modification
|
//Interface to expose only the desired functions of CardType without allowing modification
|
||||||
public interface CardTypeView extends Iterable<String> {
|
public interface CardTypeView extends Iterable<String>, Serializable {
|
||||||
boolean isEmpty();
|
boolean isEmpty();
|
||||||
Iterable<CoreType> getCoreTypes();
|
Iterable<CoreType> getCoreTypes();
|
||||||
Iterable<Supertype> getSupertypes();
|
Iterable<Supertype> getSupertypes();
|
||||||
|
|||||||
@@ -18,9 +18,11 @@
|
|||||||
package forge.card;
|
package forge.card;
|
||||||
|
|
||||||
import com.google.common.collect.UnmodifiableIterator;
|
import com.google.common.collect.UnmodifiableIterator;
|
||||||
|
|
||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.util.BinaryUtil;
|
import forge.util.BinaryUtil;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
@@ -34,7 +36,8 @@ import java.util.NoSuchElementException;
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public final class ColorSet implements Comparable<ColorSet>, Iterable<Byte> {
|
public final class ColorSet implements Comparable<ColorSet>, Iterable<Byte>, Serializable {
|
||||||
|
private static final long serialVersionUID = 794691267379929080L;
|
||||||
|
|
||||||
private final byte myColor;
|
private final byte myColor;
|
||||||
private final float orderWeight;
|
private final float orderWeight;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package forge.card.mana;
|
|||||||
|
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -35,7 +36,9 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
* @version $Id: CardManaCost.java 9708 2011-08-09 19:34:12Z jendave $
|
* @version $Id: CardManaCost.java 9708 2011-08-09 19:34:12Z jendave $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public final class ManaCost implements Comparable<ManaCost>, Iterable<ManaCostShard> {
|
public final class ManaCost implements Comparable<ManaCost>, Iterable<ManaCostShard>, Serializable {
|
||||||
|
private static final long serialVersionUID = -2477430496624149226L;
|
||||||
|
|
||||||
private static final char DELIM = (char)6;
|
private static final char DELIM = (char)6;
|
||||||
|
|
||||||
private List<ManaCostShard> shards;
|
private List<ManaCostShard> shards;
|
||||||
|
|||||||
@@ -17,6 +17,15 @@
|
|||||||
*/
|
*/
|
||||||
package forge.deck;
|
package forge.deck;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import forge.StaticData;
|
import forge.StaticData;
|
||||||
@@ -26,17 +35,9 @@ import forge.util.ItemPool;
|
|||||||
import forge.util.ItemPoolSorter;
|
import forge.util.ItemPoolSorter;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
|
|
||||||
public class CardPool extends ItemPool<PaperCard> {
|
public class CardPool extends ItemPool<PaperCard> {
|
||||||
|
private static final long serialVersionUID = -5379091255613968393L;
|
||||||
|
|
||||||
public CardPool() {
|
public CardPool() {
|
||||||
super(PaperCard.class);
|
super(PaperCard.class);
|
||||||
|
|||||||
@@ -17,13 +17,17 @@
|
|||||||
*/
|
*/
|
||||||
package forge.item;
|
package forge.item;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.ObjectInputStream;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
import forge.ImageKeys;
|
import forge.ImageKeys;
|
||||||
|
import forge.StaticData;
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
import forge.card.CardRules;
|
import forge.card.CardRules;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A lightweight version of a card that matches real-world cards, to use outside of games (eg. inventory, decks, trade).
|
* A lightweight version of a card that matches real-world cards, to use outside of games (eg. inventory, decks, trade).
|
||||||
* <br><br>
|
* <br><br>
|
||||||
@@ -31,9 +35,11 @@ import forge.card.CardRules;
|
|||||||
*
|
*
|
||||||
* @author Forge
|
* @author Forge
|
||||||
*/
|
*/
|
||||||
public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet, IPaperCard {
|
public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFromSet, IPaperCard, Serializable {
|
||||||
|
private static final long serialVersionUID = 2942081982620691205L;
|
||||||
|
|
||||||
// Reference to rules
|
// Reference to rules
|
||||||
private final transient CardRules rules;
|
private transient CardRules rules;
|
||||||
|
|
||||||
// These fields are kinda PK for PrintedCard
|
// These fields are kinda PK for PrintedCard
|
||||||
private final String name;
|
private final String name;
|
||||||
@@ -43,7 +49,7 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
|||||||
private Boolean hasImage;
|
private Boolean hasImage;
|
||||||
|
|
||||||
// Calculated fields are below:
|
// Calculated fields are below:
|
||||||
private final transient CardRarity rarity; // rarity is given in ctor when set is assigned
|
private transient CardRarity rarity; // rarity is given in ctor when set is assigned
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
@@ -199,4 +205,13 @@ public final class PaperCard implements Comparable<IPaperCard>, InventoryItemFro
|
|||||||
|
|
||||||
return Integer.compare(artIndex, o.getArtIndex());
|
return Integer.compare(artIndex, o.getArtIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
|
||||||
|
// default deserialization
|
||||||
|
ois.defaultReadObject();
|
||||||
|
|
||||||
|
final IPaperCard pc = StaticData.instance().getCommonCards().getCard(name, edition, artIndex);
|
||||||
|
this.rules = pc.getRules();
|
||||||
|
this.rarity = pc.getRarity();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import com.google.common.base.Predicate;
|
|||||||
|
|
||||||
import forge.item.InventoryItem;
|
import forge.item.InventoryItem;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
@@ -34,7 +35,8 @@ import java.util.Map.Entry;
|
|||||||
* @param <T>
|
* @param <T>
|
||||||
* an Object
|
* an Object
|
||||||
*/
|
*/
|
||||||
public class ItemPool<T extends InventoryItem> implements Iterable<Entry<T, Integer>> {
|
public class ItemPool<T extends InventoryItem> implements Iterable<Entry<T, Integer>>, Serializable {
|
||||||
|
private static final long serialVersionUID = 6572047177527559797L;
|
||||||
|
|
||||||
/** The fn to printed. */
|
/** The fn to printed. */
|
||||||
public final transient Function<Entry<T, Integer>, T> FN_GET_KEY = new Function<Entry<T, Integer>, T>() {
|
public final transient Function<Entry<T, Integer>, T> FN_GET_KEY = new Function<Entry<T, Integer>, T>() {
|
||||||
|
|||||||
@@ -56,8 +56,10 @@ import forge.game.player.Player;
|
|||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.player.RegisteredPlayer;
|
import forge.game.player.RegisteredPlayer;
|
||||||
import forge.game.replacement.ReplacementHandler;
|
import forge.game.replacement.ReplacementHandler;
|
||||||
|
import forge.game.spellability.Ability;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
import forge.game.spellability.SpellAbilityStackInstance;
|
||||||
|
import forge.game.spellability.SpellAbilityView;
|
||||||
import forge.game.trigger.TriggerHandler;
|
import forge.game.trigger.TriggerHandler;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.MagicStack;
|
import forge.game.zone.MagicStack;
|
||||||
@@ -105,20 +107,20 @@ public class Game {
|
|||||||
private final GameView view;
|
private final GameView view;
|
||||||
private final Tracker tracker = new Tracker();
|
private final Tracker tracker = new Tracker();
|
||||||
|
|
||||||
private GameEntityCache<Player, PlayerView> playerCache = new GameEntityCache<>();
|
private final GameEntityCache<Player, PlayerView> playerCache = new GameEntityCache<>();
|
||||||
public Player getPlayer(PlayerView playerView) {
|
public Player getPlayer(PlayerView playerView) {
|
||||||
return playerCache.get(playerView);
|
return playerCache.get(playerView);
|
||||||
}
|
}
|
||||||
public void addPlayer(Integer id, Player player) {
|
public void addPlayer(int id, Player player) {
|
||||||
playerCache.put(id, player);
|
playerCache.put(Integer.valueOf(id), player);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GameEntityCache<Card, CardView> cardCache = new GameEntityCache<>();
|
private final GameEntityCache<Card, CardView> cardCache = new GameEntityCache<>();
|
||||||
public Card getCard(CardView cardView) {
|
public Card getCard(CardView cardView) {
|
||||||
return cardCache.get(cardView);
|
return cardCache.get(cardView);
|
||||||
}
|
}
|
||||||
public void addCard(Integer id, Card card) {
|
public void addCard(int id, Card card) {
|
||||||
cardCache.put(id, card);
|
cardCache.put(Integer.valueOf(id), card);
|
||||||
}
|
}
|
||||||
public CardCollection getCardList(Iterable<CardView> cardViews) {
|
public CardCollection getCardList(Iterable<CardView> cardViews) {
|
||||||
CardCollection list = new CardCollection();
|
CardCollection list = new CardCollection();
|
||||||
@@ -126,10 +128,20 @@ public class Game {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final GameEntityCache<SpellAbility, SpellAbilityView> spabCache = new GameEntityCache<>();
|
||||||
|
public SpellAbility getSpellAbility(final SpellAbilityView view) {
|
||||||
|
return spabCache.get(view);
|
||||||
|
}
|
||||||
|
public void addSpellAbility(int id, SpellAbility spellAbility) {
|
||||||
|
spabCache.put(Integer.valueOf(id), spellAbility);
|
||||||
|
}
|
||||||
|
|
||||||
public Game(List<RegisteredPlayer> players0, GameRules rules0, Match match0) { /* no more zones to map here */
|
public Game(List<RegisteredPlayer> players0, GameRules rules0, Match match0) { /* no more zones to map here */
|
||||||
rules = rules0;
|
rules = rules0;
|
||||||
match = match0;
|
match = match0;
|
||||||
|
|
||||||
|
spabCache.put(Ability.PLAY_LAND_SURROGATE.getId(), Ability.PLAY_LAND_SURROGATE);
|
||||||
|
|
||||||
int highestTeam = -1;
|
int highestTeam = -1;
|
||||||
for (RegisteredPlayer psc : players0) {
|
for (RegisteredPlayer psc : players0) {
|
||||||
// Track highest team number for auto assigning unassigned teams
|
// Track highest team number for auto assigning unassigned teams
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package forge.game;
|
package forge.game;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class GameEntityCache<Entity extends GameEntity, View extends GameEntityView> {
|
import forge.trackable.TrackableObject;
|
||||||
|
|
||||||
|
public class GameEntityCache<Entity extends IIdentifiable, View extends TrackableObject> {
|
||||||
private HashMap<Integer, Entity> entityCache = new HashMap<Integer, Entity>();
|
private HashMap<Integer, Entity> entityCache = new HashMap<Integer, Entity>();
|
||||||
|
|
||||||
public void put(Integer id, Entity entity) {
|
public void put(Integer id, Entity entity) {
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ import forge.trackable.TrackableProperty;
|
|||||||
import forge.trackable.Tracker;
|
import forge.trackable.Tracker;
|
||||||
|
|
||||||
public abstract class GameEntityView extends TrackableObject {
|
public abstract class GameEntityView extends TrackableObject {
|
||||||
|
private static final long serialVersionUID = -5129089945124455670L;
|
||||||
|
|
||||||
public static GameEntityView get(GameEntity e) {
|
public static GameEntityView get(GameEntity e) {
|
||||||
return e == null ? null : e.getView();
|
return e == null ? null : e.getView();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package forge.game;
|
|||||||
|
|
||||||
import forge.game.event.IGameEventVisitor;
|
import forge.game.event.IGameEventVisitor;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
@@ -30,10 +31,12 @@ import java.util.Observable;
|
|||||||
* @author Forge
|
* @author Forge
|
||||||
* @version $Id: GameLog.java 12297 2011-11-28 19:56:47Z slapshot5 $
|
* @version $Id: GameLog.java 12297 2011-11-28 19:56:47Z slapshot5 $
|
||||||
*/
|
*/
|
||||||
public class GameLog extends Observable {
|
public class GameLog extends Observable implements Serializable {
|
||||||
private List<GameLogEntry> log = new ArrayList<GameLogEntry>();
|
private static final long serialVersionUID = 6465283802022948827L;
|
||||||
|
|
||||||
private GameLogFormatter formatter = new GameLogFormatter(this);
|
private final List<GameLogEntry> log = new ArrayList<GameLogEntry>();
|
||||||
|
|
||||||
|
private final transient GameLogFormatter formatter = new GameLogFormatter(this);
|
||||||
|
|
||||||
/** Logging level:
|
/** Logging level:
|
||||||
* 0 - Turn
|
* 0 - Turn
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package forge.game;
|
package forge.game;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class GameLogEntry implements Serializable {
|
||||||
|
private static final long serialVersionUID = -5322859985172769630L;
|
||||||
|
|
||||||
public class GameLogEntry {
|
|
||||||
public final String message;
|
public final String message;
|
||||||
public final GameLogEntryType type;
|
public final GameLogEntryType type;
|
||||||
// might add here date and some other fields
|
// might add here date and some other fields
|
||||||
@@ -13,7 +16,6 @@ public class GameLogEntry {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return type.getCaption() + ": " + message;
|
return type.getCaption() + ": " + message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,14 +111,14 @@ public class GameLogFormatter extends IGameEventVisitor.Base<GameLogEntry> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GameLogEntry visit(final GameEventPlayerControl event) {
|
public GameLogEntry visit(final GameEventPlayerControl event) {
|
||||||
final LobbyPlayer newController = event.newController;
|
final LobbyPlayer newLobbyPlayer = event.newLobbyPlayer;
|
||||||
final Player p = event.player;
|
final Player p = event.player;
|
||||||
|
|
||||||
final String message;
|
final String message;
|
||||||
if (newController == null) {
|
if (newLobbyPlayer == null) {
|
||||||
message = p.getName() + " has restored control over themself";
|
message = p.getName() + " has restored control over themself";
|
||||||
} else {
|
} else {
|
||||||
message = String.format("%s is controlled by %s", p.getName(), newController.getName());
|
message = String.format("%s is controlled by %s", p.getName(), newLobbyPlayer.getName());
|
||||||
}
|
}
|
||||||
return new GameLogEntry(GameLogEntryType.PLAYER_CONROL, message);
|
return new GameLogEntry(GameLogEntryType.PLAYER_CONROL, message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import forge.item.PaperCard;
|
|||||||
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
@@ -41,7 +42,9 @@ import java.util.Map.Entry;
|
|||||||
// only getters) and
|
// only getters) and
|
||||||
// GameObserver class - who should be notified of any considerable ingame event
|
// GameObserver class - who should be notified of any considerable ingame event
|
||||||
public final class GameOutcome implements Iterable<Pair<LobbyPlayer, PlayerStatistics>> {
|
public final class GameOutcome implements Iterable<Pair<LobbyPlayer, PlayerStatistics>> {
|
||||||
public static class AnteResult {
|
public static class AnteResult implements Serializable {
|
||||||
|
private static final long serialVersionUID = 5087554550408543192L;
|
||||||
|
|
||||||
public final List<PaperCard> lostCards;
|
public final List<PaperCard> lostCards;
|
||||||
public final List<PaperCard> wonCards;
|
public final List<PaperCard> wonCards;
|
||||||
|
|
||||||
@@ -50,8 +53,7 @@ public final class GameOutcome implements Iterable<Pair<LobbyPlayer, PlayerStati
|
|||||||
if (won) {
|
if (won) {
|
||||||
this.wonCards = cards;
|
this.wonCards = cards;
|
||||||
this.lostCards = new ArrayList<>();
|
this.lostCards = new ArrayList<>();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
this.lostCards = cards;
|
this.lostCards = cards;
|
||||||
this.wonCards = new ArrayList<>();
|
this.wonCards = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package forge.game;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.game.GameOutcome.AnteResult;
|
import forge.game.GameOutcome.AnteResult;
|
||||||
@@ -22,6 +24,7 @@ import forge.trackable.TrackableProperty;
|
|||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
|
|
||||||
public class GameView extends TrackableObject {
|
public class GameView extends TrackableObject {
|
||||||
|
private static final long serialVersionUID = 8522884512960961528L;
|
||||||
|
|
||||||
/*private final TrackableIndex<CardView> cards = new TrackableIndex<CardView>();
|
/*private final TrackableIndex<CardView> cards = new TrackableIndex<CardView>();
|
||||||
private final TrackableIndex<PlayerView> players = new TrackableIndex<PlayerView>();
|
private final TrackableIndex<PlayerView> players = new TrackableIndex<PlayerView>();
|
||||||
@@ -29,7 +32,7 @@ public class GameView extends TrackableObject {
|
|||||||
private final TrackableIndex<StackItemView> stackItems = new TrackableIndex<StackItemView>();*/
|
private final TrackableIndex<StackItemView> stackItems = new TrackableIndex<StackItemView>();*/
|
||||||
private final TrackableCollection<PlayerView> players;
|
private final TrackableCollection<PlayerView> players;
|
||||||
private CombatView combatView;
|
private CombatView combatView;
|
||||||
private final Game game; //TODO: Remove this when possible before network support added
|
private final transient Game game; //TODO: Remove this when possible before network support added
|
||||||
|
|
||||||
public GameView(final Game game0) {
|
public GameView(final Game game0) {
|
||||||
super(-1, game0.getTracker()); //ID not needed
|
super(-1, game0.getTracker()); //ID not needed
|
||||||
@@ -88,10 +91,17 @@ public class GameView extends TrackableObject {
|
|||||||
set(TrackableProperty.PlayerTurn, PlayerView.get(phaseHandler.getPlayerTurn()));
|
set(TrackableProperty.PlayerTurn, PlayerView.get(phaseHandler.getPlayerTurn()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public FCollectionView<StackItemView> getStack() {
|
||||||
|
return get(TrackableProperty.Stack);
|
||||||
|
}
|
||||||
|
public StackItemView peekStack() {
|
||||||
|
return Iterables.getFirst(getStack(), null);
|
||||||
|
}
|
||||||
public int getStormCount() {
|
public int getStormCount() {
|
||||||
return get(TrackableProperty.StormCount);
|
return get(TrackableProperty.StormCount);
|
||||||
}
|
}
|
||||||
void updateStack(MagicStack stack) {
|
void updateStack(final MagicStack stack) {
|
||||||
|
set(TrackableProperty.Stack, StackItemView.getCollection(stack));
|
||||||
set(TrackableProperty.StormCount, stack.getSpellsCastThisTurn().size());
|
set(TrackableProperty.StormCount, stack.getSpellsCastThisTurn().size());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,10 +176,6 @@ public class GameView extends TrackableObject {
|
|||||||
|
|
||||||
//TODO: Find better ways to make this information available to all GUIs without using the Game class
|
//TODO: Find better ways to make this information available to all GUIs without using the Game class
|
||||||
|
|
||||||
public FCollectionView<StackItemView> getStack() {
|
|
||||||
return StackItemView.getCollection(game.getStack());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMatchWonBy(LobbyPlayer questPlayer) {
|
public boolean isMatchWonBy(LobbyPlayer questPlayer) {
|
||||||
return game.getMatch().isWonBy(questPlayer);
|
return game.getMatch().isWonBy(questPlayer);
|
||||||
}
|
}
|
||||||
@@ -182,10 +188,6 @@ public class GameView extends TrackableObject {
|
|||||||
return game.getOutcome().getWinningLobbyPlayer();
|
return game.getOutcome().getWinningLobbyPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public StackItemView peekStack() {
|
|
||||||
return StackItemView.get(game.getStack().peek());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isWinner(LobbyPlayer guiPlayer) {
|
public boolean isWinner(LobbyPlayer guiPlayer) {
|
||||||
return game.getOutcome().isWinner(guiPlayer);
|
return game.getOutcome().isWinner(guiPlayer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import forge.game.event.GameEventCombatChanged;
|
|||||||
import forge.game.player.DelayedReveal;
|
import forge.game.player.DelayedReveal;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.AbilitySub;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
import forge.game.spellability.SpellAbilityStackInstance;
|
||||||
@@ -700,10 +701,10 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
final int fetchNum = Math.min(player.getCardsIn(ZoneType.Library).size(), 4);
|
final int fetchNum = Math.min(player.getCardsIn(ZoneType.Library).size(), 4);
|
||||||
CardCollectionView shown = !decider.hasKeyword("LimitSearchLibrary") ? player.getCardsIn(ZoneType.Library) : player.getCardsIn(ZoneType.Library, fetchNum);
|
CardCollectionView shown = !decider.hasKeyword("LimitSearchLibrary") ? player.getCardsIn(ZoneType.Library) : player.getCardsIn(ZoneType.Library, fetchNum);
|
||||||
// Look at whole library before moving onto choosing a card
|
// Look at whole library before moving onto choosing a card
|
||||||
delayedReveal = new DelayedReveal(shown, ZoneType.Library, player, source.getName() + " - Looking at cards in ");
|
delayedReveal = new DelayedReveal(shown, ZoneType.Library, PlayerView.get(player), source.getName() + " - Looking at cards in ");
|
||||||
}
|
}
|
||||||
else if (origin.contains(ZoneType.Hand) && player.isOpponentOf(decider)) {
|
else if (origin.contains(ZoneType.Hand) && player.isOpponentOf(decider)) {
|
||||||
delayedReveal = new DelayedReveal(player.getCardsIn(ZoneType.Hand), ZoneType.Hand, player, source.getName() + " - Looking at cards in ");
|
delayedReveal = new DelayedReveal(player.getCardsIn(ZoneType.Hand), ZoneType.Hand, PlayerView.get(player), source.getName() + " - Looking at cards in ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,7 +785,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
Card c = null;
|
Card c = null;
|
||||||
if (sa.hasParam("AtRandom")) {
|
if (sa.hasParam("AtRandom")) {
|
||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
delayedReveal.reveal(decider.getController());
|
decider.getController().reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||||
}
|
}
|
||||||
c = Aggregates.random(fetchList);
|
c = Aggregates.random(fetchList);
|
||||||
}
|
}
|
||||||
@@ -812,7 +813,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
fetchList.remove(c);
|
fetchList.remove(c);
|
||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
delayedReveal.remove(c);
|
delayedReveal.remove(CardView.get(c));
|
||||||
}
|
}
|
||||||
chosenCards.add(c);
|
chosenCards.add(c);
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import forge.game.card.CardCollectionView;
|
|||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.player.DelayedReveal;
|
import forge.game.player.DelayedReveal;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.game.zone.PlayerZone;
|
import forge.game.zone.PlayerZone;
|
||||||
@@ -144,7 +145,7 @@ public class DigEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
else if (!sa.hasParam("NoLooking")) {
|
else if (!sa.hasParam("NoLooking")) {
|
||||||
// show the user the revealed cards
|
// show the user the revealed cards
|
||||||
delayedReveal = new DelayedReveal(top, srcZone, p);
|
delayedReveal = new DelayedReveal(top, srcZone, PlayerView.get(p));
|
||||||
|
|
||||||
if (noMove) {
|
if (noMove) {
|
||||||
// Let the activating player see the cards even if they're not moved
|
// Let the activating player see the cards even if they're not moved
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ import java.util.Collection;
|
|||||||
import forge.util.FCollection;
|
import forge.util.FCollection;
|
||||||
|
|
||||||
public class CardCollection extends FCollection<Card> implements CardCollectionView {
|
public class CardCollection extends FCollection<Card> implements CardCollectionView {
|
||||||
|
private static final long serialVersionUID = -8133537013727100275L;
|
||||||
|
|
||||||
public static final CardCollectionView EMPTY = new CardCollection();
|
public static final CardCollectionView EMPTY = new CardCollection();
|
||||||
|
|
||||||
public static boolean hasCard(CardCollection cards) {
|
public static boolean hasCard(CardCollection cards) {
|
||||||
|
|||||||
@@ -10,10 +10,10 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
import forge.ImageKeys;
|
import forge.ImageKeys;
|
||||||
import forge.card.CardStateName;
|
|
||||||
import forge.card.CardEdition;
|
import forge.card.CardEdition;
|
||||||
import forge.card.CardRarity;
|
import forge.card.CardRarity;
|
||||||
import forge.card.CardRules;
|
import forge.card.CardRules;
|
||||||
|
import forge.card.CardStateName;
|
||||||
import forge.card.CardType;
|
import forge.card.CardType;
|
||||||
import forge.card.CardTypeView;
|
import forge.card.CardTypeView;
|
||||||
import forge.card.ColorSet;
|
import forge.card.ColorSet;
|
||||||
@@ -32,6 +32,8 @@ import forge.trackable.Tracker;
|
|||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
|
|
||||||
public class CardView extends GameEntityView {
|
public class CardView extends GameEntityView {
|
||||||
|
private static final long serialVersionUID = -3624090829028979255L;
|
||||||
|
|
||||||
public static CardView get(Card c) {
|
public static CardView get(Card c) {
|
||||||
return c == null ? null : c.getView();
|
return c == null ? null : c.getView();
|
||||||
}
|
}
|
||||||
@@ -715,6 +717,8 @@ public class CardView extends GameEntityView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public class CardStateView extends TrackableObject {
|
public class CardStateView extends TrackableObject {
|
||||||
|
private static final long serialVersionUID = 6673944200513430607L;
|
||||||
|
|
||||||
private final CardStateName state;
|
private final CardStateName state;
|
||||||
|
|
||||||
public CardStateView(final int id0, final CardStateName state0, final Tracker tracker) {
|
public CardStateView(final int id0, final CardStateName state0, final Tracker tracker) {
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ import forge.util.FCollection;
|
|||||||
|
|
||||||
|
|
||||||
public class CombatView extends TrackableObject {
|
public class CombatView extends TrackableObject {
|
||||||
|
private static final long serialVersionUID = 68085618912864941L;
|
||||||
|
|
||||||
public CombatView(final Tracker tracker) {
|
public CombatView(final Tracker tracker) {
|
||||||
super(-1, tracker); //ID not needed
|
super(-1, tracker); //ID not needed
|
||||||
set(TrackableProperty.AttackersWithDefenders, new HashMap<CardView, GameEntityView>());
|
set(TrackableProperty.AttackersWithDefenders, new HashMap<CardView, GameEntityView>());
|
||||||
|
|||||||
@@ -2,20 +2,25 @@ package forge.game.event;
|
|||||||
|
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
import forge.game.player.PlayerController;
|
||||||
|
|
||||||
public class GameEventPlayerControl extends GameEvent {
|
public class GameEventPlayerControl extends GameEvent {
|
||||||
public final Player player;
|
public final Player player;
|
||||||
public final LobbyPlayer oldController;
|
public final LobbyPlayer oldLobbyPlayer;
|
||||||
public final LobbyPlayer newController;
|
public final PlayerController oldController;
|
||||||
|
public final LobbyPlayer newLobbyPlayer;
|
||||||
|
public final PlayerController newController;
|
||||||
|
|
||||||
public GameEventPlayerControl(Player p, LobbyPlayer old, LobbyPlayer new1) {
|
public GameEventPlayerControl(final Player p, final LobbyPlayer oldLobbyPlayer, final PlayerController oldController, final LobbyPlayer newLobbyPlayer, final PlayerController newController) {
|
||||||
player = p;
|
this.player = p;
|
||||||
oldController = old;
|
this.oldLobbyPlayer = oldLobbyPlayer;
|
||||||
newController = new1;
|
this.oldController = oldController;
|
||||||
|
this.newLobbyPlayer = newLobbyPlayer;
|
||||||
|
this.newController = newController;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> T visit(IGameEventVisitor<T> visitor) {
|
public <T> T visit(final IGameEventVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package forge.game.keyword;
|
package forge.game.keyword;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -7,8 +8,10 @@ import java.util.Iterator;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class KeywordCollection implements Iterable<String> {
|
public class KeywordCollection implements Iterable<String>, Serializable {
|
||||||
private KeywordCollectionView view;
|
private static final long serialVersionUID = -2882986558147844702L;
|
||||||
|
|
||||||
|
private transient KeywordCollectionView view;
|
||||||
private final EnumMap<Keyword, List<KeywordInstance<?>>> map = new EnumMap<Keyword, List<KeywordInstance<?>>>(Keyword.class);
|
private final EnumMap<Keyword, List<KeywordInstance<?>>> map = new EnumMap<Keyword, List<KeywordInstance<?>>>(Keyword.class);
|
||||||
|
|
||||||
public boolean contains(Keyword keyword) {
|
public boolean contains(Keyword keyword) {
|
||||||
@@ -134,7 +137,9 @@ public class KeywordCollection implements Iterable<String> {
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class KeywordCollectionView implements Iterable<String> {
|
public class KeywordCollectionView implements Iterable<String>, Serializable {
|
||||||
|
private static final long serialVersionUID = 7536969077044188264L;
|
||||||
|
|
||||||
protected KeywordCollectionView() {
|
protected KeywordCollectionView() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,32 @@
|
|||||||
package forge.game.player;
|
package forge.game.player;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardView;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
//Stores information to reveal cards after a delay unless those cards can be revealed in the same dialog as cards being selected
|
/**
|
||||||
|
* Stores information to reveal cards after a delay unless those cards can be
|
||||||
|
* revealed in the same dialog as cards being selected
|
||||||
|
*/
|
||||||
public class DelayedReveal {
|
public class DelayedReveal {
|
||||||
private final CardCollection cards;
|
private final Collection<CardView> cards;
|
||||||
private final ZoneType zone;
|
private final ZoneType zone;
|
||||||
private final Player owner;
|
private final PlayerView owner;
|
||||||
private final String messagePrefix;
|
private final String messagePrefix;
|
||||||
private boolean revealed;
|
|
||||||
|
|
||||||
public DelayedReveal(Iterable<Card> cards0, ZoneType zone0, Player owner0) {
|
public DelayedReveal(Iterable<Card> cards0, ZoneType zone0, PlayerView owner0) {
|
||||||
this(cards0, zone0, owner0, null);
|
this(cards0, zone0, owner0, null);
|
||||||
}
|
}
|
||||||
public DelayedReveal(Iterable<Card> cards0, ZoneType zone0, Player owner0, String messagePrefix0) {
|
public DelayedReveal(Iterable<Card> cards0, ZoneType zone0, PlayerView owner0, String messagePrefix0) {
|
||||||
cards = new CardCollection(cards0); //create copy of list to allow modification
|
cards = CardView.getCollection(cards0);
|
||||||
zone = zone0;
|
zone = zone0;
|
||||||
owner = owner0;
|
owner = owner0;
|
||||||
messagePrefix = messagePrefix0;
|
messagePrefix = messagePrefix0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterable<Card> getCards() {
|
public Collection<CardView> getCards() {
|
||||||
return cards;
|
return cards;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,17 +34,16 @@ public class DelayedReveal {
|
|||||||
return zone;
|
return zone;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Player getOwner() {
|
public PlayerView getOwner() {
|
||||||
return owner;
|
return owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void remove(Card card) {
|
public String getMessagePrefix() {
|
||||||
|
return messagePrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(CardView card) {
|
||||||
cards.remove(card);
|
cards.remove(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reveal(PlayerController controller) {
|
|
||||||
if (revealed) { return; } //avoid revealing more than once
|
|
||||||
revealed = true;
|
|
||||||
controller.reveal(cards, zone, owner, messagePrefix);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2099,7 +2099,7 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
return mindSlaveMaster;
|
return mindSlaveMaster;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setMindSlaveMaster(Player mindSlaveMaster0) {
|
public final void setMindSlaveMaster(final Player mindSlaveMaster0) {
|
||||||
if (mindSlaveMaster == mindSlaveMaster0) {
|
if (mindSlaveMaster == mindSlaveMaster0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -2107,14 +2107,14 @@ public class Player extends GameEntity implements Comparable<Player> {
|
|||||||
view.updateMindSlaveMaster(this);
|
view.updateMindSlaveMaster(this);
|
||||||
|
|
||||||
if (mindSlaveMaster != null) {
|
if (mindSlaveMaster != null) {
|
||||||
LobbyPlayer oldLobbyPlayer = getLobbyPlayer();
|
final LobbyPlayer oldLobbyPlayer = getLobbyPlayer();
|
||||||
IGameEntitiesFactory master = (IGameEntitiesFactory)mindSlaveMaster.getLobbyPlayer();
|
final PlayerController oldController = getController();
|
||||||
|
final IGameEntitiesFactory master = (IGameEntitiesFactory)mindSlaveMaster.getLobbyPlayer();
|
||||||
controller = master.createMindSlaveController(mindSlaveMaster, this);
|
controller = master.createMindSlaveController(mindSlaveMaster, this);
|
||||||
game.fireEvent(new GameEventPlayerControl(this, oldLobbyPlayer, getLobbyPlayer()));
|
game.fireEvent(new GameEventPlayerControl(this, oldLobbyPlayer, oldController, getLobbyPlayer(), controller));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
controller = controllerCreator;
|
controller = controllerCreator;
|
||||||
game.fireEvent(new GameEventPlayerControl(this, getLobbyPlayer(), null));
|
game.fireEvent(new GameEventPlayerControl(this, getLobbyPlayer(), controller, null, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardShields;
|
import forge.game.card.CardShields;
|
||||||
|
import forge.game.card.CardView;
|
||||||
import forge.game.card.CounterType;
|
import forge.game.card.CounterType;
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.cost.Cost;
|
import forge.game.cost.Cost;
|
||||||
@@ -140,6 +141,8 @@ public abstract class PlayerController {
|
|||||||
reveal(cards, zone, owner, null);
|
reveal(cards, zone, owner, null);
|
||||||
}
|
}
|
||||||
public abstract void reveal(CardCollectionView cards, ZoneType zone, Player owner, String messagePrefix);
|
public abstract void reveal(CardCollectionView cards, ZoneType zone, Player owner, String messagePrefix);
|
||||||
|
public abstract void reveal(Collection<CardView> cards, ZoneType zone, PlayerView owner, String messagePrefix);
|
||||||
|
|
||||||
/** Shows message to player to reveal chosen cardName, creatureType, number etc. AI must analyze API to understand what that is */
|
/** Shows message to player to reveal chosen cardName, creatureType, number etc. AI must analyze API to understand what that is */
|
||||||
public abstract void notifyOfValue(SpellAbility saSource, GameObject realtedTarget, String value);
|
public abstract void notifyOfValue(SpellAbility saSource, GameObject realtedTarget, String value);
|
||||||
public abstract ImmutablePair<CardCollection, CardCollection> arrangeForScry(CardCollection topN);
|
public abstract ImmutablePair<CardCollection, CardCollection> arrangeForScry(CardCollection topN);
|
||||||
|
|||||||
@@ -21,8 +21,9 @@ import forge.trackable.TrackableProperty;
|
|||||||
import forge.trackable.Tracker;
|
import forge.trackable.Tracker;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
|
|
||||||
|
|
||||||
public class PlayerView extends GameEntityView {
|
public class PlayerView extends GameEntityView {
|
||||||
|
private static final long serialVersionUID = 7005892740909549086L;
|
||||||
|
|
||||||
public static PlayerView get(Player p) {
|
public static PlayerView get(Player p) {
|
||||||
return p == null ? null : p.getView();
|
return p == null ? null : p.getView();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,12 +147,23 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
view0 = new SpellAbilityView(this);
|
view0 = new SpellAbilityView(this);
|
||||||
}
|
}
|
||||||
view = view0;
|
view = view0;
|
||||||
|
if (hostCard != null && hostCard.getGame() != null) {
|
||||||
|
hostCard.getGame().addSpellAbility(id, this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getId() {
|
public int getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return getId();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
return obj instanceof SpellAbility && this.id == ((SpellAbility) obj).id;
|
||||||
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setHostCard(final Card c) {
|
public void setHostCard(final Card c) {
|
||||||
@@ -1247,6 +1258,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public SpellAbilityView getView() {
|
public SpellAbilityView getView() {
|
||||||
|
view.updateHostCard(this);
|
||||||
|
view.updateDescription(this);
|
||||||
|
view.updateCanPlay(this);
|
||||||
|
view.updatePromptIfOnlyPossibleAbility(this);
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,8 +5,9 @@ import forge.trackable.TrackableCollection;
|
|||||||
import forge.trackable.TrackableObject;
|
import forge.trackable.TrackableObject;
|
||||||
import forge.trackable.TrackableProperty;
|
import forge.trackable.TrackableProperty;
|
||||||
|
|
||||||
|
|
||||||
public class SpellAbilityView extends TrackableObject {
|
public class SpellAbilityView extends TrackableObject {
|
||||||
|
private static final long serialVersionUID = 2514234930798754769L;
|
||||||
|
|
||||||
public static SpellAbilityView get(SpellAbility spab) {
|
public static SpellAbilityView get(SpellAbility spab) {
|
||||||
return spab == null ? null : spab.getView();
|
return spab == null ? null : spab.getView();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,8 +7,9 @@ import forge.trackable.TrackableObject;
|
|||||||
import forge.trackable.TrackableProperty;
|
import forge.trackable.TrackableProperty;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
|
|
||||||
|
|
||||||
public class StackItemView extends TrackableObject {
|
public class StackItemView extends TrackableObject {
|
||||||
|
private static final long serialVersionUID = 6733415646691356052L;
|
||||||
|
|
||||||
public static StackItemView get(SpellAbilityStackInstance si) {
|
public static StackItemView get(SpellAbilityStackInstance si) {
|
||||||
return si == null ? null : si.getView();
|
return si == null ? null : si.getView();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,16 @@
|
|||||||
*/
|
*/
|
||||||
package forge.game.zone;
|
package forge.game.zone;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Stack;
|
||||||
|
import java.util.concurrent.LinkedBlockingDeque;
|
||||||
|
|
||||||
import com.esotericsoftware.minlog.Log;
|
import com.esotericsoftware.minlog.Log;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
@@ -45,14 +55,17 @@ import forge.game.player.PlayerController.ManaPaymentPurpose;
|
|||||||
import forge.game.replacement.ReplacementEffect;
|
import forge.game.replacement.ReplacementEffect;
|
||||||
import forge.game.replacement.ReplacementHandler;
|
import forge.game.replacement.ReplacementHandler;
|
||||||
import forge.game.replacement.ReplacementLayer;
|
import forge.game.replacement.ReplacementLayer;
|
||||||
import forge.game.spellability.*;
|
import forge.game.spellability.Ability;
|
||||||
|
import forge.game.spellability.AbilityStatic;
|
||||||
|
import forge.game.spellability.OptionalCost;
|
||||||
|
import forge.game.spellability.Spell;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.spellability.SpellAbilityStackInstance;
|
||||||
|
import forge.game.spellability.TargetChoices;
|
||||||
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* MagicStack class.
|
* MagicStack class.
|
||||||
@@ -518,6 +531,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
|||||||
setResolving(false);
|
setResolving(false);
|
||||||
unfreezeStack();
|
unfreezeStack();
|
||||||
sa.resetOnceResolved();
|
sa.resetOnceResolved();
|
||||||
|
game.updateStackForView();
|
||||||
|
|
||||||
//game.getAction().checkStaticAbilities();
|
//game.getAction().checkStaticAbilities();
|
||||||
game.getPhaseHandler().onStackResolved();
|
game.getPhaseHandler().onStackResolved();
|
||||||
|
|||||||
@@ -5,6 +5,8 @@ import java.util.Collection;
|
|||||||
import forge.util.FCollection;
|
import forge.util.FCollection;
|
||||||
|
|
||||||
public class TrackableCollection<T extends TrackableObject> extends FCollection<T> {
|
public class TrackableCollection<T extends TrackableObject> extends FCollection<T> {
|
||||||
|
private static final long serialVersionUID = 1528674215758232314L;
|
||||||
|
|
||||||
public TrackableCollection() {
|
public TrackableCollection() {
|
||||||
}
|
}
|
||||||
public TrackableCollection(T e) {
|
public TrackableCollection(T e) {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package forge.trackable;
|
package forge.trackable;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.EnumMap;
|
import java.util.EnumMap;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -8,7 +9,9 @@ import java.util.Set;
|
|||||||
import forge.game.IIdentifiable;
|
import forge.game.IIdentifiable;
|
||||||
|
|
||||||
//base class for objects that can be tracked and synced between game server and GUI
|
//base class for objects that can be tracked and synced between game server and GUI
|
||||||
public abstract class TrackableObject implements IIdentifiable {
|
public abstract class TrackableObject implements IIdentifiable, Serializable {
|
||||||
|
private static final long serialVersionUID = 7386836745378571056L;
|
||||||
|
|
||||||
private final int id;
|
private final int id;
|
||||||
protected final transient Tracker tracker;
|
protected final transient Tracker tracker;
|
||||||
private final Map<TrackableProperty, Object> props;
|
private final Map<TrackableProperty, Object> props;
|
||||||
@@ -60,6 +63,30 @@ public abstract class TrackableObject implements IIdentifiable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy to this Trackable object the first object of the provided iterator
|
||||||
|
* whose id matches.
|
||||||
|
*
|
||||||
|
* @see TrackableObject#copy(TrackableObject)
|
||||||
|
*/
|
||||||
|
public final void copy(final Iterable<? extends TrackableObject> others) {
|
||||||
|
for (final TrackableObject other : others) {
|
||||||
|
if (this.equals(other)) {
|
||||||
|
copy(other);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy all properties of another Trackable object to this object.
|
||||||
|
*/
|
||||||
|
public final void copy(final TrackableObject other) {
|
||||||
|
for (final TrackableProperty prop : other.props.keySet()) {
|
||||||
|
set(prop, other.get(prop));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//use when updating collection type properties with using set
|
//use when updating collection type properties with using set
|
||||||
protected final void flagAsChanged(final TrackableProperty key) {
|
protected final void flagAsChanged(final TrackableProperty key) {
|
||||||
changedProps.add(key);
|
changedProps.add(key);
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ public enum TrackableProperty {
|
|||||||
MatchOver(TrackableTypes.BooleanType),
|
MatchOver(TrackableTypes.BooleanType),
|
||||||
NumGamesInMatch(TrackableTypes.IntegerType),
|
NumGamesInMatch(TrackableTypes.IntegerType),
|
||||||
NumPlayedGamesInMatch(TrackableTypes.IntegerType),
|
NumPlayedGamesInMatch(TrackableTypes.IntegerType),
|
||||||
|
Stack(TrackableTypes.StackItemViewListType),
|
||||||
StormCount(TrackableTypes.IntegerType),
|
StormCount(TrackableTypes.IntegerType),
|
||||||
GameOver(TrackableTypes.BooleanType),
|
GameOver(TrackableTypes.BooleanType),
|
||||||
PoisonCountersToLose(TrackableTypes.IntegerType),
|
PoisonCountersToLose(TrackableTypes.IntegerType),
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ import forge.card.ColorSet;
|
|||||||
import forge.card.mana.ManaCost;
|
import forge.card.mana.ManaCost;
|
||||||
import forge.game.GameEntityView;
|
import forge.game.GameEntityView;
|
||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
import forge.game.card.CounterType;
|
|
||||||
import forge.game.card.CardView.CardStateView;
|
import forge.game.card.CardView.CardStateView;
|
||||||
|
import forge.game.card.CounterType;
|
||||||
import forge.game.keyword.KeywordCollection.KeywordCollectionView;
|
import forge.game.keyword.KeywordCollection.KeywordCollectionView;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.StackItemView;
|
import forge.game.spellability.StackItemView;
|
||||||
@@ -284,6 +284,22 @@ public class TrackableTypes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
public static final TrackableType<TrackableCollection<StackItemView>> StackItemViewListType = new TrackableType<TrackableCollection<StackItemView>>() {
|
||||||
|
@Override
|
||||||
|
protected TrackableCollection<StackItemView> getDefaultValue() {
|
||||||
|
return new TrackableCollection<StackItemView>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TrackableCollection<StackItemView> deserialize(TrackableDeserializer td, TrackableCollection<StackItemView> oldValue) {
|
||||||
|
return td.readCollection(oldValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void serialize(TrackableSerializer ts, TrackableCollection<StackItemView> value) {
|
||||||
|
ts.write(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
public static final TrackableType<ManaCost> ManaCostType = new TrackableType<ManaCost>() {
|
public static final TrackableType<ManaCost> ManaCostType = new TrackableType<ManaCost>() {
|
||||||
@Override
|
@Override
|
||||||
public ManaCost getDefaultValue() {
|
public ManaCost getDefaultValue() {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package forge.util;
|
package forge.util;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -12,7 +13,9 @@ import java.util.ListIterator;
|
|||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
//base class for a collection with quick lookup and that maintains order
|
//base class for a collection with quick lookup and that maintains order
|
||||||
public class FCollection<T> implements List<T>, Set<T>, FCollectionView<T>, Cloneable {
|
public class FCollection<T> implements List<T>, Set<T>, FCollectionView<T>, Cloneable, Serializable {
|
||||||
|
private static final long serialVersionUID = -1664555336364294106L;
|
||||||
|
|
||||||
private final HashSet<T> set = new HashSet<T>();
|
private final HashSet<T> set = new HashSet<T>();
|
||||||
private final LinkedList<T> list = new LinkedList<T>();
|
private final LinkedList<T> list = new LinkedList<T>();
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import org.apache.commons.lang3.StringUtils;
|
|||||||
|
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
|
|
||||||
public class MessageUtil {
|
public class MessageUtil {
|
||||||
@@ -17,6 +18,14 @@ public class MessageUtil {
|
|||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String formatMessage(String message, PlayerView player, Object related) {
|
||||||
|
if (related instanceof Player && message.indexOf("{player") >= 0) {
|
||||||
|
String noun = mayBeYou(player, related);
|
||||||
|
message = message.replace("{player}", noun).replace("{player's}", Lang.getPossesive(noun));
|
||||||
|
}
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
// These are not much related to PlayerController
|
// These are not much related to PlayerController
|
||||||
public static String formatNotificationMessage(SpellAbility sa, Player player, GameObject target, String value) {
|
public static String formatNotificationMessage(SpellAbility sa, Player player, GameObject target, String value) {
|
||||||
if (sa == null || sa.getApi() == null || sa.getHostCard() == null) {
|
if (sa == null || sa.getApi() == null || sa.getHostCard() == null) {
|
||||||
@@ -50,4 +59,7 @@ public class MessageUtil {
|
|||||||
public static String mayBeYou(Player player, Object what) {
|
public static String mayBeYou(Player player, Object what) {
|
||||||
return what == null ? "(null)" : what == player ? "you" : what.toString();
|
return what == null ? "(null)" : what == player ? "you" : what.toString();
|
||||||
}
|
}
|
||||||
|
public static String mayBeYou(PlayerView player, Object what) {
|
||||||
|
return what == null ? "(null)" : what == player ? "you" : what.toString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import forge.download.GuiDownloader;
|
|||||||
import forge.error.BugReportDialog;
|
import forge.error.BugReportDialog;
|
||||||
import forge.gui.BoxedProductCardListViewer;
|
import forge.gui.BoxedProductCardListViewer;
|
||||||
import forge.gui.CardListViewer;
|
import forge.gui.CardListViewer;
|
||||||
import forge.gui.FNetOverlay;
|
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
import forge.gui.framework.FScreen;
|
import forge.gui.framework.FScreen;
|
||||||
import forge.interfaces.IGuiBase;
|
import forge.interfaces.IGuiBase;
|
||||||
@@ -280,9 +279,4 @@ public class GuiDesktop implements IGuiBase {
|
|||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void netMessage(final String origin, final String message) {
|
|
||||||
FNetOverlay.SINGLETON_INSTANCE.showUp("");
|
|
||||||
FNetOverlay.SINGLETON_INSTANCE.addMessage(origin, message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -135,9 +135,14 @@ public enum FNetOverlay {
|
|||||||
getPanel().validate();
|
getPanel().validate();
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleDateFormat inFormat = new SimpleDateFormat("HH:mm:ss");
|
private final static SimpleDateFormat inFormat = new SimpleDateFormat("HH:mm:ss");
|
||||||
public void addMessage(String origin, String message) {
|
public void addMessage(final String origin, final String message) {
|
||||||
String toAdd = String.format("%n[%s] %s: %s", inFormat.format(new Date()), origin, 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);
|
txtLog.append(toAdd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,39 +2,17 @@ package forge.screens.home;
|
|||||||
|
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
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 java.util.Vector;
|
||||||
|
|
||||||
import javax.swing.SwingUtilities;
|
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.Deck;
|
||||||
import forge.deck.DeckFormat;
|
|
||||||
import forge.deck.DeckSection;
|
|
||||||
import forge.deck.DeckType;
|
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.CardCollections;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.player.GamePlayerUtil;
|
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.toolbox.FList;
|
import forge.toolbox.FList;
|
||||||
import forge.toolbox.FOptionPane;
|
|
||||||
import forge.util.Aggregates;
|
|
||||||
import forge.util.storage.IStorage;
|
|
||||||
|
|
||||||
public class CLobby {
|
public class CLobby {
|
||||||
|
|
||||||
@@ -118,7 +96,6 @@ public class CLobby {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// General updates when switching back to this view
|
// General updates when switching back to this view
|
||||||
view.updatePlayersFromPrefs();
|
|
||||||
view.getBtnStart().requestFocusInWindow();
|
view.getBtnStart().requestFocusInWindow();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -134,14 +111,6 @@ public class CLobby {
|
|||||||
view.getDeckChooser(6).initialize(FPref.CONSTRUCTED_P7_DECK_STATE, DeckType.COLOR_DECK);
|
view.getDeckChooser(6).initialize(FPref.CONSTRUCTED_P7_DECK_STATE, DeckType.COLOR_DECK);
|
||||||
view.getDeckChooser(7).initialize(FPref.CONSTRUCTED_P8_DECK_STATE, DeckType.COLOR_DECK);
|
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();
|
final ForgePreferences prefs = FModel.getPreferences();
|
||||||
// Checkbox event handling
|
// Checkbox event handling
|
||||||
view.getCbSingletons().addActionListener(new ActionListener() {
|
view.getCbSingletons().addActionListener(new ActionListener() {
|
||||||
@@ -165,208 +134,4 @@ public class CLobby {
|
|||||||
view.getCbArtifacts().setSelected(prefs.getPrefBoolean(FPref.DECKGEN_ARTIFACTS));
|
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.FocusAdapter;
|
||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.swing.ButtonGroup;
|
import javax.swing.ButtonGroup;
|
||||||
import javax.swing.JCheckBoxMenuItem;
|
import javax.swing.JCheckBoxMenuItem;
|
||||||
@@ -17,7 +19,9 @@ import net.miginfocom.swing.MigLayout;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
import forge.AIOption;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.UiCommand;
|
import forge.UiCommand;
|
||||||
import forge.assets.FSkinProp;
|
import forge.assets.FSkinProp;
|
||||||
@@ -25,6 +29,7 @@ import forge.deck.DeckSection;
|
|||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.gui.framework.FScreen;
|
import forge.gui.framework.FScreen;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
|
import forge.match.LobbySlot;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.net.game.LobbySlotType;
|
import forge.net.game.LobbySlotType;
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
@@ -32,7 +37,6 @@ import forge.properties.ForgePreferences.FPref;
|
|||||||
import forge.screens.deckeditor.CDeckEditorUI;
|
import forge.screens.deckeditor.CDeckEditorUI;
|
||||||
import forge.screens.deckeditor.controllers.CEditorCommander;
|
import forge.screens.deckeditor.controllers.CEditorCommander;
|
||||||
import forge.screens.deckeditor.controllers.CEditorVariant;
|
import forge.screens.deckeditor.controllers.CEditorVariant;
|
||||||
import forge.screens.home.VLobby.LobbyType;
|
|
||||||
import forge.screens.home.sanctioned.AvatarSelector;
|
import forge.screens.home.sanctioned.AvatarSelector;
|
||||||
import forge.toolbox.FComboBox;
|
import forge.toolbox.FComboBox;
|
||||||
import forge.toolbox.FComboBoxWrapper;
|
import forge.toolbox.FComboBoxWrapper;
|
||||||
@@ -53,17 +57,16 @@ public class PlayerPanel extends FPanel {
|
|||||||
private final static ForgePreferences prefs = FModel.getPreferences();
|
private final static ForgePreferences prefs = FModel.getPreferences();
|
||||||
private static final SkinColor unfocusedPlayerOverlay = FSkin.getColor(FSkin.Colors.CLR_OVERLAY).alphaColor(120);
|
private static final SkinColor unfocusedPlayerOverlay = FSkin.getColor(FSkin.Colors.CLR_OVERLAY).alphaColor(120);
|
||||||
|
|
||||||
|
private LobbySlotType type;
|
||||||
private final int index;
|
private final int index;
|
||||||
private final LobbyType lobbyType;
|
private String playerName = StringUtils.EMPTY;
|
||||||
|
private boolean mayEdit, mayControl, mayRemove;
|
||||||
private LobbySlotType type = LobbySlotType.LOCAL;
|
|
||||||
private boolean editableForClient;
|
|
||||||
|
|
||||||
private final FLabel nameRandomiser;
|
private final FLabel nameRandomiser;
|
||||||
private final FLabel avatarLabel = new FLabel.Builder().opaque(true).hoverable(true).iconScaleFactor(0.99f).iconInBackground(true).build();
|
private final FLabel avatarLabel = new FLabel.Builder().opaque(true).hoverable(true).iconScaleFactor(0.99f).iconInBackground(true).build();
|
||||||
private int avatarIndex;
|
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 radioHuman;
|
||||||
private FRadioButton radioAi;
|
private FRadioButton radioAi;
|
||||||
private JCheckBoxMenuItem radioAiUseSimulation;
|
private JCheckBoxMenuItem radioAiUseSimulation;
|
||||||
@@ -78,7 +81,6 @@ public class PlayerPanel extends FPanel {
|
|||||||
|
|
||||||
private final String variantBtnConstraints = "height 30px, hidemode 3";
|
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 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 scmDeckEditor = new FLabel.ButtonBuilder().text("Scheme Deck Editor").build();
|
||||||
private final FLabel scmLabel;
|
private final FLabel scmLabel;
|
||||||
@@ -95,26 +97,25 @@ public class PlayerPanel extends FPanel {
|
|||||||
private final FLabel vgdLabel;
|
private final FLabel vgdLabel;
|
||||||
|
|
||||||
private final VLobby lobby;
|
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();
|
super();
|
||||||
|
|
||||||
this.lobby = lobby;
|
this.lobby = lobby;
|
||||||
|
this.index = index;
|
||||||
|
this.mayEdit = mayEdit;
|
||||||
|
this.mayControl = mayControl;
|
||||||
|
|
||||||
this.deckLabel = lobby.newLabel("Deck:");
|
this.deckLabel = lobby.newLabel("Deck:");
|
||||||
this.scmLabel = lobby.newLabel("Scheme deck:");
|
this.scmLabel = lobby.newLabel("Scheme deck:");
|
||||||
this.cmdLabel = lobby.newLabel("Commander deck:");
|
this.cmdLabel = lobby.newLabel("Commander deck:");
|
||||||
this.pchLabel = lobby.newLabel("Planar deck:");
|
this.pchLabel = lobby.newLabel("Planar deck:");
|
||||||
this.vgdLabel = lobby.newLabel("Vanguard:");
|
this.vgdLabel = lobby.newLabel("Vanguard:");
|
||||||
|
|
||||||
this.index = index;
|
|
||||||
this.lobbyType = lobbyType;
|
|
||||||
this.playerIsArchenemy = index == 0;
|
|
||||||
|
|
||||||
setLayout(new MigLayout("insets 10px, gap 5px"));
|
setLayout(new MigLayout("insets 10px, gap 5px"));
|
||||||
|
|
||||||
// Add a button to players 3+ (or if server) to remove them from the setup
|
// Add a button to players 3+ (or if server) to remove them from the setup
|
||||||
closeBtn = createCloseButton();
|
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();
|
createAvatar();
|
||||||
this.add(avatarLabel, "spany 2, width 80px, height 80px");
|
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");
|
this.add(lobby.newLabel("Team:"), "w 40px, h 30px");
|
||||||
populateTeamsComboBoxes();
|
populateTeamsComboBoxes();
|
||||||
|
|
||||||
|
// Set these before action listeners are added
|
||||||
|
this.setTeam(slot == null ? index : slot.getTeam());
|
||||||
|
this.setIsArchenemy(slot != null && slot.isArchenemy());
|
||||||
|
|
||||||
teamComboBox.addActionListener(teamListener);
|
teamComboBox.addActionListener(teamListener);
|
||||||
aeTeamComboBox.addActionListener(teamListener);
|
aeTeamComboBox.addActionListener(teamListener);
|
||||||
teamComboBox.addTo(this, variantBtnConstraints + ", pushx, growx, gaptop 5px");
|
teamComboBox.addTo(this, variantBtnConstraints + ", pushx, growx, gaptop 5px");
|
||||||
aeTeamComboBox.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");
|
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");
|
this.add(vgdSelectorBtn, variantBtnConstraints + ", cell 2 6, sx 4, growx, wrap");
|
||||||
|
|
||||||
addHandlersToVariantsControls();
|
addHandlersToVariantsControls();
|
||||||
updateVariantControlsVisibility();
|
|
||||||
|
|
||||||
this.addMouseListener(new FMouseAdapter() {
|
this.addMouseListener(new FMouseAdapter() {
|
||||||
@Override public final void onLeftMouseDown(final MouseEvent e) {
|
@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();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void update() {
|
void update() {
|
||||||
if (type != LobbySlotType.REMOTE) {
|
avatarLabel.setEnabled(mayEdit);
|
||||||
if (radioHuman.isSelected()) {
|
avatarLabel.setIcon(FSkin.getAvatars().get(Integer.valueOf(type == LobbySlotType.OPEN ? -1 : avatarIndex)));
|
||||||
type = LobbySlotType.LOCAL;
|
avatarLabel.repaintSelf();
|
||||||
} else if (radioAi.isSelected()) {
|
|
||||||
type = LobbySlotType.AI;
|
txtPlayerName.setEnabled(mayEdit);
|
||||||
} else if (radioOpen.isSelected()) {
|
txtPlayerName.setText(type == LobbySlotType.OPEN ? StringUtils.EMPTY : playerName);
|
||||||
type = LobbySlotType.OPEN;
|
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 ||
|
radioHuman.setSelected(type == LobbySlotType.LOCAL);
|
||||||
(lobbyType == LobbyType.SERVER && (type == LobbySlotType.LOCAL || type == LobbySlotType.AI)) ||
|
radioAi.setSelected(type == LobbySlotType.AI);
|
||||||
(lobbyType == LobbyType.CLIENT && editableForClient);
|
radioOpen.setSelected(type == LobbySlotType.OPEN);
|
||||||
avatarLabel.setEnabled(isEditable);
|
|
||||||
txtPlayerName.setEnabled(isEditable);
|
|
||||||
nameRandomiser.setEnabled(isEditable);
|
|
||||||
deckLabel.setVisible(isEditable);
|
|
||||||
deckBtn.setVisible(isEditable);
|
|
||||||
|
|
||||||
final boolean hasSlotControls = lobbyType == LobbyType.LOCAL || (lobbyType == LobbyType.SERVER && type != LobbySlotType.REMOTE);
|
updateVariantControlsVisibility();
|
||||||
closeBtn.setVisible(hasSlotControls);
|
|
||||||
radioAi.setVisible(hasSlotControls);
|
|
||||||
radioHuman.setVisible(hasSlotControls);
|
|
||||||
radioOpen.setVisible(hasSlotControls && lobbyType == LobbyType.SERVER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final FMouseAdapter radioMouseAdapter = new FMouseAdapter() {
|
private final FMouseAdapter radioMouseAdapter(final FRadioButton source, final LobbySlotType type) {
|
||||||
|
return new FMouseAdapter() {
|
||||||
@Override public final void onLeftClick(final MouseEvent e) {
|
@Override public final void onLeftClick(final MouseEvent e) {
|
||||||
|
if (!source.isEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setType(type);
|
||||||
|
lobby.firePlayerChangeListener(index);
|
||||||
avatarLabel.requestFocusInWindow();
|
avatarLabel.requestFocusInWindow();
|
||||||
lobby.updateVanguardList(index);
|
lobby.updateVanguardList(index);
|
||||||
update();
|
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() {
|
private FocusAdapter nameFocusListener = new FocusAdapter() {
|
||||||
@Override
|
@Override
|
||||||
public void focusGained(FocusEvent e) {
|
public void focusGained(FocusEvent e) {
|
||||||
@@ -226,7 +248,8 @@ public class PlayerPanel extends FPanel {
|
|||||||
prefs.setPref(FPref.PLAYER_NAME, newName);
|
prefs.setPref(FPref.PLAYER_NAME, newName);
|
||||||
prefs.save();
|
prefs.save();
|
||||||
}
|
}
|
||||||
lobby.firePlayerChangeListener();
|
lobby.firePlayerChangeListener(index);
|
||||||
|
lobby.update();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -247,10 +270,10 @@ public class PlayerPanel extends FPanel {
|
|||||||
|
|
||||||
final FLabel avatar = (FLabel)e.getSource();
|
final FLabel avatar = (FLabel)e.getSource();
|
||||||
|
|
||||||
PlayerPanel.this.lobby.changePlayerFocus(index);
|
lobby.changePlayerFocus(index);
|
||||||
avatar.requestFocusInWindow();
|
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()) {
|
for (final FLabel lbl : aSel.getSelectables()) {
|
||||||
lbl.setCommand(new UiCommand() {
|
lbl.setCommand(new UiCommand() {
|
||||||
@Override
|
@Override
|
||||||
@@ -265,64 +288,35 @@ public class PlayerPanel extends FPanel {
|
|||||||
aSel.dispose();
|
aSel.dispose();
|
||||||
|
|
||||||
if (index < 2) {
|
if (index < 2) {
|
||||||
PlayerPanel.this.lobby.updateAvatarPrefs();
|
lobby.updateAvatarPrefs();
|
||||||
}
|
}
|
||||||
|
|
||||||
lobby.firePlayerChangeListener();
|
lobby.firePlayerChangeListener(index);
|
||||||
}
|
}
|
||||||
@Override public final void onRightClick(final MouseEvent e) {
|
@Override public final void onRightClick(final MouseEvent e) {
|
||||||
if (!avatarLabel.isEnabled()) {
|
if (!avatarLabel.isEnabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerPanel.this.lobby.changePlayerFocus(index);
|
lobby.changePlayerFocus(index);
|
||||||
avatarLabel.requestFocusInWindow();
|
avatarLabel.requestFocusInWindow();
|
||||||
|
|
||||||
setRandomAvatar();
|
setRandomAvatar();
|
||||||
|
|
||||||
if (index < 2) {
|
if (index < 2) {
|
||||||
PlayerPanel.this.lobby.updateAvatarPrefs();
|
lobby.updateAvatarPrefs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public void updateVariantControlsVisibility() {
|
private void updateVariantControlsVisibility() {
|
||||||
boolean isCommanderApplied = false;
|
boolean isCommanderApplied = mayEdit && (lobby.hasVariant(GameType.Commander) || lobby.hasVariant(GameType.TinyLeaders));
|
||||||
boolean isPlanechaseApplied = false;
|
boolean isPlanechaseApplied = mayEdit && lobby.hasVariant(GameType.Planechase);
|
||||||
boolean isVanguardApplied = false;
|
boolean isVanguardApplied = mayEdit && lobby.hasVariant(GameType.Vanguard);
|
||||||
boolean isArchenemyApplied = false;
|
boolean isArchenemyApplied = mayEdit && lobby.hasVariant(GameType.Archenemy);
|
||||||
boolean archenemyVisiblity = false;
|
boolean archenemyVisiblity = mayEdit && lobby.hasVariant(GameType.ArchenemyRumble) || (isArchenemyApplied && isArchenemy());
|
||||||
boolean isDeckBuildingAllowed = true;
|
// Commander deck building replaces normal one, so hide it
|
||||||
|
boolean isDeckBuildingAllowed = mayEdit && !isCommanderApplied && !lobby.hasVariant(GameType.MomirBasic);
|
||||||
for (final GameType variant : lobby.getAppliedVariants()) {
|
|
||||||
switch (variant) {
|
|
||||||
case Archenemy:
|
|
||||||
isArchenemyApplied = true;
|
|
||||||
if (playerIsArchenemy) {
|
|
||||||
archenemyVisiblity = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ArchenemyRumble:
|
|
||||||
archenemyVisiblity = true;
|
|
||||||
break;
|
|
||||||
case Commander:
|
|
||||||
case TinyLeaders:
|
|
||||||
isCommanderApplied = true;
|
|
||||||
isDeckBuildingAllowed = false; //Commander deck replaces basic deck, so hide that
|
|
||||||
break;
|
|
||||||
case Planechase:
|
|
||||||
isPlanechaseApplied = true;
|
|
||||||
break;
|
|
||||||
case Vanguard:
|
|
||||||
isVanguardApplied = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (variant.isAutoGenerated()) {
|
|
||||||
isDeckBuildingAllowed = false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deckLabel.setVisible(isDeckBuildingAllowed);
|
deckLabel.setVisible(isDeckBuildingAllowed);
|
||||||
deckBtn.setVisible(isDeckBuildingAllowed);
|
deckBtn.setVisible(isDeckBuildingAllowed);
|
||||||
@@ -336,7 +330,6 @@ public class PlayerPanel extends FPanel {
|
|||||||
|
|
||||||
teamComboBox.setVisible(!isArchenemyApplied);
|
teamComboBox.setVisible(!isArchenemyApplied);
|
||||||
aeTeamComboBox.setVisible(isArchenemyApplied);
|
aeTeamComboBox.setVisible(isArchenemyApplied);
|
||||||
aeTeamComboBox.setEnabled(!(isArchenemyApplied && playerIsArchenemy));
|
|
||||||
|
|
||||||
pchDeckSelectorBtn.setVisible(isPlanechaseApplied);
|
pchDeckSelectorBtn.setVisible(isPlanechaseApplied);
|
||||||
pchDeckEditor.setVisible(isPlanechaseApplied);
|
pchDeckEditor.setVisible(isPlanechaseApplied);
|
||||||
@@ -367,30 +360,53 @@ public class PlayerPanel extends FPanel {
|
|||||||
return type == LobbySlotType.AI;
|
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();
|
return radioAi.isSelected() && radioAiUseSimulation.isSelected();
|
||||||
}
|
}
|
||||||
|
public void setUseAiSimulation(final boolean useSimulation) {
|
||||||
|
radioAi.setSelected(useSimulation);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isLocal() {
|
public boolean isLocal() {
|
||||||
return type == LobbySlotType.LOCAL;
|
return type == LobbySlotType.LOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isArchenemy() {
|
public boolean isArchenemy() {
|
||||||
return playerIsArchenemy;
|
return aeTeamComboBox.getSelectedIndex() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRemote(final boolean remote) {
|
public void setType(final LobbySlotType type) {
|
||||||
if (remote) {
|
this.type = type;
|
||||||
type = LobbySlotType.REMOTE;
|
switch (type) {
|
||||||
} else {
|
case LOCAL:
|
||||||
|
radioHuman.setSelected(true);
|
||||||
|
break;
|
||||||
|
case AI:
|
||||||
|
radioAi.setSelected(true);
|
||||||
|
break;
|
||||||
|
case OPEN:
|
||||||
radioOpen.setSelected(true);
|
radioOpen.setSelected(true);
|
||||||
type = LobbySlotType.OPEN;
|
break;
|
||||||
|
case REMOTE:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEditableForClient(final boolean editable) {
|
public void setRemote(final boolean remote) {
|
||||||
editableForClient = editable;
|
if (remote) {
|
||||||
|
setType(LobbySlotType.REMOTE);
|
||||||
|
radioHuman.setSelected(false);
|
||||||
|
radioAi.setSelected(false);
|
||||||
|
radioOpen.setSelected(false);
|
||||||
|
} else {
|
||||||
|
setType(LobbySlotType.OPEN);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVanguardButtonText(String text) {
|
public void setVanguardButtonText(String text) {
|
||||||
@@ -408,77 +424,46 @@ public class PlayerPanel extends FPanel {
|
|||||||
private void populateTeamsComboBoxes() {
|
private void populateTeamsComboBoxes() {
|
||||||
aeTeamComboBox.addItem("Archenemy");
|
aeTeamComboBox.addItem("Archenemy");
|
||||||
aeTeamComboBox.addItem("Heroes");
|
aeTeamComboBox.addItem("Heroes");
|
||||||
aeTeamComboBox.setSelectedIndex(lobby.getArchenemyTeams().get(index) - 1);
|
|
||||||
aeTeamComboBox.setEnabled(playerIsArchenemy);
|
|
||||||
|
|
||||||
for (int i = 1; i <= VLobby.MAX_PLAYERS; i++) {
|
for (int i = 1; i <= VLobby.MAX_PLAYERS; i++) {
|
||||||
teamComboBox.addItem(i);
|
teamComboBox.addItem(i);
|
||||||
}
|
}
|
||||||
teamComboBox.setSelectedIndex(lobby.getTeams().get(index) - 1);
|
|
||||||
teamComboBox.setEnabled(true);
|
teamComboBox.setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ActionListener teamListener = new ActionListener() {
|
private ActionListener teamListener = new ActionListener() {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override public final void actionPerformed(final ActionEvent e) {
|
||||||
public void actionPerformed(ActionEvent e) {
|
final FComboBox<Object> cb = (FComboBox<Object>) e.getSource();
|
||||||
FComboBox<Object> cb = (FComboBox<Object>)e.getSource();
|
|
||||||
cb.requestFocusInWindow();
|
cb.requestFocusInWindow();
|
||||||
Object selection = cb.getSelectedItem();
|
final Object selection = cb.getSelectedItem();
|
||||||
|
|
||||||
if (null == selection) {
|
if (null != selection) {
|
||||||
return;
|
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
|
* @param index
|
||||||
*/
|
*/
|
||||||
private void addHandlersToVariantsControls() {
|
private void addHandlersToVariantsControls() {
|
||||||
// Archenemy buttons
|
// Archenemy buttons
|
||||||
scmDeckSelectorBtn.setCommand(new Runnable() {
|
scmDeckSelectorBtn.setCommand(new Runnable() {
|
||||||
@Override
|
@Override public final void run() {
|
||||||
public void run() {
|
lobby.setCurrentGameMode(lobby.getVntArchenemy().isSelected() ? GameType.Archenemy : GameType.ArchenemyRumble);
|
||||||
PlayerPanel.this.lobby.setCurrentGameMode(PlayerPanel.this.lobby.getVntArchenemy().isSelected() ? GameType.Archenemy : GameType.ArchenemyRumble);
|
|
||||||
scmDeckSelectorBtn.requestFocusInWindow();
|
scmDeckSelectorBtn.requestFocusInWindow();
|
||||||
PlayerPanel.this.lobby.changePlayerFocus(index, PlayerPanel.this.lobby.getCurrentGameMode());
|
lobby.changePlayerFocus(index);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
scmDeckEditor.setCommand(new UiCommand() {
|
scmDeckEditor.setCommand(new UiCommand() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
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>() {
|
Predicate<PaperCard> predSchemes = new Predicate<PaperCard>() {
|
||||||
@Override
|
@Override public final boolean apply(final PaperCard arg0) {
|
||||||
public boolean apply(PaperCard arg0) {
|
|
||||||
return arg0.getRules().getType().isScheme();
|
return arg0.getRules().getType().isScheme();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -493,16 +478,16 @@ public class PlayerPanel extends FPanel {
|
|||||||
cmdDeckSelectorBtn.setCommand(new Runnable() {
|
cmdDeckSelectorBtn.setCommand(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
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();
|
cmdDeckSelectorBtn.requestFocusInWindow();
|
||||||
PlayerPanel.this.lobby.changePlayerFocus(index, PlayerPanel.this.lobby.getCurrentGameMode());
|
lobby.changePlayerFocus(index);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cmdDeckEditor.setCommand(new UiCommand() {
|
cmdDeckEditor.setCommand(new UiCommand() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
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);
|
Singletons.getControl().setCurrentScreen(FScreen.DECK_EDITOR_COMMANDER);
|
||||||
CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(new CEditorCommander(CDeckEditorUI.SINGLETON_INSTANCE.getCDetailPicture()));
|
CDeckEditorUI.SINGLETON_INSTANCE.setEditorController(new CEditorCommander(CDeckEditorUI.SINGLETON_INSTANCE.getCDetailPicture()));
|
||||||
}
|
}
|
||||||
@@ -512,16 +497,16 @@ public class PlayerPanel extends FPanel {
|
|||||||
pchDeckSelectorBtn.setCommand(new Runnable() {
|
pchDeckSelectorBtn.setCommand(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Planechase);
|
lobby.setCurrentGameMode(GameType.Planechase);
|
||||||
pchDeckSelectorBtn.requestFocusInWindow();
|
pchDeckSelectorBtn.requestFocusInWindow();
|
||||||
PlayerPanel.this.lobby.changePlayerFocus(index, GameType.Planechase);
|
lobby.changePlayerFocus(index, GameType.Planechase);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
pchDeckEditor.setCommand(new UiCommand() {
|
pchDeckEditor.setCommand(new UiCommand() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Planechase);
|
lobby.setCurrentGameMode(GameType.Planechase);
|
||||||
Predicate<PaperCard> predPlanes = new Predicate<PaperCard>() {
|
Predicate<PaperCard> predPlanes = new Predicate<PaperCard>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(PaperCard arg0) {
|
public boolean apply(PaperCard arg0) {
|
||||||
@@ -539,9 +524,9 @@ public class PlayerPanel extends FPanel {
|
|||||||
vgdSelectorBtn.setCommand(new Runnable() {
|
vgdSelectorBtn.setCommand(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Vanguard);
|
lobby.setCurrentGameMode(GameType.Vanguard);
|
||||||
vgdSelectorBtn.requestFocusInWindow();
|
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
|
* @param index
|
||||||
*/
|
*/
|
||||||
private void createPlayerTypeOptions() {
|
private void createPlayerTypeOptions() {
|
||||||
final boolean isServer = lobbyType == LobbyType.SERVER;
|
radioHuman = new FRadioButton("Human");
|
||||||
radioHuman = new FRadioButton(isServer ? "Local" : "Human", index == 0);
|
radioAi = new FRadioButton("AI");
|
||||||
radioAi = new FRadioButton("AI", !isServer && index != 0);
|
radioOpen = new FRadioButton("Open");
|
||||||
radioOpen = new FRadioButton("Open", isServer && index != 0);
|
|
||||||
final JPopupMenu menu = new JPopupMenu();
|
final JPopupMenu menu = new JPopupMenu();
|
||||||
radioAiUseSimulation = new JCheckBoxMenuItem("Use Simulation");
|
radioAiUseSimulation = new JCheckBoxMenuItem("Use Simulation");
|
||||||
menu.add(radioAiUseSimulation);
|
menu.add(radioAiUseSimulation);
|
||||||
|
radioAiUseSimulation.addActionListener(new ActionListener() {
|
||||||
|
@Override public final void actionPerformed(final ActionEvent e) {
|
||||||
|
lobby.firePlayerChangeListener(index);
|
||||||
|
} });
|
||||||
radioAi.setComponentPopupMenu(menu);
|
radioAi.setComponentPopupMenu(menu);
|
||||||
|
|
||||||
radioHuman.addMouseListener(radioMouseAdapter);
|
radioHuman.addMouseListener(radioMouseAdapter(radioHuman, LobbySlotType.LOCAL));
|
||||||
radioAi.addMouseListener(radioMouseAdapter);
|
radioAi.addMouseListener (radioMouseAdapter(radioAi, LobbySlotType.AI));
|
||||||
radioOpen.addMouseListener(radioMouseAdapter);
|
radioOpen.addMouseListener (radioMouseAdapter(radioOpen, LobbySlotType.OPEN));
|
||||||
|
|
||||||
final ButtonGroup tempBtnGroup = new ButtonGroup();
|
final ButtonGroup tempBtnGroup = new ButtonGroup();
|
||||||
tempBtnGroup.add(radioHuman);
|
tempBtnGroup.add(radioHuman);
|
||||||
@@ -576,9 +565,9 @@ public class PlayerPanel extends FPanel {
|
|||||||
deckBtn.setCommand(new Runnable() {
|
deckBtn.setCommand(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
PlayerPanel.this.lobby.setCurrentGameMode(GameType.Constructed);
|
lobby.setCurrentGameMode(GameType.Constructed);
|
||||||
deckBtn.requestFocusInWindow();
|
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() {
|
newNameBtn.setCommand(new UiCommand() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String newName = PlayerPanel.this.lobby.getNewName();
|
String newName = lobby.getNewName();
|
||||||
if (null == newName) {
|
if (null == newName) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -605,7 +594,7 @@ public class PlayerPanel extends FPanel {
|
|||||||
prefs.save();
|
prefs.save();
|
||||||
}
|
}
|
||||||
txtPlayerName.requestFocus();
|
txtPlayerName.requestFocus();
|
||||||
PlayerPanel.this.lobby.changePlayerFocus(index);
|
lobby.changePlayerFocus(index);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
newNameBtn.addFocusListener(nameFocusListener);
|
newNameBtn.addFocusListener(nameFocusListener);
|
||||||
@@ -640,10 +629,10 @@ public class PlayerPanel extends FPanel {
|
|||||||
.icon(FSkin.getIcon(FSkinProp.ICO_CLOSE)).hoverable(true).build();
|
.icon(FSkin.getIcon(FSkinProp.ICO_CLOSE)).hoverable(true).build();
|
||||||
closeBtn.setCommand(new Runnable() {
|
closeBtn.setCommand(new Runnable() {
|
||||||
@Override public final void run() {
|
@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;
|
return;
|
||||||
}
|
}
|
||||||
PlayerPanel.this.lobby.removePlayer(index);
|
lobby.removePlayer(index);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return closeBtn;
|
return closeBtn;
|
||||||
@@ -654,9 +643,8 @@ public class PlayerPanel extends FPanel {
|
|||||||
if (index < currentPrefs.length) {
|
if (index < currentPrefs.length) {
|
||||||
avatarIndex = Integer.parseInt(currentPrefs[index]);
|
avatarIndex = Integer.parseInt(currentPrefs[index]);
|
||||||
avatarLabel.setIcon(FSkin.getAvatars().get(avatarIndex));
|
avatarLabel.setIcon(FSkin.getAvatars().get(avatarIndex));
|
||||||
}
|
} else {
|
||||||
else {
|
setRandomAvatar(false);
|
||||||
setRandomAvatar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
avatarLabel.setToolTipText("L-click: Select avatar. R-click: Randomize avatar.");
|
avatarLabel.setToolTipText("L-click: Select avatar. R-click: Randomize avatar.");
|
||||||
@@ -664,25 +652,22 @@ public class PlayerPanel extends FPanel {
|
|||||||
avatarLabel.addMouseListener(avatarMouseListener);
|
avatarLabel.addMouseListener(avatarMouseListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Applies a random avatar, avoiding avatars already used.
|
/** Applies a random avatar, avoiding avatars already used. */
|
||||||
* @param playerIndex */
|
private void setRandomAvatar() {
|
||||||
public void setRandomAvatar() {
|
setRandomAvatar(true);
|
||||||
|
}
|
||||||
|
private void setRandomAvatar(final boolean fireListeners) {
|
||||||
int random = 0;
|
int random = 0;
|
||||||
|
|
||||||
List<Integer> usedAvatars = lobby.getUsedAvatars();
|
final List<Integer> usedAvatars = lobby.getUsedAvatars();
|
||||||
do {
|
do {
|
||||||
random = MyRandom.getRandom().nextInt(FSkin.getAvatars().size());
|
random = MyRandom.getRandom().nextInt(FSkin.getAvatars().size());
|
||||||
} while (usedAvatars.contains(random));
|
} while (usedAvatars.contains(random));
|
||||||
setAvatar(random);
|
setAvatar(random);
|
||||||
|
|
||||||
lobby.firePlayerChangeListener();
|
if (fireListeners) {
|
||||||
|
lobby.firePlayerChangeListener(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAvatar(int newAvatarIndex) {
|
|
||||||
avatarIndex = newAvatarIndex;
|
|
||||||
SkinImage icon = FSkin.getAvatars().get(newAvatarIndex);
|
|
||||||
avatarLabel.setIcon(icon);
|
|
||||||
avatarLabel.repaintSelf();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private final FSkin.LineSkinBorder focusedBorder = new FSkin.LineSkinBorder(FSkin.getColor(FSkin.Colors.CLR_BORDERS).alphaColor(255), 3);
|
private final FSkin.LineSkinBorder 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) {
|
public void setFocused(boolean focused) {
|
||||||
avatarLabel.setBorder(focused ? focusedBorder : defaultBorder);
|
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() {
|
public int getAvatarIndex() {
|
||||||
return avatarIndex;
|
return avatarIndex;
|
||||||
}
|
}
|
||||||
|
public void setAvatar(final int newAvatarIndex) {
|
||||||
public void setPlayerName(String string) {
|
avatarIndex = newAvatarIndex;
|
||||||
txtPlayerName.setText(string);
|
final SkinImage icon = FSkin.getAvatars().get(newAvatarIndex);
|
||||||
|
avatarLabel.setIcon(icon);
|
||||||
|
avatarLabel.repaintSelf();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getPlayerName() {
|
public int getTeam() {
|
||||||
return txtPlayerName.getText();
|
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(VSubmenuSealed.SINGLETON_INSTANCE);
|
||||||
//allSubmenus.add(VSubmenuWinston.SINGLETON_INSTANCE);
|
//allSubmenus.add(VSubmenuWinston.SINGLETON_INSTANCE);
|
||||||
|
|
||||||
allSubmenus.add(VSubmenuOnlineLobby.SINGLETON_INSTANCE);
|
//allSubmenus.add(VSubmenuOnlineLobby.SINGLETON_INSTANCE);
|
||||||
|
|
||||||
allSubmenus.add(VSubmenuDuels.SINGLETON_INSTANCE);
|
allSubmenus.add(VSubmenuDuels.SINGLETON_INSTANCE);
|
||||||
allSubmenus.add(VSubmenuChallenges.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.ItemEvent;
|
||||||
import java.awt.event.ItemListener;
|
import java.awt.event.ItemListener;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeSet;
|
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
@@ -24,25 +19,31 @@ import javax.swing.event.ListSelectionListener;
|
|||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
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.UiCommand;
|
||||||
|
import forge.deck.CardPool;
|
||||||
|
import forge.deck.Deck;
|
||||||
import forge.deck.DeckProxy;
|
import forge.deck.DeckProxy;
|
||||||
|
import forge.deck.DeckSection;
|
||||||
import forge.deck.DeckType;
|
import forge.deck.DeckType;
|
||||||
|
import forge.deck.DeckgenUtil;
|
||||||
import forge.deckchooser.DecksComboBoxEvent;
|
import forge.deckchooser.DecksComboBoxEvent;
|
||||||
import forge.deckchooser.FDeckChooser;
|
import forge.deckchooser.FDeckChooser;
|
||||||
import forge.deckchooser.IDecksComboBoxListener;
|
import forge.deckchooser.IDecksComboBoxListener;
|
||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
import forge.gui.CardDetailPanel;
|
import forge.gui.CardDetailPanel;
|
||||||
import forge.interfaces.ILobby;
|
|
||||||
import forge.interfaces.IPlayerChangeListener;
|
import forge.interfaces.IPlayerChangeListener;
|
||||||
|
import forge.interfaces.IUpdateable;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
|
import forge.match.GameLobby;
|
||||||
|
import forge.match.LobbySlot;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.net.game.LobbySlotType;
|
import forge.net.game.LobbySlotType;
|
||||||
import forge.net.game.LobbyState;
|
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||||
import forge.net.game.LobbyState.LobbyPlayerData;
|
|
||||||
import forge.net.game.server.RemoteClient;
|
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.toolbox.FCheckBox;
|
import forge.toolbox.FCheckBox;
|
||||||
@@ -55,39 +56,34 @@ import forge.toolbox.FScrollPanel;
|
|||||||
import forge.toolbox.FSkin;
|
import forge.toolbox.FSkin;
|
||||||
import forge.toolbox.FSkin.SkinImage;
|
import forge.toolbox.FSkin.SkinImage;
|
||||||
import forge.toolbox.FTextField;
|
import forge.toolbox.FTextField;
|
||||||
|
import forge.util.Aggregates;
|
||||||
import forge.util.Lang;
|
import forge.util.Lang;
|
||||||
import forge.util.NameGenerator;
|
import forge.util.NameGenerator;
|
||||||
|
import forge.util.storage.IStorage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lobby view. View of a number of players at the deck selection stage.
|
* 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>
|
* <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;
|
static final int MAX_PLAYERS = 8;
|
||||||
private static final ForgePreferences prefs = FModel.getPreferences();
|
private static final ForgePreferences prefs = FModel.getPreferences();
|
||||||
|
|
||||||
public enum LobbyType { LOCAL, SERVER, CLIENT; }
|
|
||||||
|
|
||||||
// General variables
|
// General variables
|
||||||
private final LobbyType type;
|
private final GameLobby lobby;
|
||||||
private int localPlayer = 0;
|
|
||||||
private IPlayerChangeListener playerChangeListener = null;
|
private IPlayerChangeListener playerChangeListener = null;
|
||||||
private final LblHeader lblTitle = new LblHeader("Sanctioned Format: Constructed");
|
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 int playerWithFocus = 0; // index of the player that currently has focus
|
||||||
private PlayerPanel playerPanelWithFocus;
|
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 StartButton btnStart = new StartButton();
|
||||||
private final JPanel pnlStart = new JPanel(new MigLayout("insets 0, gap 0, wrap 2"));
|
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
|
private final JPanel constructedFrame = new JPanel(new MigLayout("insets 0, gap 0, wrap 2")); // Main content frame
|
||||||
|
|
||||||
// Variants frame and variables
|
// 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 FPanel variantsPanel = new FPanel(new MigLayout("insets 10, gapx 10"));
|
||||||
private final VariantCheckBox vntVanguard = new VariantCheckBox(GameType.Vanguard);
|
private final VariantCheckBox vntVanguard = new VariantCheckBox(GameType.Vanguard);
|
||||||
private final VariantCheckBox vntMomirBasic = new VariantCheckBox(GameType.MomirBasic);
|
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 vntPlanechase = new VariantCheckBox(GameType.Planechase);
|
||||||
private final VariantCheckBox vntArchenemy = new VariantCheckBox(GameType.Archenemy);
|
private final VariantCheckBox vntArchenemy = new VariantCheckBox(GameType.Archenemy);
|
||||||
private final VariantCheckBox vntArchenemyRumble = new VariantCheckBox(GameType.ArchenemyRumble);
|
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
|
// Player frame elements
|
||||||
private final JPanel playersFrame = new JPanel(new MigLayout("insets 0, gap 0 5, wrap, hidemode 3"));
|
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 List<FDeckChooser> deckChoosers = new ArrayList<FDeckChooser>(8);
|
||||||
private final FCheckBox cbSingletons = new FCheckBox("Singleton Mode");
|
private final FCheckBox cbSingletons = new FCheckBox("Singleton Mode");
|
||||||
private final FCheckBox cbArtifacts = new FCheckBox("Remove Artifacts");
|
private final FCheckBox cbArtifacts = new FCheckBox("Remove Artifacts");
|
||||||
|
private final Deck[] decks = new Deck[MAX_PLAYERS];
|
||||||
|
|
||||||
// Variants
|
// Variants
|
||||||
private final List<FList<Object>> schemeDeckLists = new ArrayList<FList<Object>>();
|
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>();
|
private final Vector<Object> aiListData = new Vector<Object>();
|
||||||
|
|
||||||
// CTR
|
// CTR
|
||||||
public VLobby(final LobbyType type) {
|
public VLobby(final GameLobby lobby) {
|
||||||
this.type = type;
|
this.lobby = lobby;
|
||||||
|
|
||||||
lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
|
lblTitle.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2));
|
||||||
|
|
||||||
@@ -142,55 +141,23 @@ public class VLobby implements ILobby {
|
|||||||
|
|
||||||
variantsPanel.setOpaque(false);
|
variantsPanel.setOpaque(false);
|
||||||
variantsPanel.add(newLabel("Variants:"));
|
variantsPanel.add(newLabel("Variants:"));
|
||||||
variantsPanel.add(vntVanguard);
|
for (final VariantCheckBox vcb : vntBoxes) {
|
||||||
variantsPanel.add(vntMomirBasic);
|
variantsPanel.add(vcb);
|
||||||
variantsPanel.add(vntCommander);
|
}
|
||||||
variantsPanel.add(vntTinyLeaders);
|
|
||||||
variantsPanel.add(vntPlanechase);
|
|
||||||
variantsPanel.add(vntArchenemy);
|
|
||||||
variantsPanel.add(vntArchenemyRumble);
|
|
||||||
|
|
||||||
constructedFrame.add(new FScrollPane(variantsPanel, false, true,
|
constructedFrame.add(new FScrollPane(variantsPanel, false, true,
|
||||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER,
|
||||||
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED),
|
||||||
"w 100%, h 45px!, gapbottom 10px, spanx 2, wrap");
|
"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.setOpaque(false);
|
||||||
playersFrame.add(playersScroll, "w 100%, h 100%-35px");
|
playersFrame.add(playersScroll, "w 100%, h 100%-35px");
|
||||||
|
|
||||||
if (type != LobbyType.CLIENT) {
|
if (lobby.hasControl()) {
|
||||||
addPlayerBtn.setFocusable(true);
|
addPlayerBtn.setFocusable(true);
|
||||||
addPlayerBtn.setCommand(new Runnable() {
|
addPlayerBtn.setCommand(new Runnable() {
|
||||||
@Override public final void run() {
|
@Override public final void run() {
|
||||||
addPlayer();
|
lobby.addSlot();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
playersFrame.add(addPlayerBtn, "height 30px!, growx, pushx");
|
playersFrame.add(addPlayerBtn, "height 30px!, growx, pushx");
|
||||||
@@ -209,9 +176,16 @@ public class VLobby implements ILobby {
|
|||||||
decksFrame.setOpaque(false);
|
decksFrame.setOpaque(false);
|
||||||
|
|
||||||
// Start Button
|
// Start Button
|
||||||
if (type != LobbyType.CLIENT) {
|
if (lobby.hasControl()) {
|
||||||
pnlStart.setOpaque(false);
|
pnlStart.setOpaque(false);
|
||||||
pnlStart.add(btnStart, "align center");
|
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);
|
populateDeckPanel(GameType.Constructed);
|
||||||
populateVanguardLists();
|
populateVanguardLists();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int addPlayerInFreeSlot(final String name) {
|
public void update() {
|
||||||
if (activePlayersNum >= MAX_PLAYERS) {
|
activePlayersNum = lobby.getNumberOfSlots();
|
||||||
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++;
|
|
||||||
addPlayerBtn.setEnabled(activePlayersNum < MAX_PLAYERS);
|
addPlayerBtn.setEnabled(activePlayersNum < MAX_PLAYERS);
|
||||||
|
|
||||||
playerPanels.get(slot).setVisible(true);
|
for (final VariantCheckBox vcb : vntBoxes) {
|
||||||
playerPanels.get(slot).focusOnAvatar();
|
vcb.setSelected(hasVariant(vcb.variant));
|
||||||
|
vcb.setEnabled(lobby.hasControl());
|
||||||
firePlayerChangeListener();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void removePlayer(final int playerIndex) {
|
final boolean allowNetworking = lobby.isAllowNetworking();
|
||||||
if (activePlayersNum <= playerIndex) {
|
for (int i = 0; i < MAX_PLAYERS; i++) {
|
||||||
return;
|
final boolean hasPanel = i < playerPanels.size();
|
||||||
}
|
if (i < activePlayersNum) {
|
||||||
activePlayersNum--;
|
// visible panels
|
||||||
final FPanel player = playerPanels.get(playerIndex);
|
final LobbySlot slot = lobby.getSlot(i);
|
||||||
player.setVisible(false);
|
final PlayerPanel panel;
|
||||||
addPlayerBtn.setEnabled(true);
|
if (hasPanel) {
|
||||||
|
panel = playerPanels.get(i);
|
||||||
//find closest player still in game and give focus
|
|
||||||
int min = MAX_PLAYERS;
|
|
||||||
final List<Integer> participants = getParticipants();
|
|
||||||
if (!participants.isEmpty()) {
|
|
||||||
int closest = 2;
|
|
||||||
|
|
||||||
for (final int participantIndex : getParticipants()) {
|
|
||||||
final int diff = Math.abs(playerIndex - participantIndex);
|
|
||||||
|
|
||||||
if (diff < min) {
|
|
||||||
min = diff;
|
|
||||||
closest = participantIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
changePlayerFocus(closest);
|
|
||||||
playerPanels.get(closest).focusOnAvatar();
|
|
||||||
}
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
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.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();
|
panel.update();
|
||||||
|
|
||||||
|
deckChoosers.get(i).setIsAi(slot.getType() == LobbySlotType.AI);
|
||||||
|
} else if (hasPanel) {
|
||||||
|
playerPanels.get(i).setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLocalPlayer(final int index) {
|
if (playerWithFocus >= activePlayersNum) {
|
||||||
localPlayer = index;
|
playerWithFocus = activePlayersNum - 1;
|
||||||
|
}
|
||||||
|
changePlayerFocus(playerWithFocus);
|
||||||
|
refreshPanels(true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPlayerChangeListener(final IPlayerChangeListener listener) {
|
public void setPlayerChangeListener(final IPlayerChangeListener listener) {
|
||||||
this.playerChangeListener = listener;
|
this.playerChangeListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
void firePlayerChangeListener() {
|
void firePlayerChangeListener(final int index) {
|
||||||
if (playerChangeListener != null) {
|
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);
|
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.
|
/** Builds the actual deck panel layouts for each player.
|
||||||
@@ -374,53 +300,142 @@ public class VLobby implements ILobby {
|
|||||||
String labelConstraints = "gaptop 10px, gapbottom 5px";
|
String labelConstraints = "gaptop 10px, gapbottom 5px";
|
||||||
|
|
||||||
// Main deck
|
// Main deck
|
||||||
final FDeckChooser mainChooser = new FDeckChooser(null, isPlayerAI(playerIndex));
|
final FDeckChooser mainChooser = new FDeckChooser(null, false);
|
||||||
mainChooser.initialize();
|
mainChooser.initialize();
|
||||||
mainChooser.getLstDecks().setSelectCommand(new UiCommand() {
|
mainChooser.getLstDecks().setSelectCommand(new UiCommand() {
|
||||||
@Override
|
@Override public final void run() {
|
||||||
public void run() {
|
|
||||||
VLobby.this.onDeckClicked(playerIndex, mainChooser.getSelectedDeckType(), mainChooser.getLstDecks().getSelectedItems());
|
VLobby.this.onDeckClicked(playerIndex, mainChooser.getSelectedDeckType(), mainChooser.getLstDecks().getSelectedItems());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
deckChoosers.add(mainChooser);
|
deckChoosers.add(mainChooser);
|
||||||
|
|
||||||
// Scheme deck list
|
// Scheme deck list
|
||||||
FPanel schemeDeckPanel = new FPanel();
|
final FPanel schemeDeckPanel = new FPanel();
|
||||||
schemeDeckPanel.setBorderToggle(false);
|
schemeDeckPanel.setBorderToggle(false);
|
||||||
schemeDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
schemeDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
||||||
schemeDeckPanel.add(new FLabel.Builder().text("Select Scheme deck:").build(), labelConstraints);
|
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.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);
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
schemeDeckPanel.add(scrSchemes, "grow, push");
|
schemeDeckPanel.add(scrSchemes, "grow, push");
|
||||||
schemeDeckLists.add(schemeDeckList);
|
schemeDeckLists.add(schemeDeckList);
|
||||||
schemeDeckPanels.add(schemeDeckPanel);
|
schemeDeckPanels.add(schemeDeckPanel);
|
||||||
|
|
||||||
// Commander deck list
|
// Commander deck list
|
||||||
FPanel commanderDeckPanel = new FPanel();
|
final FPanel commanderDeckPanel = new FPanel();
|
||||||
commanderDeckPanel.setBorderToggle(false);
|
commanderDeckPanel.setBorderToggle(false);
|
||||||
commanderDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
commanderDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
||||||
commanderDeckPanel.add(new FLabel.Builder().text("Select Commander deck:").build(), labelConstraints);
|
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.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);
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
commanderDeckPanel.add(scrCommander, "grow, push");
|
commanderDeckPanel.add(scrCommander, "grow, push");
|
||||||
commanderDeckLists.add(commanderDeckList);
|
commanderDeckLists.add(commanderDeckList);
|
||||||
commanderDeckPanels.add(commanderDeckPanel);
|
commanderDeckPanels.add(commanderDeckPanel);
|
||||||
|
|
||||||
// Planar deck list
|
// Planar deck list
|
||||||
FPanel planarDeckPanel = new FPanel();
|
final FPanel planarDeckPanel = new FPanel();
|
||||||
planarDeckPanel.setBorderToggle(false);
|
planarDeckPanel.setBorderToggle(false);
|
||||||
planarDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
planarDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
||||||
planarDeckPanel.add(new FLabel.Builder().text("Select Planar deck:").build(), labelConstraints);
|
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.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);
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
planarDeckPanel.add(scrPlanes, "grow, push");
|
planarDeckPanel.add(scrPlanes, "grow, push");
|
||||||
planarDeckLists.add(planarDeckList);
|
planarDeckLists.add(planarDeckList);
|
||||||
@@ -430,15 +445,15 @@ public class VLobby implements ILobby {
|
|||||||
FPanel vgdDeckPanel = new FPanel();
|
FPanel vgdDeckPanel = new FPanel();
|
||||||
vgdDeckPanel.setBorderToggle(false);
|
vgdDeckPanel.setBorderToggle(false);
|
||||||
|
|
||||||
FList<Object> vgdAvatarList = new FList<Object>();
|
final FList<Object> vgdAvatarList = new FList<Object>();
|
||||||
vgdAvatarList.setListData(isPlayerAI(playerIndex) ? aiListData : humanListData);
|
vgdAvatarList.setListData(isPlayerAI(playerIndex) ? aiListData : humanListData);
|
||||||
vgdAvatarList.setSelectedIndex(0);
|
vgdAvatarList.setSelectedIndex(0);
|
||||||
vgdAvatarList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
vgdAvatarList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
|
||||||
vgdAvatarList.addListSelectionListener(vgdLSListener);
|
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);
|
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||||
|
|
||||||
CardDetailPanel vgdDetail = new CardDetailPanel();
|
final CardDetailPanel vgdDetail = new CardDetailPanel();
|
||||||
vgdAvatarDetails.add(vgdDetail);
|
vgdAvatarDetails.add(vgdDetail);
|
||||||
|
|
||||||
vgdDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
vgdDeckPanel.setLayout(new MigLayout(sectionConstraints));
|
||||||
@@ -449,16 +464,19 @@ public class VLobby implements ILobby {
|
|||||||
vgdPanels.add(vgdDeckPanel);
|
vgdPanels.add(vgdDeckPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void onDeckClicked(int iPlayer, DeckType type, Collection<DeckProxy> selectedDecks) {
|
protected void onDeckClicked(final int iPlayer, final DeckType type, final Collection<DeckProxy> selectedDecks) {
|
||||||
String text = type.toString() + ": " + Lang.joinHomogenous(selectedDecks, DeckProxy.FN_GET_NAME);
|
if (iPlayer < activePlayersNum && lobby.mayEdit(iPlayer)) {
|
||||||
|
final String text = type.toString() + ": " + Lang.joinHomogenous(selectedDecks, DeckProxy.FN_GET_NAME);
|
||||||
playerPanels.get(iPlayer).setDeckSelectorButtonText(text);
|
playerPanels.get(iPlayer).setDeckSelectorButtonText(text);
|
||||||
|
fireDeckChangeListener(iPlayer, selectedDecks.iterator().next().getDeck());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Populates the deck panel with the focused player's deck choices. */
|
/** Populates the deck panel with the focused player's deck choices. */
|
||||||
private void populateDeckPanel(final GameType forGameType) {
|
private void populateDeckPanel(final GameType forGameType) {
|
||||||
decksFrame.removeAll();
|
decksFrame.removeAll();
|
||||||
|
|
||||||
if (playerPanelWithFocus.getType() == LobbySlotType.OPEN || playerPanelWithFocus.getType() == LobbySlotType.REMOTE) {
|
if (!lobby.mayEdit(playerWithFocus)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -487,7 +505,7 @@ public class VLobby implements ILobby {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @return {@link javax.swing.JButton} */
|
/** @return {@link javax.swing.JButton} */
|
||||||
public JButton getBtnStart() {
|
JButton getBtnStart() {
|
||||||
return this.btnStart;
|
return this.btnStart;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,18 +515,18 @@ public class VLobby implements ILobby {
|
|||||||
public List<FDeckChooser> getDeckChoosers() { return Collections.unmodifiableList(deckChoosers); }
|
public List<FDeckChooser> getDeckChoosers() { return Collections.unmodifiableList(deckChoosers); }
|
||||||
|
|
||||||
/** Gets the random deck checkbox for Singletons. */
|
/** Gets the random deck checkbox for Singletons. */
|
||||||
public FCheckBox getCbSingletons() { return cbSingletons; }
|
FCheckBox getCbSingletons() { return cbSingletons; }
|
||||||
|
|
||||||
/** Gets the random deck checkbox for Artifacts. */
|
/** Gets the random deck checkbox for Artifacts. */
|
||||||
public FCheckBox getCbArtifacts() { return cbArtifacts; }
|
FCheckBox getCbArtifacts() { return cbArtifacts; }
|
||||||
|
|
||||||
public FCheckBox getVntArchenemy() { return vntArchenemy; }
|
FCheckBox getVntArchenemy() { return vntArchenemy; }
|
||||||
public FCheckBox getVntArchenemyRumble() { return vntArchenemyRumble; }
|
FCheckBox getVntArchenemyRumble() { return vntArchenemyRumble; }
|
||||||
public FCheckBox getVntCommander() { return vntCommander; }
|
FCheckBox getVntCommander() { return vntCommander; }
|
||||||
public FCheckBox getVntMomirBasic() { return vntMomirBasic; }
|
FCheckBox getVntMomirBasic() { return vntMomirBasic; }
|
||||||
public FCheckBox getVntPlanechase() { return vntPlanechase; }
|
FCheckBox getVntPlanechase() { return vntPlanechase; }
|
||||||
public FCheckBox getVntTinyLeaders() { return vntTinyLeaders; }
|
FCheckBox getVntTinyLeaders() { return vntTinyLeaders; }
|
||||||
public FCheckBox getVntVanguard() { return vntVanguard; }
|
FCheckBox getVntVanguard() { return vntVanguard; }
|
||||||
|
|
||||||
public int getLastArchenemy() { return lastArchenemy; }
|
public int getLastArchenemy() { return lastArchenemy; }
|
||||||
public void setLastArchenemy(final int archenemy) { lastArchenemy = archenemy; }
|
public void setLastArchenemy(final int archenemy) { lastArchenemy = archenemy; }
|
||||||
@@ -524,38 +542,22 @@ public class VLobby implements ILobby {
|
|||||||
return deckChoosers.get(playernum);
|
return deckChoosers.get(playernum);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Integer> getTeams() { return teams; }
|
GameType getCurrentGameMode() {
|
||||||
public List<Integer> getArchenemyTeams() { return archenemyTeams; }
|
return lobby.getGameType();
|
||||||
public GameType getCurrentGameMode() { return currentGameMode; }
|
}
|
||||||
public void setCurrentGameMode(final GameType mode) { currentGameMode = mode; }
|
void setCurrentGameMode(final GameType mode) {
|
||||||
|
lobby.setGameType(mode);
|
||||||
public boolean isPlayerAI(int playernum) {
|
update();
|
||||||
return playerPanels.get(playernum).isAi();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getAiOptions(int playernum) {
|
public boolean isPlayerAI(final int playernum) {
|
||||||
if (playerPanels.get(playernum).isSimulatedAi()) {
|
return playernum < activePlayersNum ? playerPanels.get(playernum).isAi() : false;
|
||||||
Map<String, String> options = new HashMap<String, String>();
|
|
||||||
options.put("UseSimulation", "True");
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNumPlayers() {
|
public int getNumPlayers() {
|
||||||
return activePlayersNum;
|
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. */
|
/** Revalidates the player and deck sections. Necessary after adding or hiding any panels. */
|
||||||
private void refreshPanels(boolean refreshPlayerFrame, boolean refreshDeckFrame) {
|
private void refreshPanels(boolean refreshPlayerFrame, boolean refreshDeckFrame) {
|
||||||
if (refreshPlayerFrame) {
|
if (refreshPlayerFrame) {
|
||||||
@@ -569,7 +571,7 @@ public class VLobby implements ILobby {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void changePlayerFocus(int newFocusOwner) {
|
public void changePlayerFocus(int newFocusOwner) {
|
||||||
changePlayerFocus(newFocusOwner, appliedVariants.contains(currentGameMode) ? currentGameMode : GameType.Constructed);
|
changePlayerFocus(newFocusOwner, lobby.getGameType());
|
||||||
}
|
}
|
||||||
|
|
||||||
void changePlayerFocus(int newFocusOwner, GameType gType) {
|
void changePlayerFocus(int newFocusOwner, GameType gType) {
|
||||||
@@ -593,32 +595,15 @@ public class VLobby implements ILobby {
|
|||||||
prefs.save();
|
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. */
|
/** Adds a pre-styled FLabel component with the specified title. */
|
||||||
FLabel newLabel(String title) {
|
FLabel newLabel(String title) {
|
||||||
return new FLabel.Builder().text(title).fontSize(14).fontStyle(Font.ITALIC).build();
|
return new FLabel.Builder().text(title).fontSize(14).fontStyle(Font.ITALIC).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Integer> getUsedAvatars() {
|
List<Integer> getUsedAvatars() {
|
||||||
List<Integer> usedAvatars = Arrays.asList(-1,-1,-1,-1,-1,-1,-1,-1);
|
final List<Integer> usedAvatars = Lists.newArrayListWithCapacity(MAX_PLAYERS);
|
||||||
int i = 0;
|
for (final PlayerPanel pp : playerPanels) {
|
||||||
for (PlayerPanel pp : playerPanels) {
|
usedAvatars.add(pp.getAvatarIndex());
|
||||||
usedAvatars.set(i++, pp.getAvatarIndex());
|
|
||||||
}
|
}
|
||||||
return usedAvatars;
|
return usedAvatars;
|
||||||
}
|
}
|
||||||
@@ -660,92 +645,30 @@ public class VLobby implements ILobby {
|
|||||||
return names;
|
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
|
//========== Various listeners in build order
|
||||||
|
|
||||||
@SuppressWarnings("serial") private class VariantCheckBox extends FCheckBox {
|
@SuppressWarnings("serial") private class VariantCheckBox extends FCheckBox {
|
||||||
private final GameType variantType;
|
private final GameType variant;
|
||||||
|
private VariantCheckBox(final GameType variantType) {
|
||||||
private VariantCheckBox(GameType variantType0) {
|
super(variantType.toString());
|
||||||
super(variantType0.toString());
|
this.variant = variantType;
|
||||||
|
|
||||||
variantType = variantType0;
|
|
||||||
|
|
||||||
setToolTipText(variantType.getDescription());
|
setToolTipText(variantType.getDescription());
|
||||||
|
|
||||||
addItemListener(new ItemListener() {
|
addItemListener(new ItemListener() {
|
||||||
@Override
|
@Override public final void itemStateChanged(final ItemEvent e) {
|
||||||
public void itemStateChanged(ItemEvent e) {
|
|
||||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
if (e.getStateChange() == ItemEvent.SELECTED) {
|
||||||
appliedVariants.add(variantType);
|
lobby.applyVariant(variantType);
|
||||||
currentGameMode = variantType;
|
} else {
|
||||||
|
lobby.removeVariant(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;
|
|
||||||
}
|
}
|
||||||
}
|
VLobby.this.update();
|
||||||
else {
|
|
||||||
appliedVariants.remove(variantType);
|
|
||||||
if (currentGameMode == variantType) {
|
|
||||||
currentGameMode = GameType.Constructed;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (PlayerPanel pp : playerPanels) {
|
|
||||||
pp.toggleIsPlayerArchenemy();
|
|
||||||
}
|
|
||||||
changePlayerFocus(playerWithFocus, currentGameMode);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionListener nameListener = new ActionListener() {
|
final ActionListener nameListener = new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
FTextField nField = (FTextField)e.getSource();
|
FTextField nField = (FTextField)e.getSource();
|
||||||
@@ -756,39 +679,51 @@ public class VLobby implements ILobby {
|
|||||||
/** This listener will look for a vanguard avatar being selected in the lists
|
/** This listener will look for a vanguard avatar being selected in the lists
|
||||||
/ and update the corresponding detail panel. */
|
/ and update the corresponding detail panel. */
|
||||||
private ListSelectionListener vgdLSListener = new ListSelectionListener() {
|
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
|
final PaperCard vanguardAvatar;
|
||||||
public void valueChanged(ListSelectionEvent e) {
|
final Deck deck = decks[index];
|
||||||
int index = vgdAvatarLists.indexOf(e.getSource());
|
if (selected instanceof PaperCard) {
|
||||||
Object obj = vgdAvatarLists.get(index).getSelectedValue();
|
pp.setVanguardButtonText(((PaperCard) selected).getName());
|
||||||
PlayerPanel pp = playerPanels.get(index);
|
cdp.setCard(CardView.getCardForUi((PaperCard) selected));
|
||||||
CardDetailPanel cdp = vgdAvatarDetails.get(index);
|
|
||||||
|
|
||||||
if (obj instanceof PaperCard) {
|
|
||||||
pp.setVanguardButtonText(((PaperCard) obj).getName());
|
|
||||||
cdp.setCard(CardView.getCardForUi((PaperCard) obj));
|
|
||||||
cdp.setVisible(true);
|
cdp.setVisible(true);
|
||||||
refreshPanels(false, true);
|
refreshPanels(false, true);
|
||||||
}
|
|
||||||
else {
|
vanguardAvatar = (PaperCard)selected;
|
||||||
pp.setVanguardButtonText((String) obj);
|
} else {
|
||||||
|
String sel = (String) selected;
|
||||||
|
pp.setVanguardButtonText(sel);
|
||||||
cdp.setVisible(false);
|
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();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
//========== METHODS FOR VARIANTS
|
//========== 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. */
|
/** Gets the list of planar deck lists. */
|
||||||
public List<FList<Object>> getPlanarDeckLists() {
|
public List<FList<Object>> getPlanarDeckLists() {
|
||||||
return planarDeckLists;
|
return planarDeckLists;
|
||||||
|
|||||||
@@ -8,74 +8,102 @@ import javax.swing.JMenu;
|
|||||||
import forge.GuiBase;
|
import forge.GuiBase;
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.UiCommand;
|
import forge.UiCommand;
|
||||||
import forge.game.GameRules;
|
|
||||||
import forge.game.GameType;
|
|
||||||
import forge.gui.FNetOverlay;
|
import forge.gui.FNetOverlay;
|
||||||
import forge.gui.framework.FScreen;
|
import forge.gui.framework.FScreen;
|
||||||
import forge.gui.framework.ICDoc;
|
import forge.gui.framework.ICDoc;
|
||||||
|
import forge.interfaces.IGuiGame;
|
||||||
|
import forge.interfaces.ILobbyListener;
|
||||||
import forge.interfaces.IPlayerChangeListener;
|
import forge.interfaces.IPlayerChangeListener;
|
||||||
|
import forge.interfaces.IUpdateable;
|
||||||
|
import forge.match.GameLobby.GameLobbyData;
|
||||||
import forge.menus.IMenuProvider;
|
import forge.menus.IMenuProvider;
|
||||||
import forge.menus.MenuUtil;
|
import forge.menus.MenuUtil;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
|
import forge.net.ClientGameLobby;
|
||||||
import forge.net.FGameClient;
|
import forge.net.FGameClient;
|
||||||
import forge.net.FServerManager;
|
import forge.net.FServerManager;
|
||||||
import forge.net.game.LobbyState;
|
import forge.net.ServerGameLobby;
|
||||||
import forge.net.game.LobbyState.LobbyPlayerData;
|
import forge.net.game.IRemote;
|
||||||
import forge.net.game.LoginEvent;
|
import forge.net.game.IdentifiableNetEvent;
|
||||||
import forge.net.game.client.ILobbyListener;
|
import forge.net.game.MessageEvent;
|
||||||
|
import forge.net.game.NetEvent;
|
||||||
|
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.home.VLobby;
|
import forge.screens.home.VLobby;
|
||||||
import forge.screens.home.VLobby.LobbyType;
|
|
||||||
import forge.screens.home.sanctioned.ConstructedGameMenu;
|
import forge.screens.home.sanctioned.ConstructedGameMenu;
|
||||||
|
|
||||||
public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
public enum CSubmenuOnlineLobby implements ICDoc, IMenuProvider {
|
||||||
SINGLETON_INSTANCE;
|
SINGLETON_INSTANCE;
|
||||||
|
|
||||||
final void host(final int portNumber) {
|
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);
|
server.startServer(portNumber);
|
||||||
FServerManager.getInstance().setLobby(lobby);
|
server.setLobby(lobby);
|
||||||
FServerManager.getInstance().hostGame(new GameRules(GameType.Constructed));
|
|
||||||
|
|
||||||
FNetOverlay.SINGLETON_INSTANCE.showUp("Hosting game");
|
FNetOverlay.SINGLETON_INSTANCE.showUp("Hosting game");
|
||||||
lobby.setPlayerChangeListener(new IPlayerChangeListener() {
|
lobby.setListener(new IUpdateable() {
|
||||||
@Override public final void update(final LobbyPlayerData data) {
|
@Override public final void update() {
|
||||||
FServerManager.getInstance().updateLobbyState();
|
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());
|
server.setLobbyListener(new ILobbyListener() {
|
||||||
FNetOverlay.SINGLETON_INSTANCE.setGameClient(client);
|
@Override public final void update(final GameLobbyData state, final int slot) {
|
||||||
client.addLobbyListener(new ILobbyListener() {
|
// NO-OP, lobby connected directly
|
||||||
@Override public final void update(final LobbyState state) {
|
|
||||||
lobby.setState(state);
|
|
||||||
}
|
}
|
||||||
@Override public final void message(final String source, final String message) {
|
@Override public final void message(final String source, final String message) {
|
||||||
FNetOverlay.SINGLETON_INSTANCE.addMessage(source, message);
|
FNetOverlay.SINGLETON_INSTANCE.addMessage(source, message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
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);
|
Singletons.getControl().setCurrentScreen(FScreen.ONLINE_LOBBY);
|
||||||
FNetOverlay.SINGLETON_INSTANCE.showUp(String.format("Hosting on port %d", portNumber));
|
FNetOverlay.SINGLETON_INSTANCE.showUp(String.format("Hosting on port %d", portNumber));
|
||||||
}
|
}
|
||||||
|
|
||||||
final void join(final String hostname, final int port) {
|
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);
|
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() {
|
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) {
|
@Override public final void message(final String source, final String message) {
|
||||||
FNetOverlay.SINGLETON_INSTANCE.addMessage(source, message);
|
FNetOverlay.SINGLETON_INSTANCE.addMessage(source, message);
|
||||||
}
|
}
|
||||||
|
@Override public final void update(final GameLobbyData state, final int slot) {
|
||||||
|
lobby.setLocalPlayer(slot);
|
||||||
|
lobby.setData(state);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
lobby.setPlayerChangeListener(new IPlayerChangeListener() {
|
view.setPlayerChangeListener(new IPlayerChangeListener() {
|
||||||
@Override public final void update(final LobbyPlayerData data) {
|
@Override public final void update(final int index, final UpdateLobbyPlayerEvent event) {
|
||||||
client.send(new LoginEvent(data.getName()));
|
client.send(event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
client.connect(hostname, port);
|
client.connect(hostname, port);
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ import forge.gui.framework.EDocID;
|
|||||||
import forge.gui.framework.FScreen;
|
import forge.gui.framework.FScreen;
|
||||||
import forge.gui.framework.IVDoc;
|
import forge.gui.framework.IVDoc;
|
||||||
import forge.gui.framework.IVTopLevelUI;
|
import forge.gui.framework.IVTopLevelUI;
|
||||||
|
import forge.match.GameLobby;
|
||||||
import forge.screens.home.VLobby;
|
import forge.screens.home.VLobby;
|
||||||
import forge.screens.home.VLobby.LobbyType;
|
|
||||||
import forge.toolbox.FPanel;
|
import forge.toolbox.FPanel;
|
||||||
import forge.util.gui.SOptionPane;
|
import forge.util.gui.SOptionPane;
|
||||||
import forge.view.FView;
|
import forge.view.FView;
|
||||||
@@ -33,9 +33,9 @@ public enum VOnlineLobby implements IVDoc<COnlineLobby>, IVTopLevelUI {
|
|||||||
VLobby getLobby() {
|
VLobby getLobby() {
|
||||||
return lobby;
|
return lobby;
|
||||||
}
|
}
|
||||||
VLobby setLobby(final LobbyType type) {
|
VLobby setLobby(final GameLobby lobby) {
|
||||||
this.lobby = new VLobby(type);
|
this.lobby = new VLobby(lobby);
|
||||||
getLayoutControl().setLobby(lobby);
|
getLayoutControl().setLobby(this.lobby);
|
||||||
return this.lobby;
|
return this.lobby;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,8 +65,10 @@ public enum VOnlineLobby implements IVDoc<COnlineLobby>, IVTopLevelUI {
|
|||||||
container.repaint();
|
container.repaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!lobby.getPlayerPanels().isEmpty()) {
|
||||||
lobby.changePlayerFocus(0);
|
lobby.changePlayerFocus(0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EDocID getDocumentID() {
|
public EDocID getDocumentID() {
|
||||||
|
|||||||
@@ -9,11 +9,14 @@ import forge.deckchooser.IDecksComboBoxListener;
|
|||||||
import forge.gui.framework.DragCell;
|
import forge.gui.framework.DragCell;
|
||||||
import forge.gui.framework.DragTab;
|
import forge.gui.framework.DragTab;
|
||||||
import forge.gui.framework.EDocID;
|
import forge.gui.framework.EDocID;
|
||||||
|
import forge.interfaces.IPlayerChangeListener;
|
||||||
|
import forge.match.GameLobby;
|
||||||
|
import forge.match.LocalLobby;
|
||||||
|
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||||
import forge.screens.home.EMenuGroup;
|
import forge.screens.home.EMenuGroup;
|
||||||
import forge.screens.home.IVSubmenu;
|
import forge.screens.home.IVSubmenu;
|
||||||
import forge.screens.home.VLobby;
|
|
||||||
import forge.screens.home.VHomeUI;
|
import forge.screens.home.VHomeUI;
|
||||||
import forge.screens.home.VLobby.LobbyType;
|
import forge.screens.home.VLobby;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assembles Swing components of constructed submenu singleton.
|
* Assembles Swing components of constructed submenu singleton.
|
||||||
@@ -28,12 +31,22 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
private DragCell parentCell;
|
private DragCell parentCell;
|
||||||
private final DragTab tab = new DragTab("Constructed Mode");
|
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() {
|
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() {
|
public VLobby getLobby() {
|
||||||
return lobby;
|
return vLobby;
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////
|
/////////////////////////////////////
|
||||||
@@ -112,25 +125,27 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
|||||||
|
|
||||||
container.removeAll();
|
container.removeAll();
|
||||||
container.setLayout(new MigLayout("insets 0, gap 0, wrap 1, ax right"));
|
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.populate();
|
||||||
fdc.getDecksComboBox().addListener(new IDecksComboBoxListener() {
|
fdc.getDecksComboBox().addListener(new IDecksComboBoxListener() {
|
||||||
@Override public final void deckTypeSelected(final DecksComboBoxEvent ev) {
|
@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(vLobby.getConstructedFrame(), "gap 20px 20px 20px 0px, push, grow");
|
||||||
container.add(lobby.getPanelStart(), "gap 0 0 3.5%! 3.5%!, ax center");
|
container.add(vLobby.getPanelStart(), "gap 0 0 3.5%! 3.5%!, ax center");
|
||||||
|
|
||||||
if (container.isShowing()) {
|
if (container.isShowing()) {
|
||||||
container.validate();
|
container.validate();
|
||||||
container.repaint();
|
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.CardPool;
|
||||||
import forge.deck.Deck;
|
import forge.deck.Deck;
|
||||||
import forge.deckchooser.FDeckViewer;
|
import forge.deckchooser.FDeckViewer;
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GameEntityView;
|
import forge.game.GameEntityView;
|
||||||
import forge.game.GameView;
|
import forge.game.GameView;
|
||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
@@ -61,9 +60,8 @@ import forge.game.player.DelayedReveal;
|
|||||||
import forge.game.player.IHasIcon;
|
import forge.game.player.IHasIcon;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbilityView;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.gui.FNetOverlay;
|
|
||||||
import forge.gui.GuiChoose;
|
import forge.gui.GuiChoose;
|
||||||
import forge.gui.GuiDialog;
|
import forge.gui.GuiDialog;
|
||||||
import forge.gui.GuiUtils;
|
import forge.gui.GuiUtils;
|
||||||
@@ -78,9 +76,9 @@ import forge.interfaces.IButton;
|
|||||||
import forge.item.InventoryItem;
|
import forge.item.InventoryItem;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.match.AbstractGuiGame;
|
import forge.match.AbstractGuiGame;
|
||||||
|
import forge.match.MatchButtonType;
|
||||||
import forge.menus.IMenuProvider;
|
import forge.menus.IMenuProvider;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.player.PlayerControllerHuman;
|
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.match.controllers.CAntes;
|
import forge.screens.match.controllers.CAntes;
|
||||||
@@ -103,6 +101,7 @@ import forge.toolbox.FSkin.SkinImage;
|
|||||||
import forge.toolbox.MouseTriggerEvent;
|
import forge.toolbox.MouseTriggerEvent;
|
||||||
import forge.toolbox.special.PhaseIndicator;
|
import forge.toolbox.special.PhaseIndicator;
|
||||||
import forge.toolbox.special.PhaseLabel;
|
import forge.toolbox.special.PhaseLabel;
|
||||||
|
import forge.trackable.TrackableCollection;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
import forge.util.gui.SOptionPane;
|
import forge.util.gui.SOptionPane;
|
||||||
@@ -183,6 +182,21 @@ public final class CMatchUI
|
|||||||
public void setGameView(final GameView gameView) {
|
public void setGameView(final GameView gameView) {
|
||||||
super.setGameView(gameView);
|
super.setGameView(gameView);
|
||||||
screen.setTabCaption(gameView.getTitle());
|
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
|
@Override
|
||||||
@@ -248,7 +262,7 @@ public final class CMatchUI
|
|||||||
view.getLblAvatar().getResizeTimer().start();
|
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.sortedPlayers = sortedPlayers;
|
||||||
this.setLocalPlayers(myPlayers);
|
this.setLocalPlayers(myPlayers);
|
||||||
allHands = sortedPlayers.size() == getLocalPlayerCount();
|
allHands = sortedPlayers.size() == getLocalPlayerCount();
|
||||||
@@ -356,7 +370,7 @@ public final class CMatchUI
|
|||||||
@Override
|
@Override
|
||||||
public final boolean stopAtPhase(final PlayerView turn, final PhaseType phase) {
|
public final boolean stopAtPhase(final PlayerView turn, final PhaseType phase) {
|
||||||
final VField vf = getFieldViewFor(turn);
|
final VField vf = getFieldViewFor(turn);
|
||||||
final PhaseLabel label = vf.getPhaseIndicator() .getLabelFor(phase);
|
final PhaseLabel label = vf.getPhaseIndicator().getLabelFor(phase);
|
||||||
return label == null || label.getEnabled();
|
return label == null || label.getEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,12 +555,6 @@ public final class CMatchUI
|
|||||||
return panels;
|
return panels;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean resetForNewGame() {
|
|
||||||
FloatingCardArea.closeAll();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IButton getBtnOK(final PlayerView playerView) {
|
public IButton getBtnOK(final PlayerView playerView) {
|
||||||
return view.getBtnOK();
|
return view.getBtnOK();
|
||||||
@@ -558,13 +566,15 @@ public final class CMatchUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusButton(final IButton button) {
|
public void focusButton(final MatchButtonType button) {
|
||||||
// ensure we don't steal focus from an overlay
|
// ensure we don't steal focus from an overlay
|
||||||
if (!SOverlayUtils.overlayHasFocus()) {
|
if (!SOverlayUtils.overlayHasFocus()) {
|
||||||
FThreads.invokeInEdtLater(new Runnable() {
|
FThreads.invokeInEdtLater(new Runnable() {
|
||||||
@Override
|
@Override public final void run() {
|
||||||
public void run() {
|
final FButton btn = button == MatchButtonType.OK
|
||||||
((FButton)button).requestFocusInWindow();
|
? getCPrompt().getView().getBtnOK()
|
||||||
|
: getCPrompt().getView().getBtnCancel();
|
||||||
|
btn.requestFocusInWindow();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -579,7 +589,7 @@ public final class CMatchUI
|
|||||||
public void updatePhase() {
|
public void updatePhase() {
|
||||||
final PlayerView p = getGameView().getPlayerTurn();
|
final PlayerView p = getGameView().getPlayerTurn();
|
||||||
final PhaseType ph = getGameView().getPhase();
|
final PhaseType ph = getGameView().getPhase();
|
||||||
PhaseLabel lbl = getFieldViewFor(p).getPhaseIndicator().getLabelFor(ph);
|
final PhaseLabel lbl = p == null ? null : getFieldViewFor(p).getPhaseIndicator().getLabelFor(ph);
|
||||||
|
|
||||||
resetAllPhaseButtons();
|
resetAllPhaseButtons();
|
||||||
if (lbl != null) {
|
if (lbl != null) {
|
||||||
@@ -629,8 +639,12 @@ public final class CMatchUI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateStack() {
|
public void updateStack() {
|
||||||
|
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||||
|
@Override public final void run() {
|
||||||
getCStack().update();
|
getCStack().update();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear all visually highlighted card panels on the battlefield.
|
* Clear all visually highlighted card panels on the battlefield.
|
||||||
@@ -664,7 +678,7 @@ public final class CMatchUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SpellAbility getAbilityToPlay(List<SpellAbility> abilities, ITriggerEvent triggerEvent) {
|
public SpellAbilityView getAbilityToPlay(final List<SpellAbilityView> abilities, final ITriggerEvent triggerEvent) {
|
||||||
if (triggerEvent == null) {
|
if (triggerEvent == null) {
|
||||||
if (abilities.isEmpty()) {
|
if (abilities.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
@@ -691,7 +705,7 @@ public final class CMatchUI
|
|||||||
boolean enabled;
|
boolean enabled;
|
||||||
boolean hasEnabled = false;
|
boolean hasEnabled = false;
|
||||||
int shortcut = KeyEvent.VK_1; //use number keys as shortcuts for abilities 1-9
|
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();
|
enabled = ab.canPlay();
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
hasEnabled = true;
|
hasEnabled = true;
|
||||||
@@ -763,12 +777,7 @@ public final class CMatchUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hear(LobbyPlayer player, String message) {
|
public void openView(final TrackableCollection<PlayerView> myPlayers) {
|
||||||
FNetOverlay.SINGLETON_INSTANCE.addMessage(player.getName(), message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void openView(final Iterable<PlayerView> myPlayers) {
|
|
||||||
final GameView gameView = getGameView();
|
final GameView gameView = getGameView();
|
||||||
gameView.getGameLog().addObserver(getCLog());
|
gameView.getGameLog().addObserver(getCLog());
|
||||||
|
|
||||||
@@ -841,16 +850,14 @@ public final class CMatchUI
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
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) {
|
if (isOptional) {
|
||||||
return oneOrNone(title, gameEntityViews);
|
return oneOrNone(title, optionList);
|
||||||
}
|
}
|
||||||
return one(title, gameEntityViews);
|
return one(title, optionList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package forge.screens.match;
|
package forge.screens.match;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.swing.SwingUtilities;
|
import javax.swing.SwingUtilities;
|
||||||
@@ -91,21 +92,49 @@ public class VMatchUI implements IVTopLevelUI {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add extra hands to existing hand panel.
|
// Determine (an) existing hand panel
|
||||||
for (int i = 1; i < lstHands.size(); i++) {
|
DragCell cellWithHands = null;
|
||||||
// If already in layout, no need to add again.
|
for (final EDocID handId : EDocID.Hands) {
|
||||||
if (lstHands.get(i).getParentCell() == null) { // if i == 0, we get NPE in two lines
|
cellWithHands = handId.getDoc().getParentCell();
|
||||||
DragCell cellWithHand = lstHands.get(0).getParentCell();
|
if (cellWithHands != null) {
|
||||||
cellWithHand.addDoc(lstHands.get(i));
|
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
|
if (myVHand == null) {
|
||||||
for (int i = EDocID.Hands.length - 1; i >= lstHands.size(); i--) {
|
// Hand not present, remove cell if necessary
|
||||||
DragCell cellWithHand = EDocID.Hands[i].getDoc().getParentCell();
|
if (parentCell != null) {
|
||||||
if (cellWithHand != null) {
|
parentCell.removeDoc(handId.getDoc());
|
||||||
cellWithHand.removeDoc(EDocID.Hands[i].getDoc());
|
handId.setDoc(new VEmptyDoc(handId));
|
||||||
EDocID.Hands[i].setDoc(new VEmptyDoc(EDocID.Hands[i]));
|
}
|
||||||
|
} 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 java.util.Iterator;
|
||||||
|
|
||||||
import com.google.common.collect.Iterators;
|
import com.google.common.collect.Iterators;
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
|
||||||
import forge.Singletons;
|
import forge.Singletons;
|
||||||
import forge.UiCommand;
|
import forge.UiCommand;
|
||||||
@@ -130,7 +131,8 @@ public class CDock implements ICDoc {
|
|||||||
public void initialize() {
|
public void initialize() {
|
||||||
final String temp = FModel.getPreferences()
|
final String temp = FModel.getPreferences()
|
||||||
.getPref(FPref.UI_TARGETING_OVERLAY);
|
.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();
|
refreshArcStateDisplay();
|
||||||
|
|
||||||
view.getBtnConcede().setCommand(new UiCommand() {
|
view.getBtnConcede().setCommand(new UiCommand() {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import forge.UiCommand;
|
|||||||
import forge.game.GameView;
|
import forge.game.GameView;
|
||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbilityView;
|
||||||
import forge.gui.framework.ICDoc;
|
import forge.gui.framework.ICDoc;
|
||||||
import forge.gui.framework.SDisplayUtil;
|
import forge.gui.framework.SDisplayUtil;
|
||||||
import forge.screens.match.CMatchUI;
|
import forge.screens.match.CMatchUI;
|
||||||
@@ -120,7 +120,7 @@ public class CPrompt implements ICDoc {
|
|||||||
return matchUI.getGameController().selectCard(cardView, otherCardViewsToSelect, triggerEvent);
|
return matchUI.getGameController().selectCard(cardView, otherCardViewsToSelect, triggerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectAbility(final SpellAbility sa) {
|
public void selectAbility(final SpellAbilityView sa) {
|
||||||
matchUI.getGameController().selectAbility(sa);
|
matchUI.getGameController().selectAbility(sa);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,22 @@
|
|||||||
package forge.toolbox;
|
package forge.toolbox;
|
||||||
|
|
||||||
import forge.interfaces.IComboBox;
|
import java.awt.Container;
|
||||||
import forge.toolbox.FComboBox.TextAlignment;
|
|
||||||
import forge.toolbox.FSkin.SkinFont;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
import java.awt.event.ItemListener;
|
import java.awt.event.ItemListener;
|
||||||
import java.awt.event.KeyListener;
|
import java.awt.event.KeyListener;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Vector;
|
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)
|
* 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 FComboBox<E> comboBox;
|
||||||
|
private ActionListener[] suppressedActionListeners = null;
|
||||||
private Object constraints;
|
private Object constraints;
|
||||||
|
|
||||||
public FComboBoxWrapper() {
|
public FComboBoxWrapper() {
|
||||||
@@ -111,6 +116,24 @@ public class FComboBoxWrapper<E> implements IComboBox<E> {
|
|||||||
comboBox.addItemListener(l);
|
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) {
|
public void addKeyListener(KeyListener l) {
|
||||||
comboBox.addKeyListener(l);
|
comboBox.addKeyListener(l);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package forge.toolbox;
|
package forge.toolbox;
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
|
|
||||||
//MouseEvent wrapper used for passing trigger to input classes
|
//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;
|
private final MouseEvent event;
|
||||||
|
|
||||||
public MouseTriggerEvent(MouseEvent event0) {
|
public MouseTriggerEvent(MouseEvent event0) {
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
package forge.gamesimulationtests.util;
|
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.base.Predicate;
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
@@ -27,6 +35,7 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardShields;
|
import forge.game.card.CardShields;
|
||||||
|
import forge.game.card.CardView;
|
||||||
import forge.game.card.CounterType;
|
import forge.game.card.CounterType;
|
||||||
import forge.game.combat.Combat;
|
import forge.game.combat.Combat;
|
||||||
import forge.game.combat.CombatUtil;
|
import forge.game.combat.CombatUtil;
|
||||||
@@ -39,8 +48,13 @@ import forge.game.player.DelayedReveal;
|
|||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
import forge.game.player.PlayerController;
|
import forge.game.player.PlayerController;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.replacement.ReplacementEffect;
|
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.Trigger;
|
||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
import forge.game.zone.ZoneType;
|
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.card.CardSpecificationHandler;
|
||||||
import forge.gamesimulationtests.util.player.PlayerSpecification;
|
import forge.gamesimulationtests.util.player.PlayerSpecification;
|
||||||
import forge.gamesimulationtests.util.player.PlayerSpecificationHandler;
|
import forge.gamesimulationtests.util.player.PlayerSpecificationHandler;
|
||||||
import forge.gamesimulationtests.util.playeractions.*;
|
import forge.gamesimulationtests.util.playeractions.ActivateAbilityAction;
|
||||||
import forge.player.HumanPlay;
|
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.item.PaperCard;
|
||||||
|
import forge.player.HumanPlay;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
import forge.util.MyRandom;
|
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.
|
* Default harmless implementation for tests.
|
||||||
* Test-specific behaviour can easily be added by mocking (parts of) this class.
|
* Test-specific behaviour can easily be added by mocking (parts of) this class.
|
||||||
@@ -166,7 +179,7 @@ public class PlayerControllerForTests extends PlayerController {
|
|||||||
@Override
|
@Override
|
||||||
public <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, DelayedReveal delayedReveal, SpellAbility sa, String title, boolean isOptional, Player targetedPlayer) {
|
public <T extends GameEntity> T chooseSingleEntityForEffect(FCollectionView<T> optionList, DelayedReveal delayedReveal, SpellAbility sa, String title, boolean isOptional, Player targetedPlayer) {
|
||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
delayedReveal.reveal(this);
|
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||||
}
|
}
|
||||||
return chooseItem(optionList);
|
return chooseItem(optionList);
|
||||||
}
|
}
|
||||||
@@ -224,6 +237,11 @@ public class PlayerControllerForTests extends PlayerController {
|
|||||||
//nothing needs to be done here
|
//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
|
@Override
|
||||||
public void notifyOfValue(SpellAbility saSource, GameObject realtedTarget, String value) {
|
public void notifyOfValue(SpellAbility saSource, GameObject realtedTarget, String value) {
|
||||||
//nothing needs to be done here
|
//nothing needs to be done here
|
||||||
@@ -628,7 +646,7 @@ public class PlayerControllerForTests extends PlayerController {
|
|||||||
String selectPrompt, boolean isOptional, Player decider) {
|
String selectPrompt, boolean isOptional, Player decider) {
|
||||||
|
|
||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
delayedReveal.reveal(this);
|
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||||
}
|
}
|
||||||
return ChangeZoneAi.chooseCardToHiddenOriginChangeZone(destination, origin, sa, fetchList, player, decider);
|
return ChangeZoneAi.chooseCardToHiddenOriginChangeZone(destination, origin, sa, fetchList, player, decider);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -288,7 +288,4 @@ public class GuiMobile implements IGuiBase {
|
|||||||
return Forge.hostedMatch = new HostedMatch();
|
return Forge.hostedMatch = new HostedMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void netMessage(final String origin, final String message) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import forge.util.Callback;
|
|||||||
public class GameEntityPicker extends TabPageScreen<GameEntityPicker> {
|
public class GameEntityPicker extends TabPageScreen<GameEntityPicker> {
|
||||||
private final FOptionPane optionPane;
|
private final FOptionPane optionPane;
|
||||||
|
|
||||||
public GameEntityPicker(String title, List<GameEntityView> choiceList, List<CardView> revealList, String revealListCaption, FImage revealListImage, boolean isOptional, final Callback<GameEntityView> callback) {
|
public GameEntityPicker(String title, Collection<? extends GameEntityView> choiceList, Collection<CardView> revealList, String revealListCaption, FImage revealListImage, boolean isOptional, final Callback<GameEntityView> callback) {
|
||||||
super(new PickerTab[] {
|
super(new PickerTab[] {
|
||||||
new PickerTab(choiceList, "Choices", FSkinImage.DECKLIST, 1),
|
new PickerTab(choiceList, "Choices", FSkinImage.DECKLIST, 1),
|
||||||
new PickerTab(revealList, revealListCaption, revealListImage, 0)
|
new PickerTab(revealList, revealListCaption, revealListImage, 0)
|
||||||
|
|||||||
@@ -124,10 +124,6 @@ public class FMenuItem extends FDisplayObject implements IButton {
|
|||||||
g.drawLine(1, SEPARATOR_COLOR, 0, h, w, h);
|
g.drawLine(1, SEPARATOR_COLOR, 0, h, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getText() {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
@Override
|
@Override
|
||||||
public void setText(String text0) {
|
public void setText(String text0) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ public class ConstructedScreen extends LaunchScreen {
|
|||||||
PlayerPanel playerPanel = playerPanels.get(i);
|
PlayerPanel playerPanel = playerPanels.get(i);
|
||||||
String name = getPlayerName(i);
|
String name = getPlayerName(i);
|
||||||
LobbyPlayer lobbyPlayer = playerPanel.isPlayerAI() ? GamePlayerUtil.createAiPlayer(name,
|
LobbyPlayer lobbyPlayer = playerPanel.isPlayerAI() ? GamePlayerUtil.createAiPlayer(name,
|
||||||
getPlayerAvatar(i)) : GamePlayerUtil.getGuiPlayer(name, i);
|
getPlayerAvatar(i)) : GamePlayerUtil.getGuiPlayer(name, i == 0);
|
||||||
RegisteredPlayer rp = playerPanel.deckChooser.getPlayer();
|
RegisteredPlayer rp = playerPanel.deckChooser.getPlayer();
|
||||||
|
|
||||||
if (appliedVariants.isEmpty()) {
|
if (appliedVariants.isEmpty()) {
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import forge.card.CardRenderer;
|
|||||||
import forge.card.GameEntityPicker;
|
import forge.card.GameEntityPicker;
|
||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.deck.FSideboardDialog;
|
import forge.deck.FSideboardDialog;
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GameEntityView;
|
import forge.game.GameEntityView;
|
||||||
import forge.game.GameView;
|
import forge.game.GameView;
|
||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
@@ -34,17 +33,16 @@ import forge.game.phase.PhaseType;
|
|||||||
import forge.game.player.DelayedReveal;
|
import forge.game.player.DelayedReveal;
|
||||||
import forge.game.player.IHasIcon;
|
import forge.game.player.IHasIcon;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbilityView;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.interfaces.IButton;
|
import forge.interfaces.IButton;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.match.AbstractGuiGame;
|
import forge.match.AbstractGuiGame;
|
||||||
|
import forge.match.MatchButtonType;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.player.PlayerControllerHuman;
|
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.match.views.VAssignDamage;
|
import forge.screens.match.views.VAssignDamage;
|
||||||
import forge.screens.match.views.VCardDisplayArea.CardAreaPanel;
|
|
||||||
import forge.screens.match.views.VPhaseIndicator;
|
import forge.screens.match.views.VPhaseIndicator;
|
||||||
import forge.screens.match.views.VPhaseIndicator.PhaseLabel;
|
import forge.screens.match.views.VPhaseIndicator.PhaseLabel;
|
||||||
import forge.screens.match.views.VPlayerPanel;
|
import forge.screens.match.views.VPlayerPanel;
|
||||||
@@ -53,6 +51,7 @@ import forge.screens.match.views.VPrompt;
|
|||||||
import forge.screens.match.winlose.ViewWinLose;
|
import forge.screens.match.winlose.ViewWinLose;
|
||||||
import forge.toolbox.FDisplayObject;
|
import forge.toolbox.FDisplayObject;
|
||||||
import forge.toolbox.FOptionPane;
|
import forge.toolbox.FOptionPane;
|
||||||
|
import forge.trackable.TrackableCollection;
|
||||||
import forge.util.FCollectionView;
|
import forge.util.FCollectionView;
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
import forge.util.MessageUtil;
|
import forge.util.MessageUtil;
|
||||||
@@ -102,18 +101,12 @@ public class MatchController extends AbstractGuiGame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean resetForNewGame() {
|
|
||||||
CardAreaPanel.resetForNewGame(); //ensure card panels reset between games
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hotSeatMode() {
|
public boolean hotSeatMode() {
|
||||||
return FModel.getPreferences().getPrefBoolean(FPref.MATCH_HOT_SEAT_MODE);
|
return FModel.getPreferences().getPrefBoolean(FPref.MATCH_HOT_SEAT_MODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void openView(final Iterable<PlayerView> myPlayers) {
|
public void openView(final TrackableCollection<PlayerView> myPlayers) {
|
||||||
setLocalPlayers(myPlayers);
|
setLocalPlayers(myPlayers);
|
||||||
final boolean noHumans = !hasLocalPlayers();
|
final boolean noHumans = !hasLocalPlayers();
|
||||||
|
|
||||||
@@ -162,7 +155,7 @@ public class MatchController extends AbstractGuiGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void focusButton(final IButton button) {
|
public void focusButton(final MatchButtonType button) {
|
||||||
//not needed for mobile game
|
//not needed for mobile game
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +221,7 @@ public class MatchController extends AbstractGuiGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SpellAbility getAbilityToPlay(List<SpellAbility> abilities, ITriggerEvent triggerEvent) {
|
public SpellAbilityView getAbilityToPlay(List<SpellAbilityView> abilities, ITriggerEvent triggerEvent) {
|
||||||
if (abilities.isEmpty()) {
|
if (abilities.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -324,10 +317,6 @@ public class MatchController extends AbstractGuiGame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void hear(LobbyPlayer player, String message) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean stopAtPhase(PlayerView turn, PhaseType phase) {
|
public boolean stopAtPhase(PlayerView turn, PhaseType phase) {
|
||||||
return view.stopAtPhase(turn, phase);
|
return view.stopAtPhase(turn, phase);
|
||||||
@@ -475,27 +464,23 @@ public class MatchController extends AbstractGuiGame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
||||||
controller.tempShow(optionList);
|
|
||||||
final List<GameEntityView> choiceList = GameEntityView.getEntityCollection(optionList);
|
|
||||||
|
|
||||||
if (delayedReveal == null || Iterables.isEmpty(delayedReveal.getCards())) {
|
if (delayedReveal == null || Iterables.isEmpty(delayedReveal.getCards())) {
|
||||||
if (isOptional) {
|
if (isOptional) {
|
||||||
return SGuiChoose.oneOrNone(title, choiceList);
|
return SGuiChoose.oneOrNone(title, optionList);
|
||||||
}
|
}
|
||||||
return SGuiChoose.one(title, choiceList);
|
return SGuiChoose.one(title, optionList);
|
||||||
}
|
}
|
||||||
|
|
||||||
controller.tempShow(delayedReveal.getCards());
|
final Collection<CardView> revealList = delayedReveal.getCards();
|
||||||
final List<CardView> revealList = CardView.getCollection(delayedReveal.getCards());
|
final String revealListCaption = StringUtils.capitalize(MessageUtil.formatMessage("{player's} " + delayedReveal.getZone().name(), delayedReveal.getOwner(), delayedReveal.getOwner()));
|
||||||
final String revealListCaption = StringUtils.capitalize(MessageUtil.formatMessage("{player's} " + delayedReveal.getZone().name(), controller.getPlayer(), delayedReveal.getOwner()));
|
|
||||||
final FImage revealListImage = MatchController.getView().getPlayerPanels().values().iterator().next().getZoneTab(delayedReveal.getZone()).getIcon();
|
final FImage revealListImage = MatchController.getView().getPlayerPanels().values().iterator().next().getZoneTab(delayedReveal.getZone()).getIcon();
|
||||||
|
|
||||||
//use special dialog for choosing card and offering ability to see all revealed cards at the same time
|
//use special dialog for choosing card and offering ability to see all revealed cards at the same time
|
||||||
return new WaitCallback<GameEntityView>() {
|
return new WaitCallback<GameEntityView>() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
GameEntityPicker picker = new GameEntityPicker(title, choiceList, revealList, revealListCaption, revealListImage, isOptional, this);
|
GameEntityPicker picker = new GameEntityPicker(title, optionList, revealList, revealListCaption, revealListImage, isOptional, this);
|
||||||
picker.show();
|
picker.show();
|
||||||
}
|
}
|
||||||
}.invokeAndWait();
|
}.invokeAndWait();
|
||||||
|
|||||||
@@ -242,6 +242,9 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|||||||
if (ev.player.getGame().isGameOver()) {
|
if (ev.player.getGame().isGameOver()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
if (ev.newController instanceof PlayerControllerHuman) {
|
||||||
|
matchController.setGameController(PlayerView.get(ev.player), (PlayerControllerHuman) ev.newController);
|
||||||
|
}
|
||||||
needPlayerControlUpdate = true;
|
needPlayerControlUpdate = true;
|
||||||
return processEvent();
|
return processEvent();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import forge.LobbyPlayer;
|
|||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbilityView;
|
||||||
import forge.interfaces.IDevModeCheats;
|
import forge.interfaces.IDevModeCheats;
|
||||||
import forge.interfaces.IGuiGame;
|
import forge.interfaces.IGuiGame;
|
||||||
import forge.match.input.Input;
|
import forge.match.input.Input;
|
||||||
@@ -90,7 +90,7 @@ public class WatchLocalGame extends PlayerControllerHuman {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void selectAbility(final SpellAbility sa) {
|
public void selectAbility(final SpellAbilityView sa) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,11 +4,8 @@ import forge.UiCommand;
|
|||||||
import forge.assets.FSkinProp;
|
import forge.assets.FSkinProp;
|
||||||
|
|
||||||
public interface IButton {
|
public interface IButton {
|
||||||
boolean isEnabled();
|
|
||||||
void setEnabled(boolean b0);
|
void setEnabled(boolean b0);
|
||||||
boolean isVisible();
|
|
||||||
void setVisible(boolean b0);
|
void setVisible(boolean b0);
|
||||||
String getText();
|
|
||||||
void setText(String text0);
|
void setText(String text0);
|
||||||
boolean isSelected();
|
boolean isSelected();
|
||||||
void setSelected(boolean b0);
|
void setSelected(boolean b0);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import java.util.List;
|
|||||||
|
|
||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbilityView;
|
||||||
import forge.match.NextGameDecision;
|
import forge.match.NextGameDecision;
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ public interface IGameController {
|
|||||||
boolean selectCard(CardView cardView,
|
boolean selectCard(CardView cardView,
|
||||||
List<CardView> otherCardViewsToSelect, ITriggerEvent triggerEvent);
|
List<CardView> otherCardViewsToSelect, ITriggerEvent triggerEvent);
|
||||||
|
|
||||||
void selectAbility(SpellAbility sa);
|
void selectAbility(SpellAbilityView sa);
|
||||||
|
|
||||||
boolean tryUndoLastAction();
|
boolean tryUndoLastAction();
|
||||||
|
|
||||||
|
|||||||
@@ -51,5 +51,4 @@ public interface IGuiBase {
|
|||||||
void showBazaar();
|
void showBazaar();
|
||||||
IGuiGame getNewGuiGame();
|
IGuiGame getNewGuiGame();
|
||||||
HostedMatch hostMatch();
|
HostedMatch hostMatch();
|
||||||
void netMessage(String origin, String message);
|
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,6 @@ import com.google.common.base.Function;
|
|||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.assets.FSkinProp;
|
import forge.assets.FSkinProp;
|
||||||
import forge.deck.CardPool;
|
import forge.deck.CardPool;
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GameEntityView;
|
import forge.game.GameEntityView;
|
||||||
import forge.game.GameView;
|
import forge.game.GameView;
|
||||||
import forge.game.card.CardView;
|
import forge.game.card.CardView;
|
||||||
@@ -19,25 +18,24 @@ import forge.game.phase.PhaseType;
|
|||||||
import forge.game.player.DelayedReveal;
|
import forge.game.player.DelayedReveal;
|
||||||
import forge.game.player.IHasIcon;
|
import forge.game.player.IHasIcon;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbilityView;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
import forge.player.PlayerControllerHuman;
|
import forge.match.MatchButtonType;
|
||||||
import forge.util.FCollectionView;
|
import forge.trackable.TrackableCollection;
|
||||||
import forge.util.ITriggerEvent;
|
import forge.util.ITriggerEvent;
|
||||||
|
|
||||||
public interface IGuiGame {
|
public interface IGuiGame {
|
||||||
void setGameView(GameView gameView);
|
void setGameView(GameView gameView);
|
||||||
void setGameController(PlayerView player, IGameController gameController);
|
void setGameController(PlayerView player, IGameController gameController);
|
||||||
boolean resetForNewGame();
|
void openView(TrackableCollection<PlayerView> myPlayers);
|
||||||
void openView(Iterable<PlayerView> myPlayers);
|
|
||||||
void afterGameEnd();
|
void afterGameEnd();
|
||||||
void showCombat();
|
void showCombat();
|
||||||
void showPromptMessage(PlayerView playerView, String message);
|
void showPromptMessage(PlayerView playerView, String message);
|
||||||
boolean stopAtPhase(PlayerView playerTurn, PhaseType phase);
|
boolean stopAtPhase(PlayerView playerTurn, PhaseType phase);
|
||||||
IButton getBtnOK(PlayerView playerView);
|
IButton getBtnOK(PlayerView playerView);
|
||||||
IButton getBtnCancel(PlayerView playerView);
|
IButton getBtnCancel(PlayerView playerView);
|
||||||
void focusButton(IButton button);
|
void focusButton(MatchButtonType button);
|
||||||
void flashIncorrectAction();
|
void flashIncorrectAction();
|
||||||
void updatePhase();
|
void updatePhase();
|
||||||
void updateTurn(PlayerView player);
|
void updateTurn(PlayerView player);
|
||||||
@@ -54,8 +52,7 @@ public interface IGuiGame {
|
|||||||
void updateManaPool(Iterable<PlayerView> manaPoolUpdate);
|
void updateManaPool(Iterable<PlayerView> manaPoolUpdate);
|
||||||
void updateLives(Iterable<PlayerView> livesUpdate);
|
void updateLives(Iterable<PlayerView> livesUpdate);
|
||||||
void setPanelSelection(CardView hostCard);
|
void setPanelSelection(CardView hostCard);
|
||||||
void hear(LobbyPlayer player, String message);
|
SpellAbilityView getAbilityToPlay(List<SpellAbilityView> abilities,
|
||||||
SpellAbility getAbilityToPlay(List<SpellAbility> abilities,
|
|
||||||
ITriggerEvent triggerEvent);
|
ITriggerEvent triggerEvent);
|
||||||
Map<CardView, Integer> assignDamage(CardView attacker,
|
Map<CardView, Integer> assignDamage(CardView attacker,
|
||||||
List<CardView> blockers, int damage, GameEntityView defender,
|
List<CardView> blockers, int damage, GameEntityView defender,
|
||||||
@@ -161,9 +158,8 @@ public interface IGuiGame {
|
|||||||
|
|
||||||
List<PaperCard> sideboard(CardPool sideboard, CardPool main);
|
List<PaperCard> sideboard(CardPool sideboard, CardPool main);
|
||||||
GameEntityView chooseSingleEntityForEffect(String title,
|
GameEntityView chooseSingleEntityForEffect(String title,
|
||||||
FCollectionView<? extends GameEntity> optionList,
|
Collection<? extends GameEntityView> optionList,
|
||||||
DelayedReveal delayedReveal, boolean isOptional,
|
DelayedReveal delayedReveal, boolean isOptional);
|
||||||
PlayerControllerHuman controller);
|
|
||||||
void setCard(CardView card);
|
void setCard(CardView card);
|
||||||
void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi);
|
void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi);
|
||||||
boolean openZones(Collection<ZoneType> zones, Map<PlayerView, Object> players);
|
boolean openZones(Collection<ZoneType> zones, Map<PlayerView, Object> players);
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package forge.interfaces;
|
package forge.interfaces;
|
||||||
|
|
||||||
import forge.net.game.LobbyState;
|
import forge.match.GameLobby;
|
||||||
import forge.net.game.server.RemoteClient;
|
import forge.net.game.server.RemoteClient;
|
||||||
|
|
||||||
public interface ILobby {
|
public interface ILobby {
|
||||||
LobbyState getState();
|
GameLobby getState();
|
||||||
int login(RemoteClient client);
|
int login(RemoteClient client);
|
||||||
void logout(RemoteClient client);
|
void logout(RemoteClient client);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package forge.interfaces;
|
||||||
|
|
||||||
|
import forge.match.GameLobby.GameLobbyData;
|
||||||
|
|
||||||
|
public interface ILobbyListener {
|
||||||
|
void message(String source, String message);
|
||||||
|
void update(GameLobbyData state, int slot);
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package forge.interfaces;
|
package forge.interfaces;
|
||||||
|
|
||||||
import forge.net.game.LobbyState.LobbyPlayerData;
|
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||||
|
|
||||||
public interface IPlayerChangeListener {
|
public interface IPlayerChangeListener {
|
||||||
void update(LobbyPlayerData data);
|
void update(int index, UpdateLobbyPlayerEvent event);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package forge.interfaces;
|
||||||
|
|
||||||
|
public interface IUpdateable {
|
||||||
|
void update();
|
||||||
|
}
|
||||||
@@ -210,9 +210,9 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
|
|||||||
btnOk.setEnabled(okEnabled);
|
btnOk.setEnabled(okEnabled);
|
||||||
btnCancel.setEnabled(cancelEnabled);
|
btnCancel.setEnabled(cancelEnabled);
|
||||||
if (okEnabled && focusOk) {
|
if (okEnabled && focusOk) {
|
||||||
focusButton(btnOk);
|
focusButton(MatchButtonType.OK);
|
||||||
} else if (cancelEnabled) {
|
} else if (cancelEnabled) {
|
||||||
focusButton(btnCancel);
|
focusButton(MatchButtonType.CANCEL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
442
forge-gui/src/main/java/forge/match/GameLobby.java
Normal file
442
forge-gui/src/main/java/forge/match/GameLobby.java
Normal file
@@ -0,0 +1,442 @@
|
|||||||
|
package forge.match;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.EnumSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.primitives.Ints;
|
||||||
|
|
||||||
|
import forge.AIOption;
|
||||||
|
import forge.GuiBase;
|
||||||
|
import forge.LobbyPlayer;
|
||||||
|
import forge.deck.CardPool;
|
||||||
|
import forge.deck.Deck;
|
||||||
|
import forge.deck.DeckFormat;
|
||||||
|
import forge.deck.DeckSection;
|
||||||
|
import forge.game.GameType;
|
||||||
|
import forge.game.GameView;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.player.RegisteredPlayer;
|
||||||
|
import forge.interfaces.IGameController;
|
||||||
|
import forge.interfaces.IGuiGame;
|
||||||
|
import forge.interfaces.IUpdateable;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.net.game.LobbySlotType;
|
||||||
|
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||||
|
import forge.player.GamePlayerUtil;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
|
import forge.util.NameGenerator;
|
||||||
|
import forge.util.gui.SOptionPane;
|
||||||
|
|
||||||
|
public abstract class GameLobby {
|
||||||
|
private final static int MAX_PLAYERS = 8;
|
||||||
|
|
||||||
|
private GameLobbyData data = new GameLobbyData();
|
||||||
|
private int lastArchenemy = 0;
|
||||||
|
|
||||||
|
private IUpdateable listener;
|
||||||
|
|
||||||
|
private final boolean allowNetworking;
|
||||||
|
private HostedMatch hostedMatch;
|
||||||
|
private final Map<LobbySlot, IGameController> gameControllers = Maps.newHashMap();
|
||||||
|
protected GameLobby(final boolean allowNetworking) {
|
||||||
|
this.allowNetworking = allowNetworking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final boolean isAllowNetworking() {
|
||||||
|
return allowNetworking;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListener(final IUpdateable listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameLobbyData getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
public void setData(final GameLobbyData data) {
|
||||||
|
this.data = data;
|
||||||
|
updateView();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameType getGameType() {
|
||||||
|
return data.currentGameMode;
|
||||||
|
}
|
||||||
|
public void setGameType(final GameType type) {
|
||||||
|
data.currentGameMode = type;
|
||||||
|
updateView();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasVariant(final GameType variant) {
|
||||||
|
return data.appliedVariants.contains(variant);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumberOfSlots() {
|
||||||
|
return data.slots.size();
|
||||||
|
}
|
||||||
|
public LobbySlot getSlot(final int index) {
|
||||||
|
if (index < 0 || index >= getNumberOfSlots()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return data.slots.get(index);
|
||||||
|
}
|
||||||
|
public void applyToSlot(final int index, final UpdateLobbyPlayerEvent event) {
|
||||||
|
final LobbySlot slot = getSlot(index);
|
||||||
|
if (slot == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
|
|
||||||
|
final int nSlots = getNumberOfSlots();
|
||||||
|
final boolean triesToChangeArchenemy = event.getArchenemy() != null;
|
||||||
|
final boolean archenemyRemoved = triesToChangeArchenemy && !event.getArchenemy().booleanValue();
|
||||||
|
final boolean hasArchenemyChanged = triesToChangeArchenemy && slot.isArchenemy() != event.getArchenemy().booleanValue();
|
||||||
|
slot.apply(event);
|
||||||
|
|
||||||
|
// Change archenemy teams
|
||||||
|
if (hasVariant(GameType.Archenemy) && hasArchenemyChanged) {
|
||||||
|
final int newArchenemy = archenemyRemoved ? lastArchenemy : index;
|
||||||
|
if (archenemyRemoved) {
|
||||||
|
lastArchenemy = index;
|
||||||
|
}
|
||||||
|
for (int otherIndex = 0; otherIndex < nSlots; otherIndex++) {
|
||||||
|
final LobbySlot otherSlot = getSlot(otherIndex);
|
||||||
|
final boolean becomesArchenemy = otherIndex == newArchenemy;
|
||||||
|
if (!archenemyRemoved && otherSlot.isArchenemy() && !becomesArchenemy) {
|
||||||
|
lastArchenemy = otherIndex;
|
||||||
|
}
|
||||||
|
otherSlot.setIsArchenemy(becomesArchenemy);
|
||||||
|
}
|
||||||
|
updateView();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IGameController getController(final int index) {
|
||||||
|
return gameControllers.get(getSlot(index));
|
||||||
|
}
|
||||||
|
public GameView getGameView() {
|
||||||
|
return hostedMatch.getGameView();
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract boolean hasControl();
|
||||||
|
public abstract boolean mayEdit(final int index);
|
||||||
|
public abstract boolean mayControl(final int index);
|
||||||
|
public abstract boolean mayRemove(final int index);
|
||||||
|
public abstract IGuiGame getGui(final int index);
|
||||||
|
|
||||||
|
public void addSlot() {
|
||||||
|
final int newIndex = getNumberOfSlots();
|
||||||
|
addSlot(new LobbySlot(allowNetworking ? LobbySlotType.OPEN : LobbySlotType.LOCAL, null, newIndex, newIndex, false, Collections.<AIOption>emptySet()));
|
||||||
|
}
|
||||||
|
protected final void addSlot(final LobbySlot slot) {
|
||||||
|
if (data.slots.size() >= MAX_PLAYERS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.slots.add(slot);
|
||||||
|
if (StringUtils.isEmpty(slot.getName())) {
|
||||||
|
slot.setName(randomName());
|
||||||
|
}
|
||||||
|
if (data.slots.size() == 1) {
|
||||||
|
// If first slot, make archenemy
|
||||||
|
slot.setIsArchenemy(true);
|
||||||
|
lastArchenemy = 0;
|
||||||
|
}
|
||||||
|
updateView();
|
||||||
|
}
|
||||||
|
private String randomName() {
|
||||||
|
final List<String> names = Lists.newArrayListWithCapacity(MAX_PLAYERS);
|
||||||
|
for (final LobbySlot slot : data.slots) {
|
||||||
|
names.add(slot.getName());
|
||||||
|
}
|
||||||
|
return NameGenerator.getRandomName("Any", "Any", names);
|
||||||
|
}
|
||||||
|
protected final String localName() {
|
||||||
|
return FModel.getPreferences().getPref(FPref.PLAYER_NAME);
|
||||||
|
}
|
||||||
|
protected final int[] localAvatarIndices() {
|
||||||
|
final String[] sAvatars = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");
|
||||||
|
final int[] result = new int[sAvatars.length];
|
||||||
|
for (int i = 0; i < sAvatars.length; i++) {
|
||||||
|
final Integer val = Ints.tryParse(sAvatars[i]);
|
||||||
|
result[i] = val == null ? -1 : val.intValue();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSlot(final int index) {
|
||||||
|
if (index < 0 || index >= data.slots.size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getSlot(index).isArchenemy()) {
|
||||||
|
getSlot(lastArchenemy).setIsArchenemy(true);
|
||||||
|
// Should actually be a stack here, but that's rather involved for
|
||||||
|
// such a nonimportant feature
|
||||||
|
lastArchenemy = 0;
|
||||||
|
} else if (lastArchenemy == index) {
|
||||||
|
lastArchenemy = 0;
|
||||||
|
} else {
|
||||||
|
lastArchenemy--;
|
||||||
|
}
|
||||||
|
data.slots.remove(index);
|
||||||
|
updateView();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyVariant(final GameType variant) {
|
||||||
|
data.currentGameMode = variant;
|
||||||
|
data.appliedVariants.add(variant);
|
||||||
|
|
||||||
|
//ensure other necessary variants are unchecked
|
||||||
|
switch (variant) {
|
||||||
|
case Archenemy:
|
||||||
|
data.appliedVariants.remove(GameType.ArchenemyRumble);
|
||||||
|
break;
|
||||||
|
case ArchenemyRumble:
|
||||||
|
data.appliedVariants.remove(GameType.Archenemy);
|
||||||
|
break;
|
||||||
|
case Commander:
|
||||||
|
data.appliedVariants.remove(GameType.TinyLeaders);
|
||||||
|
data.appliedVariants.remove(GameType.MomirBasic);
|
||||||
|
break;
|
||||||
|
case TinyLeaders:
|
||||||
|
data.appliedVariants.remove(GameType.Commander);
|
||||||
|
data.appliedVariants.remove(GameType.MomirBasic);
|
||||||
|
break;
|
||||||
|
case Vanguard:
|
||||||
|
data.appliedVariants.remove(GameType.MomirBasic);
|
||||||
|
break;
|
||||||
|
case MomirBasic:
|
||||||
|
data.appliedVariants.remove(GameType.Commander);
|
||||||
|
data.appliedVariants.remove(GameType.Vanguard);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
updateView();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeVariant(final GameType variant) {
|
||||||
|
data.appliedVariants.remove(variant);
|
||||||
|
if (data.appliedVariants.isEmpty()) {
|
||||||
|
data.appliedVariants.add(GameType.Constructed);
|
||||||
|
}
|
||||||
|
updateView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEnoughTeams() {
|
||||||
|
int lastTeam = -1;
|
||||||
|
final boolean useArchenemyTeams = data.appliedVariants.contains(GameType.Archenemy);
|
||||||
|
for (final LobbySlot slot : data.slots) {
|
||||||
|
final int team = useArchenemyTeams ? (slot.isArchenemy() ? 0 : 1) : slot.getTeam();
|
||||||
|
if (lastTeam == -1) {
|
||||||
|
lastTeam = team;
|
||||||
|
} else if (lastTeam != team) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final void updateView() {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Starts a match with the applied variants. */
|
||||||
|
public void startGame() {
|
||||||
|
if (!isEnoughTeams()) {
|
||||||
|
SOptionPane.showMessageDialog("There are not enough teams! Please adjust team allocations.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<LobbySlot> activeSlots = Lists.newArrayListWithCapacity(getNumberOfSlots());
|
||||||
|
for (final LobbySlot slot : data.getSlots()) {
|
||||||
|
if (slot.getType() != LobbySlotType.OPEN) {
|
||||||
|
activeSlots.add(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final LobbySlot slot : activeSlots) {
|
||||||
|
if (slot.getDeck() == null) {
|
||||||
|
SOptionPane.showMessageDialog(String.format("Please specify a deck for %s", slot.getName()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Set<GameType> variantTypes = data.appliedVariants;
|
||||||
|
|
||||||
|
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 (final 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 LobbySlot slot : activeSlots) {
|
||||||
|
final String name = slot.getName();
|
||||||
|
String errMsg = GameType.Constructed.getDeckFormat().getDeckConformanceProblem(slot.getDeck());
|
||||||
|
if (null != errMsg) {
|
||||||
|
SOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid Deck");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<RegisteredPlayer> players = new ArrayList<RegisteredPlayer>();
|
||||||
|
final Map<RegisteredPlayer, IGuiGame> guis = Maps.newHashMap();
|
||||||
|
final Map<RegisteredPlayer, LobbySlot> playerToSlot = Maps.newHashMap();
|
||||||
|
boolean hasNameBeenSet = false;
|
||||||
|
for (final LobbySlot slot : activeSlots) {
|
||||||
|
final IGuiGame gui = getGui(data.slots.indexOf(slot));
|
||||||
|
final String name = slot.getName();
|
||||||
|
final int avatar = slot.getAvatarIndex();
|
||||||
|
final int team = slot.getTeam();
|
||||||
|
final boolean isArchenemy = slot.isArchenemy();
|
||||||
|
final Set<AIOption> aiOptions = slot.getAiOptions();
|
||||||
|
|
||||||
|
final boolean isAI = slot.getType() == LobbySlotType.AI;
|
||||||
|
final LobbyPlayer lobbyPlayer;
|
||||||
|
if (isAI) {
|
||||||
|
lobbyPlayer = GamePlayerUtil.createAiPlayer(name, avatar, aiOptions);
|
||||||
|
} else {
|
||||||
|
boolean setNameNow = false;
|
||||||
|
if (!hasNameBeenSet && slot.getType() == LobbySlotType.LOCAL) {
|
||||||
|
setNameNow = true;
|
||||||
|
hasNameBeenSet = true;
|
||||||
|
}
|
||||||
|
lobbyPlayer = GamePlayerUtil.getGuiPlayer(name, setNameNow);
|
||||||
|
}
|
||||||
|
|
||||||
|
Deck deck = slot.getDeck();
|
||||||
|
RegisteredPlayer rp = new RegisteredPlayer(deck);
|
||||||
|
|
||||||
|
if (variantTypes.isEmpty()) {
|
||||||
|
rp.setTeamNumber(team);
|
||||||
|
players.add(rp.setPlayer(lobbyPlayer));
|
||||||
|
} else {
|
||||||
|
PaperCard vanguardAvatar = null;
|
||||||
|
if (isCommanderMatch) {
|
||||||
|
final GameType commanderGameType = isTinyLeadersMatch ? GameType.TinyLeaders : GameType.Commander;
|
||||||
|
if (checkLegality) {
|
||||||
|
String errMsg = commanderGameType.getDeckFormat().getDeckConformanceProblem(deck);
|
||||||
|
if (null != errMsg) {
|
||||||
|
SOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid " + commanderGameType + " Deck");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (autoGenerateVariant != null) {
|
||||||
|
deck = autoGenerateVariant.autoGenerateDeck(rp);
|
||||||
|
final 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;
|
||||||
|
Iterable<PaperCard> planes = null;
|
||||||
|
|
||||||
|
//Archenemy
|
||||||
|
if (variantTypes.contains(GameType.ArchenemyRumble)
|
||||||
|
|| (variantTypes.contains(GameType.Archenemy) && isArchenemy)) {
|
||||||
|
final CardPool schemePool = deck.get(DeckSection.Schemes);
|
||||||
|
if (checkLegality) {
|
||||||
|
String errMsg = DeckFormat.getSchemeSectionConformanceProblem(schemePool);
|
||||||
|
if (null != errMsg) {
|
||||||
|
SOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid Scheme Deck");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
schemes = schemePool.toFlatList();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Planechase
|
||||||
|
if (variantTypes.contains(GameType.Planechase)) {
|
||||||
|
final CardPool planePool = deck.get(DeckSection.Planes);
|
||||||
|
if (checkLegality) {
|
||||||
|
String errMsg = DeckFormat.getPlaneSectionConformanceProblem(planePool);
|
||||||
|
if (null != errMsg) {
|
||||||
|
SOptionPane.showErrorDialog(name + "'s deck " + errMsg, "Invalid Planar Deck");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
planes = planePool.toFlatList();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Vanguard
|
||||||
|
if (variantTypes.contains(GameType.Vanguard)) {
|
||||||
|
if (vanguardAvatar == null) { //ERROR! null if avatar deselected on list
|
||||||
|
SOptionPane.showMessageDialog("No Vanguard avatar selected for " + name
|
||||||
|
+ ". Please choose one or disable the Vanguard variant");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rp = RegisteredPlayer.forVariants(variantTypes, deck, schemes, isArchenemy, planes, vanguardAvatar);
|
||||||
|
rp.setTeamNumber(team);
|
||||||
|
players.add(rp.setPlayer(lobbyPlayer));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isAI) {
|
||||||
|
guis.put(rp, gui);
|
||||||
|
}
|
||||||
|
playerToSlot.put(rp, slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
hostedMatch = GuiBase.getInterface().hostMatch();
|
||||||
|
hostedMatch.startMatch(GameType.Constructed, variantTypes, players, guis);
|
||||||
|
|
||||||
|
for (final Player p : hostedMatch.getGame().getPlayers()) {
|
||||||
|
final LobbySlot slot = playerToSlot.get(p.getRegisteredPlayer());
|
||||||
|
if (p.getController() instanceof IGameController) {
|
||||||
|
gameControllers.put(slot, (IGameController) p.getController());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final static class GameLobbyData implements Serializable {
|
||||||
|
private static final long serialVersionUID = -9038854736144187540L;
|
||||||
|
|
||||||
|
private transient GameType currentGameMode = GameType.Constructed;
|
||||||
|
private final Set<GameType> appliedVariants = EnumSet.of(GameType.Constructed);
|
||||||
|
private final List<LobbySlot> slots = Lists.newArrayList();
|
||||||
|
|
||||||
|
public GameType getCurrentGameMode() {
|
||||||
|
return currentGameMode;
|
||||||
|
}
|
||||||
|
public void setCurrentGameMode(GameType currentGameMode) {
|
||||||
|
this.currentGameMode = currentGameMode;
|
||||||
|
}
|
||||||
|
public Set<GameType> getAppliedVariants() {
|
||||||
|
return Collections.unmodifiableSet(appliedVariants);
|
||||||
|
}
|
||||||
|
public List<LobbySlot> getSlots() {
|
||||||
|
return Collections.unmodifiableList(slots);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,8 +44,8 @@ import forge.properties.ForgePreferences.FPref;
|
|||||||
import forge.quest.QuestController;
|
import forge.quest.QuestController;
|
||||||
import forge.sound.MusicPlaylist;
|
import forge.sound.MusicPlaylist;
|
||||||
import forge.sound.SoundSystem;
|
import forge.sound.SoundSystem;
|
||||||
|
import forge.trackable.TrackableCollection;
|
||||||
import forge.util.CollectionSuppliers;
|
import forge.util.CollectionSuppliers;
|
||||||
import forge.util.FCollection;
|
|
||||||
import forge.util.GuiDisplayUtil;
|
import forge.util.GuiDisplayUtil;
|
||||||
import forge.util.NameGenerator;
|
import forge.util.NameGenerator;
|
||||||
import forge.util.maps.HashMapOfLists;
|
import forge.util.maps.HashMapOfLists;
|
||||||
@@ -137,8 +137,6 @@ public class HostedMatch {
|
|||||||
game.subscribeToEvents(SoundSystem.instance);
|
game.subscribeToEvents(SoundSystem.instance);
|
||||||
game.subscribeToEvents(visitor);
|
game.subscribeToEvents(visitor);
|
||||||
|
|
||||||
final String[] indices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");
|
|
||||||
|
|
||||||
// Instantiate all required field slots (user at 0)
|
// Instantiate all required field slots (user at 0)
|
||||||
final List<Player> sortedPlayers = Lists.newArrayList(game.getRegisteredPlayers());
|
final List<Player> sortedPlayers = Lists.newArrayList(game.getRegisteredPlayers());
|
||||||
Collections.sort(sortedPlayers, new Comparator<Player>() {
|
Collections.sort(sortedPlayers, new Comparator<Player>() {
|
||||||
@@ -150,18 +148,23 @@ public class HostedMatch {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
final String[] avatarIndices = FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",");
|
||||||
final GameView gameView = getGameView();
|
final GameView gameView = getGameView();
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
int avatarIndex = 0;
|
|
||||||
humanCount = 0;
|
humanCount = 0;
|
||||||
final MapOfLists<IGuiGame, PlayerView> playersPerGui = new HashMapOfLists<IGuiGame, PlayerView>(CollectionSuppliers.<PlayerView>arrayLists());
|
final MapOfLists<IGuiGame, PlayerView> playersPerGui = new HashMapOfLists<IGuiGame, PlayerView>(CollectionSuppliers.<PlayerView>arrayLists());
|
||||||
for (final Player p : sortedPlayers) {
|
for (int iPlayer = 0; iPlayer < sortedPlayers.size(); iPlayer++) {
|
||||||
if (i < indices.length) {
|
final RegisteredPlayer rp = match.getPlayers().get(iPlayer);
|
||||||
avatarIndex = Integer.parseInt(indices[i]);
|
final Player p = sortedPlayers.get(iPlayer);
|
||||||
i++;
|
|
||||||
|
p.getLobbyPlayer().setAvatarIndex(rp.getPlayer().getAvatarIndex());
|
||||||
|
if (p.getLobbyPlayer().getAvatarIndex() == -1) {
|
||||||
|
if (iPlayer < avatarIndices.length) {
|
||||||
|
p.getLobbyPlayer().setAvatarIndex(Integer.parseInt(avatarIndices[iPlayer]));
|
||||||
|
} else {
|
||||||
|
p.getLobbyPlayer().setAvatarIndex(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
p.getLobbyPlayer().setAvatarIndex(avatarIndex);
|
|
||||||
p.updateAvatar();
|
p.updateAvatar();
|
||||||
|
|
||||||
if (p.getController() instanceof PlayerControllerHuman) {
|
if (p.getController() instanceof PlayerControllerHuman) {
|
||||||
@@ -177,8 +180,9 @@ public class HostedMatch {
|
|||||||
humanCount++;
|
humanCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (final Entry<IGuiGame, Collection<PlayerView>> e : playersPerGui.entrySet()) {
|
for (final Entry<IGuiGame, Collection<PlayerView>> e : playersPerGui.entrySet()) {
|
||||||
e.getKey().openView(new FCollection<PlayerView>(e.getValue()));
|
e.getKey().openView(new TrackableCollection<PlayerView>(e.getValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (humanCount == 0) { //watch game but do not participate
|
if (humanCount == 0) { //watch game but do not participate
|
||||||
|
|||||||
109
forge-gui/src/main/java/forge/match/LobbySlot.java
Normal file
109
forge-gui/src/main/java/forge/match/LobbySlot.java
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package forge.match;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
|
import forge.AIOption;
|
||||||
|
import forge.deck.Deck;
|
||||||
|
import forge.net.game.LobbySlotType;
|
||||||
|
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||||
|
|
||||||
|
public final class LobbySlot implements Serializable {
|
||||||
|
private static final long serialVersionUID = 6918205436608794289L;
|
||||||
|
|
||||||
|
private LobbySlotType type;
|
||||||
|
private String name;
|
||||||
|
private int avatarIndex;
|
||||||
|
private int team;
|
||||||
|
private boolean isArchenemy;
|
||||||
|
private Deck deck;
|
||||||
|
private ImmutableSet<AIOption> aiOptions;
|
||||||
|
|
||||||
|
public LobbySlot(final LobbySlotType type, final String name, final int avatarIndex, final int team, final boolean isArchenemy, final Set<AIOption> aiOptions) {
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
this.avatarIndex = avatarIndex;
|
||||||
|
this.team = team;
|
||||||
|
this.isArchenemy = isArchenemy;
|
||||||
|
this.setAiOptions(aiOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
void apply(final UpdateLobbyPlayerEvent data) {
|
||||||
|
if (data.getType() != null) {
|
||||||
|
setType(data.getType());
|
||||||
|
}
|
||||||
|
if (data.getName() != null) {
|
||||||
|
setName(data.getName());
|
||||||
|
}
|
||||||
|
if (data.getAvatarIndex() != -1) {
|
||||||
|
setAvatarIndex(data.getAvatarIndex());
|
||||||
|
}
|
||||||
|
if (data.getTeam() != -1) {
|
||||||
|
setTeam(data.getTeam());
|
||||||
|
}
|
||||||
|
if (data.getArchenemy() != null) {
|
||||||
|
setIsArchenemy(data.getArchenemy().booleanValue());
|
||||||
|
}
|
||||||
|
if (data.getAiOptions() != null) {
|
||||||
|
setAiOptions(data.getAiOptions());
|
||||||
|
}
|
||||||
|
if (data.getDeck() != null) {
|
||||||
|
setDeck(data.getDeck());
|
||||||
|
} else if (getDeck() != null && data.getSection() != null && data.getCards() != null) {
|
||||||
|
getDeck().putSection(data.getSection(), data.getCards());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LobbySlotType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
public void setType(final LobbySlotType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAvatarIndex() {
|
||||||
|
return avatarIndex;
|
||||||
|
}
|
||||||
|
public void setAvatarIndex(final int avatarIndex) {
|
||||||
|
this.avatarIndex = avatarIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTeam() {
|
||||||
|
return team;
|
||||||
|
}
|
||||||
|
public void setTeam(final int team) {
|
||||||
|
this.team = team;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isArchenemy() {
|
||||||
|
return isArchenemy;
|
||||||
|
}
|
||||||
|
public void setIsArchenemy(final boolean isArchenemy) {
|
||||||
|
this.isArchenemy = isArchenemy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Deck getDeck() {
|
||||||
|
return deck;
|
||||||
|
}
|
||||||
|
public void setDeck(final Deck deck) {
|
||||||
|
this.deck = deck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImmutableSet<AIOption> getAiOptions() {
|
||||||
|
return aiOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAiOptions(final Set<AIOption> aiOptions) {
|
||||||
|
this.aiOptions = aiOptions == null ? ImmutableSet.<AIOption>of() : ImmutableSet.copyOf(aiOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
44
forge-gui/src/main/java/forge/match/LocalLobby.java
Normal file
44
forge-gui/src/main/java/forge/match/LocalLobby.java
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
package forge.match;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import forge.AIOption;
|
||||||
|
import forge.GuiBase;
|
||||||
|
import forge.interfaces.IGuiGame;
|
||||||
|
import forge.net.game.LobbySlotType;
|
||||||
|
|
||||||
|
public final class LocalLobby extends GameLobby {
|
||||||
|
|
||||||
|
public LocalLobby() {
|
||||||
|
super(false);
|
||||||
|
|
||||||
|
final String humanName = localName();
|
||||||
|
final int[] avatarIndices = localAvatarIndices();
|
||||||
|
|
||||||
|
final LobbySlot slot0 = new LobbySlot(LobbySlotType.LOCAL, humanName, avatarIndices[0], 0, true, Collections.<AIOption>emptySet());
|
||||||
|
addSlot(slot0);
|
||||||
|
|
||||||
|
final LobbySlot slot1 = new LobbySlot(LobbySlotType.AI, null, avatarIndices[1], 1, false, Collections.<AIOption>emptySet());
|
||||||
|
addSlot(slot1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean hasControl() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mayEdit(final int index) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mayControl(final int index) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mayRemove(final int index) {
|
||||||
|
return index >= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public IGuiGame getGui(final int index) {
|
||||||
|
return GuiBase.getInterface().getNewGuiGame();
|
||||||
|
}
|
||||||
|
}
|
||||||
6
forge-gui/src/main/java/forge/match/MatchButtonType.java
Normal file
6
forge-gui/src/main/java/forge/match/MatchButtonType.java
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package forge.match;
|
||||||
|
|
||||||
|
public enum MatchButtonType {
|
||||||
|
OK,
|
||||||
|
CANCEL;
|
||||||
|
}
|
||||||
@@ -1,415 +0,0 @@
|
|||||||
package forge.match;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
|
|
||||||
import forge.LobbyPlayer;
|
|
||||||
import forge.UiCommand;
|
|
||||||
import forge.assets.FSkinProp;
|
|
||||||
import forge.deck.CardPool;
|
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GameEntityView;
|
|
||||||
import forge.game.GameView;
|
|
||||||
import forge.game.card.CardView;
|
|
||||||
import forge.game.phase.PhaseType;
|
|
||||||
import forge.game.player.DelayedReveal;
|
|
||||||
import forge.game.player.IHasIcon;
|
|
||||||
import forge.game.player.PlayerView;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.game.zone.ZoneType;
|
|
||||||
import forge.interfaces.IButton;
|
|
||||||
import forge.item.PaperCard;
|
|
||||||
import forge.net.game.GuiGameEvent;
|
|
||||||
import forge.net.game.server.IToClient;
|
|
||||||
import forge.player.PlayerControllerHuman;
|
|
||||||
import forge.trackable.TrackableObject;
|
|
||||||
import forge.util.FCollectionView;
|
|
||||||
import forge.util.ITriggerEvent;
|
|
||||||
|
|
||||||
public class NetGuiGame extends AbstractGuiGame {
|
|
||||||
|
|
||||||
private final IToClient client;
|
|
||||||
public NetGuiGame(final IToClient client) {
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void send(final String method) {
|
|
||||||
send(method, Collections.<TrackableObject>emptySet());
|
|
||||||
}
|
|
||||||
private void send(final String method, final TrackableObject object) {
|
|
||||||
send(method, Collections.singleton(object));
|
|
||||||
}
|
|
||||||
private void send(final String method, final Iterable<? extends TrackableObject> objects) {
|
|
||||||
client.send(new GuiGameEvent(method, objects));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setGameView(final GameView gameView) {
|
|
||||||
super.setGameView(gameView);
|
|
||||||
send("setGameView", gameView);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean resetForNewGame() {
|
|
||||||
send("resetForNewGame");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void openView(final Iterable<PlayerView> myPlayers) {
|
|
||||||
send("openView", myPlayers);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterGameEnd() {
|
|
||||||
send("afterGameEnd");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showCombat() {
|
|
||||||
send("showCombat");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showPromptMessage(PlayerView playerView, String message) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean stopAtPhase(PlayerView playerTurn, PhaseType phase) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IButton getBtnOK(final PlayerView playerView) {
|
|
||||||
return new NetButton(playerView, "OK");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IButton getBtnCancel(final PlayerView playerView) {
|
|
||||||
return new NetButton(playerView, "Cancel");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void focusButton(IButton button) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flashIncorrectAction() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updatePhase() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateTurn(PlayerView player) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updatePlayerControl() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void enableOverlay() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disableOverlay() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void finishGame() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object showManaPool(PlayerView player) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void hideManaPool(PlayerView player, Object zoneToRestore) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateStack() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateZones(List<Pair<PlayerView, ZoneType>> zonesToUpdate) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateSingleCard(CardView card) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateManaPool(Iterable<PlayerView> manaPoolUpdate) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateLives(Iterable<PlayerView> livesUpdate) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPanelSelection(CardView hostCard) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void hear(LobbyPlayer player, String message) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SpellAbility getAbilityToPlay(List<SpellAbility> abilities,
|
|
||||||
ITriggerEvent triggerEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<CardView, Integer> assignDamage(CardView attacker,
|
|
||||||
List<CardView> blockers, int damage, GameEntityView defender,
|
|
||||||
boolean overrideOrder) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void message(String message, String title) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showErrorDialog(String message, String title) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean showConfirmDialog(String message, String title,
|
|
||||||
String yesButtonText, String noButtonText, boolean defaultYes) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int showOptionDialog(String message, String title, FSkinProp icon,
|
|
||||||
String[] options, int defaultOption) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int showCardOptionDialog(CardView card, String message,
|
|
||||||
String title, FSkinProp icon, String[] options, int defaultOption) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String showInputDialog(String message, String title, FSkinProp icon,
|
|
||||||
String initialInput, String[] inputOptions) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean confirm(CardView c, String question, boolean defaultIsYes,
|
|
||||||
String[] options) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> List<T> getChoices(String message, int min, int max,
|
|
||||||
Collection<T> choices, T selected, Function<T, String> display) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> List<T> order(String title, String top, int remainingObjectsMin,
|
|
||||||
int remainingObjectsMax, List<T> sourceChoices,
|
|
||||||
List<T> destChoices, CardView referenceCard,
|
|
||||||
boolean sideboardingMode) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<PaperCard> sideboard(CardPool sideboard, CardPool main) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public GameEntityView chooseSingleEntityForEffect(String title,
|
|
||||||
FCollectionView<? extends GameEntity> optionList,
|
|
||||||
DelayedReveal delayedReveal, boolean isOptional,
|
|
||||||
PlayerControllerHuman controller) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCard(CardView card) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean openZones(Collection<ZoneType> zones,
|
|
||||||
Map<PlayerView, Object> players) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void restoreOldZones(Map<PlayerView, Object> playersToRestoreZonesFor) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isUiSetToSkipPhase(PlayerView playerTurn, PhaseType phase) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void updateCurrentPlayer(PlayerView player) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private final static class NetButton implements IButton {
|
|
||||||
|
|
||||||
private final PlayerView playerView;
|
|
||||||
private final String button;
|
|
||||||
private NetButton(final PlayerView playerView, final String button) {
|
|
||||||
this.playerView = playerView;
|
|
||||||
this.button = button;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEnabled() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setEnabled(boolean b0) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isVisible() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setVisible(boolean b0) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getText() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setText(String text0) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isSelected() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSelected(boolean b0) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean requestFocusInWindow() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setCommand(UiCommand command0) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setTextColor(FSkinProp color) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setTextColor(int r, int g, int b) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -83,6 +83,11 @@ public class InputConfirmMulligan extends InputSyncronizedBase {
|
|||||||
showMessage(sb.toString());
|
showMessage(sb.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final boolean allowAwaitNextInput() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
protected final void onOk() {
|
protected final void onOk() {
|
||||||
|
|||||||
36
forge-gui/src/main/java/forge/net/ClientGameLobby.java
Normal file
36
forge-gui/src/main/java/forge/net/ClientGameLobby.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package forge.net;
|
||||||
|
|
||||||
|
import forge.interfaces.IGuiGame;
|
||||||
|
import forge.match.GameLobby;
|
||||||
|
|
||||||
|
public final class ClientGameLobby extends GameLobby {
|
||||||
|
private int localPlayer = -1;
|
||||||
|
|
||||||
|
public ClientGameLobby() {
|
||||||
|
super(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocalPlayer(final int index) {
|
||||||
|
this.localPlayer = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean hasControl() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mayEdit(final int index) {
|
||||||
|
return index == localPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mayControl(final int index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mayRemove(final int index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public IGuiGame getGui(final int index) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,22 +15,44 @@ import io.netty.handler.codec.serialization.ClassResolvers;
|
|||||||
import io.netty.handler.codec.serialization.ObjectDecoder;
|
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||||
import io.netty.handler.codec.serialization.ObjectEncoder;
|
import io.netty.handler.codec.serialization.ObjectEncoder;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import forge.FThreads;
|
||||||
|
import forge.UiCommand;
|
||||||
|
import forge.assets.FSkinProp;
|
||||||
|
import forge.deck.CardPool;
|
||||||
|
import forge.game.GameEntityView;
|
||||||
import forge.game.GameView;
|
import forge.game.GameView;
|
||||||
|
import forge.game.card.CardView;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.DelayedReveal;
|
||||||
import forge.game.player.PlayerView;
|
import forge.game.player.PlayerView;
|
||||||
|
import forge.game.spellability.SpellAbilityView;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.interfaces.IButton;
|
||||||
import forge.interfaces.IGuiGame;
|
import forge.interfaces.IGuiGame;
|
||||||
|
import forge.interfaces.ILobbyListener;
|
||||||
|
import forge.match.MatchButtonType;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.net.game.GuiGameEvent;
|
import forge.net.game.GuiGameEvent;
|
||||||
import forge.net.game.LobbyUpdateEvent;
|
import forge.net.game.IdentifiableNetEvent;
|
||||||
import forge.net.game.LoginEvent;
|
import forge.net.game.LoginEvent;
|
||||||
import forge.net.game.MessageEvent;
|
import forge.net.game.MessageEvent;
|
||||||
import forge.net.game.NetEvent;
|
import forge.net.game.NetEvent;
|
||||||
import forge.net.game.client.ILobbyListener;
|
import forge.net.game.ReplyEvent;
|
||||||
import forge.net.game.client.IToServer;
|
import forge.net.game.client.IToServer;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
|
import forge.trackable.TrackableCollection;
|
||||||
|
import forge.util.ITriggerEvent;
|
||||||
|
|
||||||
public class FGameClient implements IToServer {
|
public class FGameClient implements IToServer {
|
||||||
private final IGuiGame clientGui;
|
private final IGuiGame clientGui;
|
||||||
@@ -39,6 +61,7 @@ public class FGameClient implements IToServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private final List<ILobbyListener> lobbyListeners = Lists.newArrayList();
|
private final List<ILobbyListener> lobbyListeners = Lists.newArrayList();
|
||||||
|
private final ReplyPool replies = new ReplyPool();
|
||||||
|
|
||||||
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
|
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
|
||||||
|
|
||||||
@@ -81,14 +104,32 @@ public class FGameClient implements IToServer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void send(final NetEvent event) {
|
public void send(final NetEvent event) {
|
||||||
|
System.out.println("Client sent " + event);
|
||||||
channel.writeAndFlush(event);
|
channel.writeAndFlush(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object sendAndWait(final IdentifiableNetEvent event) throws TimeoutException {
|
||||||
|
replies.initialize(event.getId());
|
||||||
|
|
||||||
|
send(event);
|
||||||
|
|
||||||
|
// Wait for reply
|
||||||
|
return replies.get(event.getId());
|
||||||
|
}
|
||||||
|
|
||||||
public void addLobbyListener(final ILobbyListener listener) {
|
public void addLobbyListener(final ILobbyListener listener) {
|
||||||
lobbyListeners.add(listener);
|
lobbyListeners.add(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setGameControllers(final Iterable<PlayerView> myPlayers) {
|
||||||
|
for (final PlayerView p : myPlayers) {
|
||||||
|
clientGui.setGameController(p, new NetGameController(this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class GameClientHandler extends ChannelInboundHandlerAdapter {
|
private class GameClientHandler extends ChannelInboundHandlerAdapter {
|
||||||
/**
|
/**
|
||||||
* Creates a client-side handler.
|
* Creates a client-side handler.
|
||||||
@@ -98,24 +139,214 @@ public class FGameClient implements IToServer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelActive(final ChannelHandlerContext ctx) {
|
public void channelActive(final ChannelHandlerContext ctx) {
|
||||||
// Don't use send here, as this.channel is not yet set!
|
// Don't use send() here, as this.channel is not yet set!
|
||||||
ctx.channel().writeAndFlush(new LoginEvent(FModel.getPreferences().getPref(FPref.PLAYER_NAME)));
|
ctx.channel().writeAndFlush(new LoginEvent(FModel.getPreferences().getPref(FPref.PLAYER_NAME), Integer.parseInt(FModel.getPreferences().getPref(FPref.UI_AVATARS).split(",")[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
|
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
|
||||||
System.out.println("Client received: " + msg);
|
System.out.println("Client received: " + msg);
|
||||||
if (msg instanceof GuiGameEvent) {
|
if (msg instanceof ReplyEvent) {
|
||||||
|
final ReplyEvent event = (ReplyEvent) msg;
|
||||||
|
replies.complete(event.getIndex(), event.getReply());
|
||||||
|
} else if (msg instanceof GuiGameEvent) {
|
||||||
final GuiGameEvent event = (GuiGameEvent) msg;
|
final GuiGameEvent event = (GuiGameEvent) msg;
|
||||||
|
final Object[] args = event.getObjects();
|
||||||
|
Serializable reply = null;
|
||||||
|
boolean doReply = false;
|
||||||
|
|
||||||
|
final IButton btn;
|
||||||
|
if (args.length >= 2 && args[0] instanceof PlayerView && args[1] instanceof MatchButtonType) {
|
||||||
|
btn = args[1] == MatchButtonType.OK ? clientGui.getBtnOK((PlayerView) args[0]) : clientGui.getBtnCancel((PlayerView) args[0]);
|
||||||
|
} else {
|
||||||
|
btn = null;
|
||||||
|
}
|
||||||
|
|
||||||
switch (event.getMethod()) {
|
switch (event.getMethod()) {
|
||||||
case "setGameView":
|
case "setGameView":
|
||||||
clientGui.setGameView((GameView) event.getObject());
|
clientGui.setGameView((GameView) args[0]);
|
||||||
break;
|
break;
|
||||||
case "openView":
|
case "openView":
|
||||||
clientGui.openView((Iterable<PlayerView>) event.getObjects());
|
final TrackableCollection<PlayerView> myPlayers = (TrackableCollection<PlayerView>) args[0];
|
||||||
default:
|
setGameControllers(myPlayers);
|
||||||
|
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||||
|
@Override public final void run() {
|
||||||
|
//clientGui.setGameView(new NetGameView(FGameClient.this));
|
||||||
|
clientGui.openView(myPlayers);
|
||||||
|
}
|
||||||
|
});
|
||||||
break;
|
break;
|
||||||
|
case "afterGameEnd":
|
||||||
|
clientGui.afterGameEnd();
|
||||||
|
break;
|
||||||
|
case "showCombat":
|
||||||
|
clientGui.showCombat();
|
||||||
|
break;
|
||||||
|
case "showPromptMessage":
|
||||||
|
clientGui.showPromptMessage((PlayerView) args[0], (String) args[1]);
|
||||||
|
break;
|
||||||
|
case "stopAtPhase":
|
||||||
|
reply = clientGui.stopAtPhase((PlayerView) args[0], (PhaseType) args[1]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "focusButton":
|
||||||
|
clientGui.focusButton((MatchButtonType) args[0]);
|
||||||
|
break;
|
||||||
|
case "flashIncorrectAction":
|
||||||
|
clientGui.flashIncorrectAction();
|
||||||
|
break;
|
||||||
|
case "updatePhase":
|
||||||
|
clientGui.updatePhase();
|
||||||
|
break;
|
||||||
|
case "updateTurn":
|
||||||
|
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||||
|
@Override public final void run() {
|
||||||
|
clientGui.updateTurn((PlayerView) args[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "udpdatePlayerControl":
|
||||||
|
clientGui.updatePlayerControl();
|
||||||
|
break;
|
||||||
|
case "enableOverlay":
|
||||||
|
clientGui.enableOverlay();
|
||||||
|
break;
|
||||||
|
case "disbleOverlay":
|
||||||
|
clientGui.disableOverlay();
|
||||||
|
break;
|
||||||
|
case "finishGame":
|
||||||
|
clientGui.finishGame();
|
||||||
|
break;
|
||||||
|
case "showManaPool":
|
||||||
|
clientGui.showManaPool((PlayerView) args[0]);
|
||||||
|
break;
|
||||||
|
case "hideManaPool":
|
||||||
|
clientGui.hideManaPool((PlayerView) args[0], args[1]);
|
||||||
|
break;
|
||||||
|
case "updateStack":
|
||||||
|
clientGui.updateStack();
|
||||||
|
break;
|
||||||
|
case "updateZones":
|
||||||
|
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||||
|
@Override public final void run() {
|
||||||
|
clientGui.updateZones((List<Pair<PlayerView, ZoneType>>) args[0]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case "updateSingleCard":
|
||||||
|
clientGui.updateSingleCard((CardView) args[0]);
|
||||||
|
break;
|
||||||
|
case "updateManaPool":
|
||||||
|
clientGui.updateManaPool((Iterable<PlayerView>) args[0]);
|
||||||
|
break;
|
||||||
|
case "updateLives":
|
||||||
|
clientGui.updateLives((Iterable<PlayerView>) args[0]);
|
||||||
|
break;
|
||||||
|
case "setPanelSelection":
|
||||||
|
clientGui.setPanelSelection((CardView) args[0]);
|
||||||
|
break;
|
||||||
|
case "getAbilityToPlay":
|
||||||
|
reply = clientGui.getAbilityToPlay((List<SpellAbilityView>) args[0], (ITriggerEvent) args[1]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "assignDamage":
|
||||||
|
reply = (Serializable) clientGui.assignDamage((CardView) args[0], (List<CardView>) args[1], (int) args[2], (GameEntityView) args[3], (boolean) args[4]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "message":
|
||||||
|
clientGui.message((String) args[0], (String) args[1]);
|
||||||
|
break;
|
||||||
|
case "showErrorDialog":
|
||||||
|
clientGui.showErrorDialog((String) args[0], (String) args[1]);
|
||||||
|
break;
|
||||||
|
case "showConfirmDialog":
|
||||||
|
reply = clientGui.showConfirmDialog((String) args[0], (String) args[1], (String) args[2], (String) args[3], (boolean) args[4]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "showOptionDialog":
|
||||||
|
reply = clientGui.showOptionDialog((String) args[0], (String) args[1], (FSkinProp) args[2], (String[]) args[3], (int) args[4]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "showCardOptionDialog":
|
||||||
|
reply = clientGui.showCardOptionDialog((CardView) args[0], (String) args[1], (String) args[2], (FSkinProp) args[3], (String[]) args[4], (int) args[5]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "showInputDialog":
|
||||||
|
reply = clientGui.showInputDialog((String) args[0], (String) args[1], (FSkinProp) args[2], (String) args[3], (String[]) args[4]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "confirm":
|
||||||
|
reply = clientGui.confirm((CardView) args[0], (String) args[1], (boolean) args[2], (String[]) args[3]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getChoices":
|
||||||
|
reply = (Serializable) clientGui.getChoices((String) args[0], (int) args[1], (int) args[2], (Collection<Object>) args[3], args[4], (Function<Object, String>) args[5]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "order":
|
||||||
|
reply = (Serializable) clientGui.order((String) args[0], (String) args[1], (int) args[2], (int) args[3], (List<Object>) args[4], (List<Object>) args[5], (CardView) args[6], (boolean) args[7]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "sideboard":
|
||||||
|
reply = (Serializable) clientGui.sideboard((CardPool) args[0], (CardPool) args[1]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "chooseSingleEntityForEffect":
|
||||||
|
reply = clientGui.chooseSingleEntityForEffect((String) args[0], (TrackableCollection<GameEntityView>) args[1], (DelayedReveal) args[2], (boolean) args[3]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "setCard":
|
||||||
|
clientGui.setCard((CardView) args[0]);
|
||||||
|
break;
|
||||||
|
// TODO case "setPlayerAvatar":
|
||||||
|
case "openZones":
|
||||||
|
reply = clientGui.openZones((Collection<ZoneType>) args[0], (Map<PlayerView, Object>) args[1]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "restoreOldZones":
|
||||||
|
clientGui.restoreOldZones((Map<PlayerView, Object>) args[0]);
|
||||||
|
break;
|
||||||
|
case "isUiSetToSkipPhase":
|
||||||
|
reply = clientGui.isUiSetToSkipPhase((PlayerView) args[0], (PhaseType) args[1]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
// BUTTONS
|
||||||
|
case "btn_setEnabled":
|
||||||
|
btn.setEnabled((boolean) args[2]);
|
||||||
|
break;
|
||||||
|
case "btn_setVisible":
|
||||||
|
btn.setVisible((boolean) args[2]);
|
||||||
|
break;
|
||||||
|
case "btn_setText":
|
||||||
|
btn.setText((String) args[2]);
|
||||||
|
break;
|
||||||
|
case "btn_isSelected":
|
||||||
|
reply = btn.isSelected();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "btn_setSelected":
|
||||||
|
btn.setSelected((boolean) args[2]);
|
||||||
|
break;
|
||||||
|
case "btn_requestFocusInWindows":
|
||||||
|
reply = btn.requestFocusInWindow();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "btn_setCommand":
|
||||||
|
btn.setCommand((UiCommand) args[2]);
|
||||||
|
break;
|
||||||
|
case "btn_setTextColor":
|
||||||
|
if (args.length == 3) {
|
||||||
|
btn.setTextColor((FSkinProp) args[2]);
|
||||||
|
} else {
|
||||||
|
btn.setTextColor((int) args[2], (int) args[3], (int) args[4]);
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
System.err.println("Unsupported game event " + event.getMethod());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (doReply) {
|
||||||
|
send(new ReplyEvent(event.getId(), reply));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,7 +376,8 @@ public class FGameClient implements IToServer {
|
|||||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||||
if (msg instanceof LobbyUpdateEvent) {
|
if (msg instanceof LobbyUpdateEvent) {
|
||||||
for (final ILobbyListener listener : lobbyListeners) {
|
for (final ILobbyListener listener : lobbyListeners) {
|
||||||
listener.update(((LobbyUpdateEvent) msg).getState());
|
final LobbyUpdateEvent event = (LobbyUpdateEvent) msg;
|
||||||
|
listener.update(event.getState(), event.getSlot());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.channelRead(ctx, msg);
|
super.channelRead(ctx, msg);
|
||||||
|
|||||||
@@ -1,15 +1,27 @@
|
|||||||
package forge.net;
|
package forge.net;
|
||||||
|
|
||||||
import forge.game.GameRules;
|
import forge.FThreads;
|
||||||
import forge.interfaces.ILobby;
|
import forge.GuiBase;
|
||||||
import forge.net.game.LobbyState;
|
import forge.LobbyPlayer;
|
||||||
import forge.net.game.LobbyUpdateEvent;
|
import forge.game.GameView;
|
||||||
|
import forge.game.card.CardView;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
|
import forge.game.spellability.SpellAbilityView;
|
||||||
|
import forge.interfaces.IGameController;
|
||||||
|
import forge.interfaces.IGuiGame;
|
||||||
|
import forge.interfaces.ILobbyListener;
|
||||||
|
import forge.match.LobbySlot;
|
||||||
|
import forge.match.NextGameDecision;
|
||||||
|
import forge.net.game.GuiGameEvent;
|
||||||
|
import forge.net.game.LobbySlotType;
|
||||||
import forge.net.game.LoginEvent;
|
import forge.net.game.LoginEvent;
|
||||||
import forge.net.game.LogoutEvent;
|
import forge.net.game.LogoutEvent;
|
||||||
import forge.net.game.MessageEvent;
|
import forge.net.game.MessageEvent;
|
||||||
import forge.net.game.NetEvent;
|
import forge.net.game.NetEvent;
|
||||||
import forge.net.game.RegisterDeckEvent;
|
import forge.net.game.ReplyEvent;
|
||||||
|
import forge.net.game.UpdateLobbyPlayerEvent;
|
||||||
import forge.net.game.server.RemoteClient;
|
import forge.net.game.server.RemoteClient;
|
||||||
|
import forge.util.ITriggerEvent;
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
@@ -27,8 +39,14 @@ import io.netty.handler.codec.serialization.ObjectEncoder;
|
|||||||
import io.netty.handler.logging.LogLevel;
|
import io.netty.handler.logging.LogLevel;
|
||||||
import io.netty.handler.logging.LoggingHandler;
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
public final class FServerManager {
|
public final class FServerManager {
|
||||||
@@ -36,18 +54,13 @@ public final class FServerManager {
|
|||||||
|
|
||||||
private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
private final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
|
||||||
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
|
private final EventLoopGroup workerGroup = new NioEventLoopGroup();
|
||||||
private final Map<Integer, NetGame> games = Maps.newTreeMap();
|
|
||||||
private int id = 0;
|
|
||||||
private final Map<Channel, RemoteClient> clients = Maps.newTreeMap();
|
private final Map<Channel, RemoteClient> clients = Maps.newTreeMap();
|
||||||
private ILobby localLobby;
|
private ServerGameLobby localLobby;
|
||||||
|
private ILobbyListener lobbyListener;
|
||||||
|
|
||||||
private FServerManager() {
|
private FServerManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int nextId() {
|
|
||||||
return id++;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static FServerManager getInstance() {
|
public static FServerManager getInstance() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = new FServerManager();
|
instance = new FServerManager();
|
||||||
@@ -62,15 +75,14 @@ public final class FServerManager {
|
|||||||
.channel(NioServerSocketChannel.class)
|
.channel(NioServerSocketChannel.class)
|
||||||
.handler(new LoggingHandler(LogLevel.INFO))
|
.handler(new LoggingHandler(LogLevel.INFO))
|
||||||
.childHandler(new ChannelInitializer<SocketChannel>() {
|
.childHandler(new ChannelInitializer<SocketChannel>() {
|
||||||
@Override
|
@Override public final void initChannel(final SocketChannel ch) {
|
||||||
public void initChannel(SocketChannel ch) throws Exception {
|
final ChannelPipeline p = ch.pipeline();
|
||||||
ChannelPipeline p = ch.pipeline();
|
|
||||||
p.addLast(
|
p.addLast(
|
||||||
new ObjectEncoder(),
|
new ObjectEncoder(),
|
||||||
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
|
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
|
||||||
new MessageHandler(),
|
new MessageHandler(),
|
||||||
new RegisterClientHandler(),
|
new RegisterClientHandler(),
|
||||||
new ToLobbyListenersHandler(),
|
new LobbyInputHandler(),
|
||||||
new DeregisterClientHandler(),
|
new DeregisterClientHandler(),
|
||||||
new GameServerHandler());
|
new GameServerHandler());
|
||||||
}
|
}
|
||||||
@@ -101,29 +113,53 @@ public final class FServerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(final NetEvent event) {
|
public void broadcast(final NetEvent event) {
|
||||||
for (final RemoteClient client : clients.values()) {
|
broadcastTo(event, clients.values());
|
||||||
|
}
|
||||||
|
public void broadcastExcept(final NetEvent event, final RemoteClient notTo) {
|
||||||
|
broadcastExcept(event, Collections.singleton(notTo));
|
||||||
|
}
|
||||||
|
public void broadcastExcept(final NetEvent event, final Collection<RemoteClient> notTo) {
|
||||||
|
broadcastTo(event, Iterables.filter(clients.values(), Predicates.not(Predicates.in(notTo))));
|
||||||
|
}
|
||||||
|
private void broadcastTo(final NetEvent event, final Iterable<RemoteClient> to) {
|
||||||
|
for (final RemoteClient client : to) {
|
||||||
event.updateForClient(client);
|
event.updateForClient(client);
|
||||||
client.send(event);
|
client.send(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLobby(final ILobby lobby) {
|
public void setLobby(final ServerGameLobby lobby) {
|
||||||
this.localLobby = lobby;
|
this.localLobby = lobby;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NetGame hostGame(final GameRules rules) {
|
public void setLobbyListener(final ILobbyListener listener) {
|
||||||
final int id = nextId();
|
this.lobbyListener = listener;
|
||||||
final NetGame game = new NetGame(rules);
|
|
||||||
games.put(id, game);
|
|
||||||
return game;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateLobbyState() {
|
public void updateLobbyState() {
|
||||||
final LobbyState state = localLobby.getState();
|
final LobbyUpdateEvent event = new LobbyUpdateEvent(localLobby.getData());
|
||||||
final LobbyUpdateEvent event = new LobbyUpdateEvent(state);
|
|
||||||
broadcast(event);
|
broadcast(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateSlot(final int index, final UpdateLobbyPlayerEvent event) {
|
||||||
|
localLobby.applyToSlot(index, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IGuiGame getGui(final int index) {
|
||||||
|
final LobbySlot slot = localLobby.getSlot(index);
|
||||||
|
final LobbySlotType type = slot.getType();
|
||||||
|
if (type == LobbySlotType.LOCAL) {
|
||||||
|
return GuiBase.getInterface().getNewGuiGame();
|
||||||
|
} else if (type == LobbySlotType.REMOTE) {
|
||||||
|
for (final RemoteClient client : clients.values()) {
|
||||||
|
if (client.getIndex() == index) {
|
||||||
|
return new NetGuiGame(client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void finalize() throws Throwable {
|
protected void finalize() throws Throwable {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
@@ -141,9 +177,187 @@ public final class FServerManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class GameServerHandler extends ChannelInboundHandlerAdapter {
|
private class GameServerHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
|
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
|
||||||
System.out.println("Server received: " + msg);
|
System.out.println("Server received: " + msg);
|
||||||
|
final RemoteClient client = clients.get(ctx.channel());
|
||||||
|
if (msg instanceof ReplyEvent) {
|
||||||
|
client.setReply(((ReplyEvent) msg).getIndex(), ((ReplyEvent) msg).getReply());
|
||||||
|
} else if (msg instanceof GuiGameEvent) {
|
||||||
|
final GuiGameEvent event = (GuiGameEvent) msg;
|
||||||
|
final GameView gameView = localLobby.getGameView();
|
||||||
|
final IGameController controller = localLobby.getController(client.getIndex());
|
||||||
|
final Object[] args = event.getObjects();
|
||||||
|
|
||||||
|
FThreads.invokeInBackgroundThread(new Runnable() {
|
||||||
|
@Override public final void run() {
|
||||||
|
Serializable reply = null;
|
||||||
|
boolean doReply = false;
|
||||||
|
|
||||||
|
switch (event.getMethod()) {
|
||||||
|
// From GameController
|
||||||
|
case "useMana":
|
||||||
|
controller.useMana((byte) args[0]);
|
||||||
|
break;
|
||||||
|
case "tryUndoLastAction":
|
||||||
|
reply = controller.tryUndoLastAction();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "selectPlayer":
|
||||||
|
controller.selectPlayer((PlayerView) args[0], (ITriggerEvent) args[1]);
|
||||||
|
break;
|
||||||
|
case "selectCard":
|
||||||
|
reply = controller.selectCard((CardView) args[0], (List<CardView>) args[1], (ITriggerEvent) args[2]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "selectButtonOk":
|
||||||
|
controller.selectButtonOk();
|
||||||
|
break;
|
||||||
|
case "selectButtonCancel":
|
||||||
|
controller.selectButtonCancel();
|
||||||
|
break;
|
||||||
|
case "selectAbility":
|
||||||
|
controller.selectAbility((SpellAbilityView) args[0]);
|
||||||
|
break;
|
||||||
|
case "passPriorityUntilEndOfTurn":
|
||||||
|
reply = controller.passPriorityUntilEndOfTurn();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "passPriority":
|
||||||
|
reply = controller.passPriority();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "nextGameDecision":
|
||||||
|
controller.nextGameDecision((NextGameDecision) args[0]);
|
||||||
|
break;
|
||||||
|
case "mayLookAtAllCards":
|
||||||
|
reply = controller.mayLookAtAllCards();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getActivateDescription":
|
||||||
|
reply = controller.getActivateDescription((CardView) args[0]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "concede":
|
||||||
|
controller.concede();
|
||||||
|
break;
|
||||||
|
case "alphaStrike":
|
||||||
|
controller.alphaStrike();
|
||||||
|
break;
|
||||||
|
// From GameView
|
||||||
|
case "getPlayers":
|
||||||
|
reply = (Serializable) gameView.getPlayers();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getTitle":
|
||||||
|
reply = gameView.getTitle();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "isCommander":
|
||||||
|
reply = gameView.isCommander();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getGameType":
|
||||||
|
reply = gameView.getGameType();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getPoisonCountersToLose":
|
||||||
|
reply = gameView.getPoisonCountersToLose();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getNumGamesInMatch":
|
||||||
|
reply = gameView.getNumGamesInMatch();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getTurn":
|
||||||
|
reply = gameView.getTurn();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getPhase":
|
||||||
|
reply = gameView.getPhase();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getPlayerTurn":
|
||||||
|
reply = gameView.getPlayerTurn();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getStack":
|
||||||
|
reply = (Serializable) gameView.getStack();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "peekStack":
|
||||||
|
reply = gameView.peekStack();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getStormCount":
|
||||||
|
reply = gameView.getStormCount();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "isFirstGameInMatch":
|
||||||
|
reply = gameView.isFirstGameInMatch();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getNumPlayedGamesInMatch":
|
||||||
|
reply = gameView.getNumPlayedGamesInMatch();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "isGameOver":
|
||||||
|
reply = gameView.isGameOver();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "isMatchOver":
|
||||||
|
reply = gameView.isMatchOver();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getWinningTeam":
|
||||||
|
reply = gameView.getWinningTeam();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getGameLog":
|
||||||
|
reply = gameView.getGameLog();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getCombat":
|
||||||
|
reply = gameView.getCombat();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "isMatchWonBy":
|
||||||
|
reply = gameView.isMatchWonBy((LobbyPlayer) args[0]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getOutcomesOfMatch":
|
||||||
|
reply = (Serializable) gameView.getOutcomesOfMatch();
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
// TODO case "getWinningPlayer":
|
||||||
|
case "isWinner":
|
||||||
|
reply = gameView.isWinner((LobbyPlayer) args[0]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getGamesWonBy":
|
||||||
|
reply = gameView.getGamesWonBy((LobbyPlayer) args[0]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getDeck":
|
||||||
|
reply = gameView.getDeck((String) args[0]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
case "getAnteResult":
|
||||||
|
reply = gameView.getAnteResult((PlayerView) args[0]);
|
||||||
|
doReply = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
System.err.println(String.format("Unknown incoming client command %s", event.getMethod()));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doReply) {
|
||||||
|
client.send(new ReplyEvent(event.getId(), reply));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -158,8 +372,7 @@ public final class FServerManager {
|
|||||||
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
|
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
|
||||||
final RemoteClient client = new RemoteClient(ctx.channel());
|
final RemoteClient client = new RemoteClient(ctx.channel());
|
||||||
clients.put(ctx.channel(), client);
|
clients.put(ctx.channel(), client);
|
||||||
games.get(0).addClient(client);
|
System.out.println("Client connected to server at " + ctx.channel().remoteAddress());
|
||||||
System.out.println("User connected to server at " + ctx.channel().remoteAddress());
|
|
||||||
updateLobbyState();
|
updateLobbyState();
|
||||||
super.channelActive(ctx);
|
super.channelActive(ctx);
|
||||||
}
|
}
|
||||||
@@ -168,47 +381,45 @@ public final class FServerManager {
|
|||||||
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||||
final RemoteClient client = clients.get(ctx.channel());
|
final RemoteClient client = clients.get(ctx.channel());
|
||||||
if (msg instanceof LoginEvent) {
|
if (msg instanceof LoginEvent) {
|
||||||
client.setUsername(((LoginEvent) msg).getUsername());
|
final String username = ((LoginEvent) msg).getUsername();
|
||||||
|
client.setUsername(username);
|
||||||
|
broadcast(new MessageEvent(null, String.format("%s joined the room", username)));
|
||||||
updateLobbyState();
|
updateLobbyState();
|
||||||
} else if (msg instanceof RegisterDeckEvent) {
|
} else if (msg instanceof UpdateLobbyPlayerEvent) {
|
||||||
games.get(0).registerDeck(client, ((RegisterDeckEvent) msg).getDeck());
|
localLobby.applyToSlot(client.getIndex(), (UpdateLobbyPlayerEvent) msg);
|
||||||
}
|
}
|
||||||
super.channelRead(ctx, msg);
|
super.channelRead(ctx, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ToLobbyListenersHandler extends ChannelInboundHandlerAdapter {
|
private class LobbyInputHandler extends ChannelInboundHandlerAdapter {
|
||||||
@Override public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
@Override public void channelRead(final ChannelHandlerContext ctx, final Object msg) throws Exception {
|
||||||
final RemoteClient client = clients.get(ctx.channel());
|
final RemoteClient client = clients.get(ctx.channel());
|
||||||
if (msg instanceof LoginEvent) {
|
if (msg instanceof LoginEvent) {
|
||||||
final LoginEvent event = (LoginEvent) msg;
|
final LoginEvent event = (LoginEvent) msg;
|
||||||
final int index = localLobby.login(client);
|
final int index = localLobby.connectPlayer(event.getUsername(), event.getAvatarIndex());
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
ctx.close();
|
ctx.close();
|
||||||
} else {
|
} else {
|
||||||
client.setIndex(index);
|
client.setIndex(index);
|
||||||
broadcast(event);
|
broadcast(event);
|
||||||
|
updateLobbyState();
|
||||||
}
|
}
|
||||||
|
} else if (msg instanceof UpdateLobbyPlayerEvent) {
|
||||||
|
updateSlot(client.getIndex(), (UpdateLobbyPlayerEvent) msg);
|
||||||
} else if (msg instanceof MessageEvent) {
|
} else if (msg instanceof MessageEvent) {
|
||||||
final MessageEvent event = (MessageEvent) msg;
|
final MessageEvent event = (MessageEvent) msg;
|
||||||
broadcast(event);
|
lobbyListener.message(event.getSource(), event.getMessage());
|
||||||
}
|
}
|
||||||
super.channelRead(ctx, msg);
|
super.channelRead(ctx, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
|
|
||||||
final RemoteClient client = clients.get(ctx.channel());
|
|
||||||
localLobby.logout(client);
|
|
||||||
updateLobbyState();
|
|
||||||
super.channelInactive(ctx);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DeregisterClientHandler extends ChannelInboundHandlerAdapter {
|
private class DeregisterClientHandler extends ChannelInboundHandlerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
|
||||||
final RemoteClient client = clients.remove(ctx.channel());
|
final RemoteClient client = clients.remove(ctx.channel());
|
||||||
// TODO remove client from games
|
localLobby.disconnectPlayer(client.getIndex());
|
||||||
broadcast(new LogoutEvent(client.getUsername()));
|
broadcast(new LogoutEvent(client.getUsername()));
|
||||||
super.channelInactive(ctx);
|
super.channelInactive(ctx);
|
||||||
}
|
}
|
||||||
|
|||||||
28
forge-gui/src/main/java/forge/net/LobbyUpdateEvent.java
Normal file
28
forge-gui/src/main/java/forge/net/LobbyUpdateEvent.java
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package forge.net;
|
||||||
|
|
||||||
|
import forge.match.GameLobby.GameLobbyData;
|
||||||
|
import forge.net.game.NetEvent;
|
||||||
|
import forge.net.game.server.RemoteClient;
|
||||||
|
|
||||||
|
public class LobbyUpdateEvent implements NetEvent {
|
||||||
|
private static final long serialVersionUID = 7114918637727047985L;
|
||||||
|
|
||||||
|
private final GameLobbyData state;
|
||||||
|
private int slot;
|
||||||
|
public LobbyUpdateEvent(final GameLobbyData state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateForClient(final RemoteClient client) {
|
||||||
|
this.slot = client.getIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameLobbyData getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSlot() {
|
||||||
|
return slot;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
package forge.net;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
|
|
||||||
import forge.ai.LobbyPlayerAi;
|
|
||||||
import forge.deck.Deck;
|
|
||||||
import forge.game.GameRules;
|
|
||||||
import forge.game.player.RegisteredPlayer;
|
|
||||||
import forge.interfaces.IGuiGame;
|
|
||||||
import forge.match.HostedMatch;
|
|
||||||
import forge.match.NetGuiGame;
|
|
||||||
import forge.net.game.server.RemoteClient;
|
|
||||||
import forge.player.LobbyPlayerHuman;
|
|
||||||
|
|
||||||
public final class NetGame {
|
|
||||||
|
|
||||||
private final Map<RemoteClient, NetPlayer> clients = Maps.newHashMap();
|
|
||||||
private final GameRules rules;
|
|
||||||
private final HostedMatch match = new HostedMatch();
|
|
||||||
public NetGame(final GameRules rules) {
|
|
||||||
this.rules = rules;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addClient(final RemoteClient client) {
|
|
||||||
clients.put(client, new NetPlayer(client, new NetGuiGame(client)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startMatch() {
|
|
||||||
final List<RegisteredPlayer> registeredPlayers = Lists.newArrayListWithCapacity(clients.size());
|
|
||||||
final Map<RegisteredPlayer, IGuiGame> guis = Maps.newHashMap();
|
|
||||||
for (final NetPlayer np : clients.values()) {
|
|
||||||
if (np.player == null) {
|
|
||||||
System.err.println("No deck registered for player " + np.client.getUsername());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
registeredPlayers.add(np.player);
|
|
||||||
guis.put(np.player, np.gui);
|
|
||||||
}
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
if (registeredPlayers.size() == 1) {
|
|
||||||
RegisteredPlayer r = new RegisteredPlayer(new Deck());
|
|
||||||
registeredPlayers.add(r);
|
|
||||||
r.setPlayer(new LobbyPlayerAi("AI", new HashMap<String, String>()));
|
|
||||||
}
|
|
||||||
match.startMatch(rules, null, registeredPlayers, guis);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void registerDeck(final RemoteClient client, final Deck deck) {
|
|
||||||
final RegisteredPlayer r = new RegisteredPlayer(deck);
|
|
||||||
clients.get(client).player = r;
|
|
||||||
r.setPlayer(new LobbyPlayerHuman(client.getUsername()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class NetPlayer {
|
|
||||||
private final RemoteClient client;
|
|
||||||
private RegisteredPlayer player = null;
|
|
||||||
private final IGuiGame gui;
|
|
||||||
private NetPlayer(final RemoteClient client, final IGuiGame gui) {
|
|
||||||
this.client = client;
|
|
||||||
this.gui = gui;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
129
forge-gui/src/main/java/forge/net/NetGameController.java
Normal file
129
forge-gui/src/main/java/forge/net/NetGameController.java
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
package forge.net;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import forge.game.card.CardView;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
|
import forge.game.spellability.SpellAbilityView;
|
||||||
|
import forge.interfaces.IDevModeCheats;
|
||||||
|
import forge.interfaces.IGameController;
|
||||||
|
import forge.match.NextGameDecision;
|
||||||
|
import forge.net.game.GuiGameEvent;
|
||||||
|
import forge.net.game.client.IToServer;
|
||||||
|
import forge.util.ITriggerEvent;
|
||||||
|
|
||||||
|
public class NetGameController implements IGameController {
|
||||||
|
|
||||||
|
private final IToServer server;
|
||||||
|
public NetGameController(final IToServer server) {
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String methodName() {
|
||||||
|
boolean passedFirst = false;
|
||||||
|
for (final StackTraceElement ste : Thread.currentThread().getStackTrace()) {
|
||||||
|
if (ste.getClassName() == getClass().getName()) {
|
||||||
|
if (passedFirst) {
|
||||||
|
return ste.getMethodName();
|
||||||
|
}
|
||||||
|
passedFirst = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void send(final String method, final Object... args) {
|
||||||
|
server.send(new GuiGameEvent(method, args));
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <T> T sendAndWait(final String method, final Object... args) {
|
||||||
|
try {
|
||||||
|
return (T) server.sendAndWait(new GuiGameEvent(method, args));
|
||||||
|
} catch (final TimeoutException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean useMana(final byte color) {
|
||||||
|
return sendAndWait(methodName(), color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryUndoLastAction() {
|
||||||
|
return sendAndWait(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectPlayer(final PlayerView playerView, final ITriggerEvent triggerEvent) {
|
||||||
|
send(methodName(), playerView, triggerEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean selectCard(final CardView cardView, final List<CardView> otherCardViewsToSelect, final ITriggerEvent triggerEvent) {
|
||||||
|
return sendAndWait(methodName(), cardView, otherCardViewsToSelect, triggerEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectButtonOk() {
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectButtonCancel() {
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void selectAbility(final SpellAbilityView sa) {
|
||||||
|
send(methodName(), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean passPriorityUntilEndOfTurn() {
|
||||||
|
return sendAndWait(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean passPriority() {
|
||||||
|
return sendAndWait(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void nextGameDecision(final NextGameDecision decision) {
|
||||||
|
send(methodName(), decision);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mayLookAtAllCards() {
|
||||||
|
// Don't do this over network
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getActivateDescription(final CardView card) {
|
||||||
|
return sendAndWait(methodName(), card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void concede() {
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IDevModeCheats cheat() {
|
||||||
|
return IDevModeCheats.NO_CHEAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canPlayUnlimitedLands() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void alphaStrike() {
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
380
forge-gui/src/main/java/forge/net/NetGuiGame.java
Normal file
380
forge-gui/src/main/java/forge/net/NetGuiGame.java
Normal file
@@ -0,0 +1,380 @@
|
|||||||
|
package forge.net;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.EnumMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import forge.LobbyPlayer;
|
||||||
|
import forge.UiCommand;
|
||||||
|
import forge.assets.FSkinProp;
|
||||||
|
import forge.deck.CardPool;
|
||||||
|
import forge.game.GameEntityView;
|
||||||
|
import forge.game.GameView;
|
||||||
|
import forge.game.card.CardView;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.DelayedReveal;
|
||||||
|
import forge.game.player.IHasIcon;
|
||||||
|
import forge.game.player.PlayerView;
|
||||||
|
import forge.game.spellability.SpellAbilityView;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.interfaces.IButton;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.match.AbstractGuiGame;
|
||||||
|
import forge.match.MatchButtonType;
|
||||||
|
import forge.net.game.GuiGameEvent;
|
||||||
|
import forge.net.game.server.IToClient;
|
||||||
|
import forge.trackable.TrackableCollection;
|
||||||
|
import forge.util.ITriggerEvent;
|
||||||
|
|
||||||
|
public class NetGuiGame extends AbstractGuiGame {
|
||||||
|
|
||||||
|
private final IToClient client;
|
||||||
|
private final Map<MatchButtonType, Map<PlayerView, NetButton>> btns = new EnumMap<MatchButtonType, Map<PlayerView,NetButton>>(MatchButtonType.class);
|
||||||
|
public NetGuiGame(final IToClient client) {
|
||||||
|
this.client = client;
|
||||||
|
for (final MatchButtonType type : MatchButtonType.values()) {
|
||||||
|
btns.put(type, Maps.<PlayerView, NetButton>newHashMap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String methodName() {
|
||||||
|
boolean passedFirst = false;
|
||||||
|
for (final StackTraceElement ste : Thread.currentThread().getStackTrace()) {
|
||||||
|
if (ste.getClassName() == getClass().getName()) {
|
||||||
|
if (passedFirst) {
|
||||||
|
return ste.getMethodName();
|
||||||
|
}
|
||||||
|
passedFirst = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void send(final String method, final Object... args) {
|
||||||
|
client.send(new GuiGameEvent(method, args));
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <T> T sendAndWait(final String method, final Object... args) {
|
||||||
|
try {
|
||||||
|
return (T) client.sendAndWait(new GuiGameEvent(method, args));
|
||||||
|
} catch (final TimeoutException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateGameView() {
|
||||||
|
send("setGameView", getGameView());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setGameView(final GameView gameView) {
|
||||||
|
super.setGameView(gameView);
|
||||||
|
updateGameView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void openView(final TrackableCollection<PlayerView> myPlayers) {
|
||||||
|
for (final MatchButtonType type : MatchButtonType.values()) {
|
||||||
|
btns.get(type).clear();
|
||||||
|
for (final PlayerView player : myPlayers) {
|
||||||
|
btns.get(type).put(player, new NetButton(player, type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
send(methodName(), myPlayers);
|
||||||
|
updateGameView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterGameEnd() {
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showCombat() {
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showPromptMessage(final PlayerView playerView, final String message) {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName(), playerView, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stopAtPhase(final PlayerView playerTurn, final PhaseType phase) {
|
||||||
|
return sendAndWait(methodName(), playerTurn, phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IButton getBtnOK(final PlayerView playerView) {
|
||||||
|
return btns.get(MatchButtonType.OK).get(playerView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IButton getBtnCancel(final PlayerView playerView) {
|
||||||
|
return btns.get(MatchButtonType.CANCEL).get(playerView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusButton(final MatchButtonType button) {
|
||||||
|
send(methodName(), button);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flashIncorrectAction() {
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePhase() {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateTurn(final PlayerView player) {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName(), player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePlayerControl() {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enableOverlay() {
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disableOverlay() {
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishGame() {
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object showManaPool(final PlayerView player) {
|
||||||
|
send(methodName(), player);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hideManaPool(final PlayerView player, final Object zoneToRestore) {
|
||||||
|
send(methodName(), player, zoneToRestore);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStack() {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateZones(final List<Pair<PlayerView, ZoneType>> zonesToUpdate) {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName(), zonesToUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSingleCard(final CardView card) {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName(), card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateManaPool(final Iterable<PlayerView> manaPoolUpdate) {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName(), manaPoolUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateLives(final Iterable<PlayerView> livesUpdate) {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName(), livesUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPanelSelection(final CardView hostCard) {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName(), hostCard);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpellAbilityView getAbilityToPlay(final List<SpellAbilityView> abilities, final ITriggerEvent triggerEvent) {
|
||||||
|
return sendAndWait(methodName(), abilities, triggerEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<CardView, Integer> assignDamage(final CardView attacker, final List<CardView> blockers, final int damage, final GameEntityView defender, final boolean overrideOrder) {
|
||||||
|
return sendAndWait(methodName(), attacker, blockers, damage, defender, overrideOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void message(final String message, final String title) {
|
||||||
|
send(methodName(), message, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showErrorDialog(final String message, final String title) {
|
||||||
|
send(methodName(), message, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean showConfirmDialog(final String message, final String title, final String yesButtonText, final String noButtonText, final boolean defaultYes) {
|
||||||
|
return sendAndWait(methodName(), message, title, yesButtonText, noButtonText, defaultYes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int showOptionDialog(final String message, final String title, final FSkinProp icon, final String[] options, final int defaultOption) {
|
||||||
|
return sendAndWait(methodName(), message, title, icon, options, defaultOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int showCardOptionDialog(final CardView card, final String message, final String title, final FSkinProp icon, final String[] options, final int defaultOption) {
|
||||||
|
return sendAndWait(methodName(), card, message, title, icon, options, defaultOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String showInputDialog(final String message, final String title, final FSkinProp icon, final String initialInput, final String[] inputOptions) {
|
||||||
|
return sendAndWait(methodName(), message, title, icon, initialInput, inputOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean confirm(final CardView c, final String question, final boolean defaultIsYes, final String[] options) {
|
||||||
|
return sendAndWait(methodName(), c, question, defaultIsYes, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
|
||||||
|
return sendAndWait(methodName(), message, min, max, choices, selected, display);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax, final List<T> sourceChoices, final List<T> destChoices, final CardView referenceCard, final boolean sideboardingMode) {
|
||||||
|
return sendAndWait(methodName(), title, top, remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices, referenceCard, sideboardingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PaperCard> sideboard(final CardPool sideboard, final CardPool main) {
|
||||||
|
return sendAndWait(methodName(), sideboard, main);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GameEntityView chooseSingleEntityForEffect(final String title, final Collection<? extends GameEntityView> optionList, final DelayedReveal delayedReveal, final boolean isOptional) {
|
||||||
|
return sendAndWait(methodName(), title, optionList, delayedReveal, isOptional);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCard(final CardView card) {
|
||||||
|
updateGameView();
|
||||||
|
send(methodName(), card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean openZones(final Collection<ZoneType> zones, final Map<PlayerView, Object> players) {
|
||||||
|
updateGameView();
|
||||||
|
return sendAndWait(methodName(), zones, players);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void restoreOldZones(final Map<PlayerView, Object> playersToRestoreZonesFor) {
|
||||||
|
send(methodName(), playersToRestoreZonesFor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isUiSetToSkipPhase(final PlayerView playerTurn, final PhaseType phase) {
|
||||||
|
return sendAndWait(methodName(), playerTurn, phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void updateCurrentPlayer(final PlayerView player) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class NetButton implements IButton {
|
||||||
|
|
||||||
|
private String methodName() {
|
||||||
|
boolean passedFirst = false;
|
||||||
|
for (final StackTraceElement ste : Thread.currentThread().getStackTrace()) {
|
||||||
|
if (ste.getClassName() == getClass().getName()) {
|
||||||
|
if (passedFirst) {
|
||||||
|
return ste.getMethodName();
|
||||||
|
}
|
||||||
|
passedFirst = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private final PlayerView playerView;
|
||||||
|
private final MatchButtonType type;
|
||||||
|
private NetButton(final PlayerView playerView, final MatchButtonType type) {
|
||||||
|
this.playerView = playerView;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(final boolean b0) {
|
||||||
|
send("btn_" + methodName(), playerView, type, b0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVisible(final boolean b0) {
|
||||||
|
send("btn_" + methodName(), playerView, type, b0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setText(final String text0) {
|
||||||
|
send("btn_" + methodName(), playerView, type, text0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSelected() {
|
||||||
|
return sendAndWait("btn_" + methodName(), playerView, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSelected(final boolean b0) {
|
||||||
|
send("btn_" + methodName(), playerView, type, b0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean requestFocusInWindow() {
|
||||||
|
return sendAndWait("btn_" + methodName(), playerView, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCommand(final UiCommand command0) {
|
||||||
|
send("btn_" + methodName(), playerView, type, command0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTextColor(final FSkinProp color) {
|
||||||
|
send("btn_" + methodName(), playerView, type, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTextColor(final int r, final int g, final int b) {
|
||||||
|
send("btn_" + methodName(), playerView, type, r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
65
forge-gui/src/main/java/forge/net/ServerGameLobby.java
Normal file
65
forge-gui/src/main/java/forge/net/ServerGameLobby.java
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package forge.net;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import forge.AIOption;
|
||||||
|
import forge.interfaces.IGuiGame;
|
||||||
|
import forge.match.GameLobby;
|
||||||
|
import forge.match.LobbySlot;
|
||||||
|
import forge.net.game.LobbySlotType;
|
||||||
|
|
||||||
|
public final class ServerGameLobby extends GameLobby {
|
||||||
|
|
||||||
|
public ServerGameLobby() {
|
||||||
|
super(true);
|
||||||
|
addSlot(new LobbySlot(LobbySlotType.LOCAL, localName(), localAvatarIndices()[0], 0, true, Collections.<AIOption>emptySet()));
|
||||||
|
addSlot(new LobbySlot(LobbySlotType.OPEN, null, -1, 1, false, Collections.<AIOption>emptySet()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int connectPlayer(final String name, final int avatarIndex) {
|
||||||
|
final int nSlots = getNumberOfSlots();
|
||||||
|
for (int index = 0; index < nSlots; index++) {
|
||||||
|
final LobbySlot slot = getSlot(index);
|
||||||
|
if (slot.getType() == LobbySlotType.OPEN) {
|
||||||
|
connectPlayer(name, avatarIndex, slot);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
private void connectPlayer(final String name, final int avatarIndex, final LobbySlot slot) {
|
||||||
|
slot.setType(LobbySlotType.REMOTE);
|
||||||
|
slot.setName(name);
|
||||||
|
slot.setAvatarIndex(avatarIndex);
|
||||||
|
updateView();
|
||||||
|
}
|
||||||
|
public void disconnectPlayer(final int index) {
|
||||||
|
final LobbySlot slot = getSlot(index);
|
||||||
|
slot.setType(LobbySlotType.OPEN);
|
||||||
|
slot.setName(StringUtils.EMPTY);
|
||||||
|
updateView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean hasControl() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mayEdit(final int index) {
|
||||||
|
final LobbySlotType type = getSlot(index).getType();
|
||||||
|
return type != LobbySlotType.REMOTE && type != LobbySlotType.OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mayControl(final int index) {
|
||||||
|
return getSlot(index).getType() != LobbySlotType.REMOTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public boolean mayRemove(final int index) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public IGuiGame getGui(final int index) {
|
||||||
|
return FServerManager.getInstance().getGui(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,10 @@
|
|||||||
package forge.player;
|
package forge.player;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import forge.AIOption;
|
||||||
import forge.GuiBase;
|
import forge.GuiBase;
|
||||||
import forge.LobbyPlayer;
|
import forge.LobbyPlayer;
|
||||||
import forge.ai.AiProfileUtil;
|
import forge.ai.AiProfileUtil;
|
||||||
@@ -13,8 +16,6 @@ import forge.util.GuiDisplayUtil;
|
|||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
import forge.util.gui.SOptionPane;
|
import forge.util.gui.SOptionPane;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
public final class GamePlayerUtil {
|
public final class GamePlayerUtil {
|
||||||
private GamePlayerUtil() { };
|
private GamePlayerUtil() { };
|
||||||
|
|
||||||
@@ -22,8 +23,8 @@ public final class GamePlayerUtil {
|
|||||||
public static final LobbyPlayer getGuiPlayer() {
|
public static final LobbyPlayer getGuiPlayer() {
|
||||||
return guiPlayer;
|
return guiPlayer;
|
||||||
}
|
}
|
||||||
public static final LobbyPlayer getGuiPlayer(String name, int index) {
|
public static final LobbyPlayer getGuiPlayer(final String name, final boolean writePref) {
|
||||||
if (index == 0) {
|
if (writePref) {
|
||||||
if (!name.equals(guiPlayer.getName())) {
|
if (!name.equals(guiPlayer.getName())) {
|
||||||
guiPlayer.setName(name);
|
guiPlayer.setName(name);
|
||||||
FModel.getPreferences().setPref(FPref.PLAYER_NAME, name);
|
FModel.getPreferences().setPref(FPref.PLAYER_NAME, name);
|
||||||
@@ -49,7 +50,7 @@ public final class GamePlayerUtil {
|
|||||||
public final static LobbyPlayer createAiPlayer(String name, int avatarIndex) {
|
public final static LobbyPlayer createAiPlayer(String name, int avatarIndex) {
|
||||||
return createAiPlayer(name, avatarIndex, null);
|
return createAiPlayer(name, avatarIndex, null);
|
||||||
}
|
}
|
||||||
public final static LobbyPlayer createAiPlayer(String name, int avatarIndex, Map<String, String> options) {
|
public final static LobbyPlayer createAiPlayer(String name, int avatarIndex, Set<AIOption> options) {
|
||||||
LobbyPlayerAi player = new LobbyPlayerAi(name, options);
|
LobbyPlayerAi player = new LobbyPlayerAi(name, options);
|
||||||
|
|
||||||
// TODO: implement specific AI profiles for quest mode.
|
// TODO: implement specific AI profiles for quest mode.
|
||||||
|
|||||||
@@ -1,128 +0,0 @@
|
|||||||
package forge.player;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import forge.game.card.CardView;
|
|
||||||
import forge.game.player.PlayerView;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.interfaces.IDevModeCheats;
|
|
||||||
import forge.interfaces.IGameController;
|
|
||||||
import forge.match.NextGameDecision;
|
|
||||||
import forge.net.game.client.IToServer;
|
|
||||||
import forge.trackable.TrackableObject;
|
|
||||||
import forge.util.ITriggerEvent;
|
|
||||||
|
|
||||||
public class NetGameController implements IGameController {
|
|
||||||
|
|
||||||
private final IToServer server;
|
|
||||||
public NetGameController(final IToServer server) {
|
|
||||||
this.server = server;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void send(final String method) {
|
|
||||||
send(method, Collections.<TrackableObject>emptySet());
|
|
||||||
}
|
|
||||||
private void send(final String method, final TrackableObject object) {
|
|
||||||
send(method, Collections.singleton(object));
|
|
||||||
}
|
|
||||||
private void send(final String method, final Iterable<? extends TrackableObject> objects) {
|
|
||||||
//server.send(new (method, objects));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean mayLookAtAllCards() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canPlayUnlimitedLands() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void concede() {
|
|
||||||
send("concede");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void alphaStrike() {
|
|
||||||
send("alphaStrike");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean useMana(byte color) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectButtonOk() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectButtonCancel() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean passPriority() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean passPriorityUntilEndOfTurn() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectPlayer(PlayerView playerView, ITriggerEvent triggerEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean selectCard(CardView cardView,
|
|
||||||
List<CardView> otherCardViewsToSelect, ITriggerEvent triggerEvent) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectAbility(SpellAbility sa) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean tryUndoLastAction() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IDevModeCheats cheat() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void nextGameDecision(NextGameDecision decision) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getActivateDescription(CardView card) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,7 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -74,6 +75,7 @@ import forge.game.spellability.AbilityManaPart;
|
|||||||
import forge.game.spellability.AbilitySub;
|
import forge.game.spellability.AbilitySub;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
import forge.game.spellability.SpellAbilityStackInstance;
|
||||||
|
import forge.game.spellability.SpellAbilityView;
|
||||||
import forge.game.spellability.TargetChoices;
|
import forge.game.spellability.TargetChoices;
|
||||||
import forge.game.trigger.Trigger;
|
import forge.game.trigger.Trigger;
|
||||||
import forge.game.trigger.WrappedAbility;
|
import forge.game.trigger.WrappedAbility;
|
||||||
@@ -217,8 +219,8 @@ public class PlayerControllerHuman
|
|||||||
* Uses GUI to learn which spell the player (human in our case) would like to play
|
* Uses GUI to learn which spell the player (human in our case) would like to play
|
||||||
*/
|
*/
|
||||||
public SpellAbility getAbilityToPlay(final List<SpellAbility> abilities, final ITriggerEvent triggerEvent) {
|
public SpellAbility getAbilityToPlay(final List<SpellAbility> abilities, final ITriggerEvent triggerEvent) {
|
||||||
return getGui().getAbilityToPlay(abilities, triggerEvent);
|
final SpellAbilityView resultView = getGui().getAbilityToPlay(SpellAbilityView.getCollection(abilities), triggerEvent);
|
||||||
//return HostedMatch.getController().getAbilityToPlay(abilities, triggerEvent);
|
return getGame().getSpellAbility(resultView);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -389,13 +391,13 @@ public class PlayerControllerHuman
|
|||||||
// Human is supposed to read the message and understand from it what to choose
|
// Human is supposed to read the message and understand from it what to choose
|
||||||
if (optionList.isEmpty()) {
|
if (optionList.isEmpty()) {
|
||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
delayedReveal.reveal(this);
|
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (!isOptional && optionList.size() == 1) {
|
if (!isOptional && optionList.size() == 1) {
|
||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
delayedReveal.reveal(this);
|
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||||
}
|
}
|
||||||
return Iterables.getFirst(optionList, null);
|
return Iterables.getFirst(optionList, null);
|
||||||
}
|
}
|
||||||
@@ -416,7 +418,7 @@ public class PlayerControllerHuman
|
|||||||
|
|
||||||
if (canUseSelectCardsInput) {
|
if (canUseSelectCardsInput) {
|
||||||
if (delayedReveal != null) {
|
if (delayedReveal != null) {
|
||||||
delayedReveal.reveal(this);
|
reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||||
}
|
}
|
||||||
InputSelectEntitiesFromList<T> input = new InputSelectEntitiesFromList<T>(this, isOptional ? 0 : 1, 1, optionList);
|
InputSelectEntitiesFromList<T> input = new InputSelectEntitiesFromList<T>(this, isOptional ? 0 : 1, 1, optionList);
|
||||||
input.setCancelAllowed(isOptional);
|
input.setCancelAllowed(isOptional);
|
||||||
@@ -425,8 +427,10 @@ public class PlayerControllerHuman
|
|||||||
return Iterables.getFirst(input.getSelected(), null);
|
return Iterables.getFirst(input.getSelected(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
final GameEntityView result = getGui().chooseSingleEntityForEffect(title, optionList, delayedReveal, isOptional, this);
|
tempShow(optionList);
|
||||||
endTempShowCards(); //assume tempShow called by GuiBase.getInterface().chooseSingleEntityForEffect
|
final GameEntityView result = getGui().chooseSingleEntityForEffect(title, GameEntityView.getEntityCollection(optionList), delayedReveal, isOptional);
|
||||||
|
endTempShowCards();
|
||||||
|
|
||||||
if (result instanceof CardView) {
|
if (result instanceof CardView) {
|
||||||
return (T) game.getCard((CardView)result);
|
return (T) game.getCard((CardView)result);
|
||||||
}
|
}
|
||||||
@@ -563,19 +567,22 @@ public class PlayerControllerHuman
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reveal(CardCollectionView cards, ZoneType zone, Player owner, String message) {
|
public void reveal(CardCollectionView cards, ZoneType zone, Player owner, String message) {
|
||||||
|
reveal(CardView.getCollection(cards), zone, PlayerView.get(owner), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reveal(Collection<CardView> cards, ZoneType zone, PlayerView owner, String message) {
|
||||||
if (StringUtils.isBlank(message)) {
|
if (StringUtils.isBlank(message)) {
|
||||||
message = "Looking at cards in {player's} " + zone.name().toLowerCase();
|
message = "Looking at cards in {player's} " + zone.name().toLowerCase();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
message += "{player's} " + zone.name().toLowerCase();
|
message += "{player's} " + zone.name().toLowerCase();
|
||||||
}
|
}
|
||||||
String fm = MessageUtil.formatMessage(message, player, owner);
|
String fm = MessageUtil.formatMessage(message, player, owner);
|
||||||
if (!cards.isEmpty()) {
|
if (!cards.isEmpty()) {
|
||||||
tempShowCards(cards);
|
tempShowCards(game.getCardList(cards));
|
||||||
getGui().reveal(fm, CardView.getCollection(cards));
|
getGui().reveal(fm, cards);
|
||||||
endTempShowCards();
|
endTempShowCards();
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
getGui().message(MessageUtil.formatMessage("There are no cards in {player's} " +
|
getGui().message(MessageUtil.formatMessage("There are no cards in {player's} " +
|
||||||
zone.name().toLowerCase(), player, owner), fm);
|
zone.name().toLowerCase(), player, owner), fm);
|
||||||
}
|
}
|
||||||
@@ -993,15 +1000,16 @@ public class PlayerControllerHuman
|
|||||||
return Iterables.getFirst(allTargets, null);
|
return Iterables.getFirst(allTargets, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
final Function<Pair<SpellAbilityStackInstance, GameObject>, String> fnToString = new Function<Pair<SpellAbilityStackInstance, GameObject>, String>() {
|
final List<Pair<SpellAbilityStackInstance, GameObject>> chosen = getGui().getChoices(saSpellskite.getHostCard().getName(), 1, 1, allTargets, null, new FnTargetToString());
|
||||||
@Override
|
return Iterables.getFirst(chosen, null);
|
||||||
public String apply(Pair<SpellAbilityStackInstance, GameObject> targ) {
|
}
|
||||||
|
|
||||||
|
private final static class FnTargetToString implements Function<Pair<SpellAbilityStackInstance, GameObject>, String>, Serializable {
|
||||||
|
private static final long serialVersionUID = -4779137632302777802L;
|
||||||
|
|
||||||
|
@Override public String apply(final Pair<SpellAbilityStackInstance, GameObject> targ) {
|
||||||
return targ.getRight().toString() + " - " + targ.getLeft().getStackDescription();
|
return targ.getRight().toString() + " - " + targ.getLeft().getStackDescription();
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
List<Pair<SpellAbilityStackInstance, GameObject>> chosen = getGui().getChoices(saSpellskite.getHostCard().getName(), 1, 1, allTargets, null, fnToString);
|
|
||||||
return Iterables.getFirst(chosen, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1352,8 +1360,8 @@ public class PlayerControllerHuman
|
|||||||
return inputProxy.selectCard(cardView, otherCardViewsToSelect, triggerEvent);
|
return inputProxy.selectCard(cardView, otherCardViewsToSelect, triggerEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectAbility(final SpellAbility sa) {
|
public void selectAbility(final SpellAbilityView sa) {
|
||||||
inputProxy.selectAbility(sa);
|
inputProxy.selectAbility(getGame().getSpellAbility(sa));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void alphaStrike() {
|
public void alphaStrike() {
|
||||||
|
|||||||
41
forge-net/src/main/java/forge/net/ReplyPool.java
Normal file
41
forge-net/src/main/java/forge/net/ReplyPool.java
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package forge.net;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
public class ReplyPool {
|
||||||
|
|
||||||
|
private final Map<Integer, CompletableFuture<Object>> pool = Maps.newHashMap();
|
||||||
|
|
||||||
|
public ReplyPool() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize(final int index) {
|
||||||
|
synchronized (pool) {
|
||||||
|
pool.put(Integer.valueOf(index), new CompletableFuture<Object>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void complete(final int index, final Object value) {
|
||||||
|
synchronized (pool) {
|
||||||
|
pool.get(Integer.valueOf(index)).complete(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object get(final int index) throws TimeoutException {
|
||||||
|
final CompletableFuture<Object> future;
|
||||||
|
synchronized (pool) {
|
||||||
|
future = pool.get(Integer.valueOf(index));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return future.get(1, TimeUnit.MINUTES);
|
||||||
|
} catch (final InterruptedException | ExecutionException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,35 +1,40 @@
|
|||||||
package forge.net.game;
|
package forge.net.game;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
import forge.net.game.server.RemoteClient;
|
import forge.net.game.server.RemoteClient;
|
||||||
import forge.trackable.TrackableObject;
|
|
||||||
|
|
||||||
public final class GuiGameEvent implements NetEvent {
|
public final class GuiGameEvent implements IdentifiableNetEvent {
|
||||||
private static final long serialVersionUID = 6223690008522514574L;
|
private static final long serialVersionUID = 6223690008522514574L;
|
||||||
|
private static int staticId = 0;
|
||||||
|
|
||||||
|
private final int id;
|
||||||
private final String method;
|
private final String method;
|
||||||
private final Iterable<? extends TrackableObject> objects;
|
private final Object[] objects;
|
||||||
|
|
||||||
public GuiGameEvent(final String method, final Iterable<? extends TrackableObject> objects) {
|
public GuiGameEvent(final String method, final Object ... objects) {
|
||||||
|
this.id = staticId++;
|
||||||
this.method = method;
|
this.method = method;
|
||||||
this.objects = objects == null ? ImmutableSet.<TrackableObject>of() : objects;
|
this.objects = objects == null ? new Object[0] : objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("GuiGameEvent %d: %s (%d args)", id, method, objects.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void updateForClient(final RemoteClient client) {
|
public void updateForClient(final RemoteClient client) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
public String getMethod() {
|
public String getMethod() {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TrackableObject getObject() {
|
public Object[] getObjects() {
|
||||||
return Iterables.getFirst(objects, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Iterable<? extends TrackableObject> getObjects() {
|
|
||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
package forge.net.game;
|
package forge.net.game;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
public interface IRemote {
|
public interface IRemote {
|
||||||
void send(NetEvent event);
|
void send(NetEvent event);
|
||||||
|
Object sendAndWait(IdentifiableNetEvent event) throws TimeoutException;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package forge.net.game;
|
||||||
|
|
||||||
|
import forge.game.IIdentifiable;
|
||||||
|
|
||||||
|
public interface IdentifiableNetEvent extends NetEvent, IIdentifiable {
|
||||||
|
}
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
package forge.net.game;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
|
|
||||||
public class LobbyState implements Serializable {
|
|
||||||
private static final long serialVersionUID = 3899410700896996173L;
|
|
||||||
|
|
||||||
private final List<LobbyPlayerData> players = Lists.newArrayList();
|
|
||||||
private int localPlayer = -1;
|
|
||||||
public int getLocalPlayer() {
|
|
||||||
return localPlayer;
|
|
||||||
}
|
|
||||||
public void setLocalPlayer(final int localPlayer) {
|
|
||||||
this.localPlayer = localPlayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addPlayer(final LobbyPlayerData data) {
|
|
||||||
players.add(data);
|
|
||||||
}
|
|
||||||
public List<LobbyPlayerData> getPlayers() {
|
|
||||||
return Collections.unmodifiableList(players);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final static class LobbyPlayerData implements Serializable {
|
|
||||||
private static final long serialVersionUID = 8642923786206592216L;
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final int avatarIndex;
|
|
||||||
private final LobbySlotType type;
|
|
||||||
public LobbyPlayerData(final String name, final int avatarIndex, final LobbySlotType type) {
|
|
||||||
this.name = name;
|
|
||||||
this.avatarIndex = avatarIndex;
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
public int getAvatarIndex() {
|
|
||||||
return avatarIndex;
|
|
||||||
}
|
|
||||||
public LobbySlotType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package forge.net.game;
|
|
||||||
|
|
||||||
import forge.net.game.server.RemoteClient;
|
|
||||||
|
|
||||||
public class LobbyUpdateEvent implements NetEvent {
|
|
||||||
private static final long serialVersionUID = -3176971304173703949L;
|
|
||||||
|
|
||||||
private final LobbyState state;
|
|
||||||
public LobbyUpdateEvent(final LobbyState state) {
|
|
||||||
this.state = state;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateForClient(final RemoteClient client) {
|
|
||||||
state.setLocalPlayer(client.getIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
public LobbyState getState() {
|
|
||||||
return state;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -6,8 +6,10 @@ public class LoginEvent implements NetEvent {
|
|||||||
private static final long serialVersionUID = -8865183377417377938L;
|
private static final long serialVersionUID = -8865183377417377938L;
|
||||||
|
|
||||||
private final String username;
|
private final String username;
|
||||||
public LoginEvent(final String username) {
|
private final int avatarIndex;
|
||||||
|
public LoginEvent(final String username, final int avatarIndex) {
|
||||||
this.username = username;
|
this.username = username;
|
||||||
|
this.avatarIndex = avatarIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -17,4 +19,8 @@ public class LoginEvent implements NetEvent {
|
|||||||
public String getUsername() {
|
public String getUsername() {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getAvatarIndex() {
|
||||||
|
return avatarIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
package forge.net.game;
|
|
||||||
|
|
||||||
import forge.deck.Deck;
|
|
||||||
import forge.net.game.server.RemoteClient;
|
|
||||||
|
|
||||||
public class RegisterDeckEvent implements NetEvent {
|
|
||||||
private static final long serialVersionUID = -6553476654530937343L;
|
|
||||||
|
|
||||||
private final Deck deck;
|
|
||||||
public RegisterDeckEvent(final Deck deck) {
|
|
||||||
this.deck = deck;
|
|
||||||
}
|
|
||||||
public void updateForClient(final RemoteClient client) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public final Deck getDeck() {
|
|
||||||
return deck;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
31
forge-net/src/main/java/forge/net/game/ReplyEvent.java
Normal file
31
forge-net/src/main/java/forge/net/game/ReplyEvent.java
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package forge.net.game;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import forge.net.game.server.RemoteClient;
|
||||||
|
|
||||||
|
public final class ReplyEvent implements NetEvent {
|
||||||
|
private static final long serialVersionUID = -2814651319617795386L;
|
||||||
|
|
||||||
|
private final int index;
|
||||||
|
private final Serializable reply;
|
||||||
|
public ReplyEvent(final int index, final Serializable reply) {
|
||||||
|
this.index = index;
|
||||||
|
this.reply = reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
public Object getReply() {
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public void updateForClient(final RemoteClient client) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("Reply (%d): %s", index, reply);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package forge.net.game;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import forge.AIOption;
|
||||||
|
import forge.deck.CardPool;
|
||||||
|
import forge.deck.Deck;
|
||||||
|
import forge.deck.DeckSection;
|
||||||
|
import forge.net.game.server.RemoteClient;
|
||||||
|
|
||||||
|
public final class UpdateLobbyPlayerEvent implements NetEvent {
|
||||||
|
private static final long serialVersionUID = -5073305607515425968L;
|
||||||
|
|
||||||
|
private final LobbySlotType type;
|
||||||
|
private final String name;
|
||||||
|
private final int avatarIndex;
|
||||||
|
private final int team;
|
||||||
|
private final Boolean isArchenemy;
|
||||||
|
private final Deck deck;
|
||||||
|
private final DeckSection section;
|
||||||
|
private final CardPool cards;
|
||||||
|
private final Set<AIOption> aiOptions;
|
||||||
|
|
||||||
|
public static UpdateLobbyPlayerEvent create(final LobbySlotType type, final String name, final int avatarIndex, final int team, final boolean isArchenemy, final Set<AIOption> aiOptions) {
|
||||||
|
return new UpdateLobbyPlayerEvent(type, name, avatarIndex, team, isArchenemy, null, null, null, aiOptions);
|
||||||
|
}
|
||||||
|
public static UpdateLobbyPlayerEvent deckUpdate(final Deck deck) {
|
||||||
|
return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, deck, null, null, null);
|
||||||
|
}
|
||||||
|
public static UpdateLobbyPlayerEvent deckUpdate(final DeckSection section, final CardPool cards) {
|
||||||
|
return new UpdateLobbyPlayerEvent(null, null, -1, -1, null, null, section, cards, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private UpdateLobbyPlayerEvent(final LobbySlotType type, final String name, final int avatarIndex, final int team, final Boolean isArchenemy, final Deck deck, final DeckSection section, final CardPool cards, final Set<AIOption> aiOptions) {
|
||||||
|
this.type = type;
|
||||||
|
this.name = name;
|
||||||
|
this.avatarIndex = avatarIndex;
|
||||||
|
this.team = team;
|
||||||
|
this.isArchenemy = isArchenemy;
|
||||||
|
this.deck = deck;
|
||||||
|
this.section = section;
|
||||||
|
this.cards = cards;
|
||||||
|
this.aiOptions = aiOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateForClient(final RemoteClient client) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public LobbySlotType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
public int getAvatarIndex() {
|
||||||
|
return avatarIndex;
|
||||||
|
}
|
||||||
|
public int getTeam() {
|
||||||
|
return team;
|
||||||
|
}
|
||||||
|
public Boolean getArchenemy() {
|
||||||
|
return isArchenemy;
|
||||||
|
}
|
||||||
|
public Deck getDeck() {
|
||||||
|
return deck;
|
||||||
|
}
|
||||||
|
public DeckSection getSection() {
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
public CardPool getCards() {
|
||||||
|
return cards;
|
||||||
|
}
|
||||||
|
public Set<AIOption> getAiOptions() {
|
||||||
|
return aiOptions == null ? null : Collections.unmodifiableSet(aiOptions);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user