mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +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:
@@ -56,8 +56,10 @@ import forge.game.player.Player;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.player.RegisteredPlayer;
|
||||
import forge.game.replacement.ReplacementHandler;
|
||||
import forge.game.spellability.Ability;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.spellability.SpellAbilityView;
|
||||
import forge.game.trigger.TriggerHandler;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.MagicStack;
|
||||
@@ -105,20 +107,20 @@ public class Game {
|
||||
private final GameView view;
|
||||
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) {
|
||||
return playerCache.get(playerView);
|
||||
}
|
||||
public void addPlayer(Integer id, Player player) {
|
||||
playerCache.put(id, player);
|
||||
public void addPlayer(int id, Player 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) {
|
||||
return cardCache.get(cardView);
|
||||
}
|
||||
public void addCard(Integer id, Card card) {
|
||||
cardCache.put(id, card);
|
||||
public void addCard(int id, Card card) {
|
||||
cardCache.put(Integer.valueOf(id), card);
|
||||
}
|
||||
public CardCollection getCardList(Iterable<CardView> cardViews) {
|
||||
CardCollection list = new CardCollection();
|
||||
@@ -126,10 +128,20 @@ public class Game {
|
||||
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 */
|
||||
rules = rules0;
|
||||
match = match0;
|
||||
|
||||
spabCache.put(Ability.PLAY_LAND_SURROGATE.getId(), Ability.PLAY_LAND_SURROGATE);
|
||||
|
||||
int highestTeam = -1;
|
||||
for (RegisteredPlayer psc : players0) {
|
||||
// Track highest team number for auto assigning unassigned teams
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package forge.game;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
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>();
|
||||
|
||||
public void put(Integer id, Entity entity) {
|
||||
|
||||
@@ -7,6 +7,8 @@ import forge.trackable.TrackableProperty;
|
||||
import forge.trackable.Tracker;
|
||||
|
||||
public abstract class GameEntityView extends TrackableObject {
|
||||
private static final long serialVersionUID = -5129089945124455670L;
|
||||
|
||||
public static GameEntityView get(GameEntity e) {
|
||||
return e == null ? null : e.getView();
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package forge.game;
|
||||
|
||||
import forge.game.event.IGameEventVisitor;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Observable;
|
||||
@@ -30,10 +31,12 @@ import java.util.Observable;
|
||||
* @author Forge
|
||||
* @version $Id: GameLog.java 12297 2011-11-28 19:56:47Z slapshot5 $
|
||||
*/
|
||||
public class GameLog extends Observable {
|
||||
private List<GameLogEntry> log = new ArrayList<GameLogEntry>();
|
||||
public class GameLog extends Observable implements Serializable {
|
||||
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:
|
||||
* 0 - Turn
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
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 GameLogEntryType type;
|
||||
// might add here date and some other fields
|
||||
@@ -10,10 +13,9 @@ public class GameLogEntry {
|
||||
type = type0;
|
||||
message = messageIn;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
// TODO Auto-generated method stub
|
||||
return type.getCaption() + ": " + message;
|
||||
}
|
||||
}
|
||||
@@ -111,14 +111,14 @@ public class GameLogFormatter extends IGameEventVisitor.Base<GameLogEntry> {
|
||||
|
||||
@Override
|
||||
public GameLogEntry visit(final GameEventPlayerControl event) {
|
||||
final LobbyPlayer newController = event.newController;
|
||||
final LobbyPlayer newLobbyPlayer = event.newLobbyPlayer;
|
||||
final Player p = event.player;
|
||||
|
||||
final String message;
|
||||
if (newController == null) {
|
||||
if (newLobbyPlayer == null) {
|
||||
message = p.getName() + " has restored control over themself";
|
||||
} 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);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import forge.item.PaperCard;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@@ -41,7 +42,9 @@ import java.util.Map.Entry;
|
||||
// only getters) and
|
||||
// GameObserver class - who should be notified of any considerable ingame event
|
||||
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> wonCards;
|
||||
|
||||
@@ -50,8 +53,7 @@ public final class GameOutcome implements Iterable<Pair<LobbyPlayer, PlayerStati
|
||||
if (won) {
|
||||
this.wonCards = cards;
|
||||
this.lostCards = new ArrayList<>();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.lostCards = cards;
|
||||
this.wonCards = new ArrayList<>();
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package forge.game;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.deck.Deck;
|
||||
import forge.game.GameOutcome.AnteResult;
|
||||
@@ -22,6 +24,7 @@ import forge.trackable.TrackableProperty;
|
||||
import forge.util.FCollectionView;
|
||||
|
||||
public class GameView extends TrackableObject {
|
||||
private static final long serialVersionUID = 8522884512960961528L;
|
||||
|
||||
/*private final TrackableIndex<CardView> cards = new TrackableIndex<CardView>();
|
||||
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 TrackableCollection<PlayerView> players;
|
||||
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) {
|
||||
super(-1, game0.getTracker()); //ID not needed
|
||||
@@ -88,10 +91,17 @@ public class GameView extends TrackableObject {
|
||||
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() {
|
||||
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());
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
public FCollectionView<StackItemView> getStack() {
|
||||
return StackItemView.getCollection(game.getStack());
|
||||
}
|
||||
|
||||
public boolean isMatchWonBy(LobbyPlayer questPlayer) {
|
||||
return game.getMatch().isWonBy(questPlayer);
|
||||
}
|
||||
@@ -182,10 +188,6 @@ public class GameView extends TrackableObject {
|
||||
return game.getOutcome().getWinningLobbyPlayer();
|
||||
}
|
||||
|
||||
public StackItemView peekStack() {
|
||||
return StackItemView.get(game.getStack().peek());
|
||||
}
|
||||
|
||||
public boolean isWinner(LobbyPlayer guiPlayer) {
|
||||
return game.getOutcome().isWinner(guiPlayer);
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import forge.game.event.GameEventCombatChanged;
|
||||
import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
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);
|
||||
CardCollectionView shown = !decider.hasKeyword("LimitSearchLibrary") ? player.getCardsIn(ZoneType.Library) : player.getCardsIn(ZoneType.Library, fetchNum);
|
||||
// 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)) {
|
||||
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 ");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -765,13 +766,13 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
}
|
||||
if (sa.hasParam("ShareLandType")) {
|
||||
for (final Card card : chosenCards) {
|
||||
|
||||
|
||||
fetchList = CardLists.filter(fetchList, new Predicate<Card>() {
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return c.sharesLandTypeWith(card);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(final Card c) {
|
||||
return c.sharesLandTypeWith(card);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -784,7 +785,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
Card c = null;
|
||||
if (sa.hasParam("AtRandom")) {
|
||||
if (delayedReveal != null) {
|
||||
delayedReveal.reveal(decider.getController());
|
||||
decider.getController().reveal(delayedReveal.getCards(), delayedReveal.getZone(), delayedReveal.getOwner(), delayedReveal.getMessagePrefix());
|
||||
}
|
||||
c = Aggregates.random(fetchList);
|
||||
}
|
||||
@@ -812,7 +813,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect {
|
||||
|
||||
fetchList.remove(c);
|
||||
if (delayedReveal != null) {
|
||||
delayedReveal.remove(c);
|
||||
delayedReveal.remove(CardView.get(c));
|
||||
}
|
||||
chosenCards.add(c);
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.player.DelayedReveal;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.PlayerZone;
|
||||
@@ -144,7 +145,7 @@ public class DigEffect extends SpellAbilityEffect {
|
||||
}
|
||||
else if (!sa.hasParam("NoLooking")) {
|
||||
// show the user the revealed cards
|
||||
delayedReveal = new DelayedReveal(top, srcZone, p);
|
||||
delayedReveal = new DelayedReveal(top, srcZone, PlayerView.get(p));
|
||||
|
||||
if (noMove) {
|
||||
// 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;
|
||||
|
||||
public class CardCollection extends FCollection<Card> implements CardCollectionView {
|
||||
private static final long serialVersionUID = -8133537013727100275L;
|
||||
|
||||
public static final CardCollectionView EMPTY = new CardCollection();
|
||||
|
||||
public static boolean hasCard(CardCollection cards) {
|
||||
|
||||
@@ -10,10 +10,10 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.ImageKeys;
|
||||
import forge.card.CardStateName;
|
||||
import forge.card.CardEdition;
|
||||
import forge.card.CardRarity;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardStateName;
|
||||
import forge.card.CardType;
|
||||
import forge.card.CardTypeView;
|
||||
import forge.card.ColorSet;
|
||||
@@ -32,6 +32,8 @@ import forge.trackable.Tracker;
|
||||
import forge.util.FCollectionView;
|
||||
|
||||
public class CardView extends GameEntityView {
|
||||
private static final long serialVersionUID = -3624090829028979255L;
|
||||
|
||||
public static CardView get(Card c) {
|
||||
return c == null ? null : c.getView();
|
||||
}
|
||||
@@ -715,6 +717,8 @@ public class CardView extends GameEntityView {
|
||||
}
|
||||
|
||||
public class CardStateView extends TrackableObject {
|
||||
private static final long serialVersionUID = 6673944200513430607L;
|
||||
|
||||
private final CardStateName state;
|
||||
|
||||
public CardStateView(final int id0, final CardStateName state0, final Tracker tracker) {
|
||||
|
||||
@@ -17,6 +17,8 @@ import forge.util.FCollection;
|
||||
|
||||
|
||||
public class CombatView extends TrackableObject {
|
||||
private static final long serialVersionUID = 68085618912864941L;
|
||||
|
||||
public CombatView(final Tracker tracker) {
|
||||
super(-1, tracker); //ID not needed
|
||||
set(TrackableProperty.AttackersWithDefenders, new HashMap<CardView, GameEntityView>());
|
||||
|
||||
@@ -2,20 +2,25 @@ package forge.game.event;
|
||||
|
||||
import forge.LobbyPlayer;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerController;
|
||||
|
||||
public class GameEventPlayerControl extends GameEvent {
|
||||
public final Player player;
|
||||
public final LobbyPlayer oldController;
|
||||
public final LobbyPlayer newController;
|
||||
public final LobbyPlayer oldLobbyPlayer;
|
||||
public final PlayerController oldController;
|
||||
public final LobbyPlayer newLobbyPlayer;
|
||||
public final PlayerController newController;
|
||||
|
||||
public GameEventPlayerControl(Player p, LobbyPlayer old, LobbyPlayer new1) {
|
||||
player = p;
|
||||
oldController = old;
|
||||
newController = new1;
|
||||
public GameEventPlayerControl(final Player p, final LobbyPlayer oldLobbyPlayer, final PlayerController oldController, final LobbyPlayer newLobbyPlayer, final PlayerController newController) {
|
||||
this.player = p;
|
||||
this.oldLobbyPlayer = oldLobbyPlayer;
|
||||
this.oldController = oldController;
|
||||
this.newLobbyPlayer = newLobbyPlayer;
|
||||
this.newController = newController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T visit(IGameEventVisitor<T> visitor) {
|
||||
public <T> T visit(final IGameEventVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package forge.game.keyword;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
@@ -7,8 +8,10 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class KeywordCollection implements Iterable<String> {
|
||||
private KeywordCollectionView view;
|
||||
public class KeywordCollection implements Iterable<String>, Serializable {
|
||||
private static final long serialVersionUID = -2882986558147844702L;
|
||||
|
||||
private transient KeywordCollectionView view;
|
||||
private final EnumMap<Keyword, List<KeywordInstance<?>>> map = new EnumMap<Keyword, List<KeywordInstance<?>>>(Keyword.class);
|
||||
|
||||
public boolean contains(Keyword keyword) {
|
||||
@@ -134,7 +137,9 @@ public class KeywordCollection implements Iterable<String> {
|
||||
return view;
|
||||
}
|
||||
|
||||
public class KeywordCollectionView implements Iterable<String> {
|
||||
public class KeywordCollectionView implements Iterable<String>, Serializable {
|
||||
private static final long serialVersionUID = 7536969077044188264L;
|
||||
|
||||
protected KeywordCollectionView() {
|
||||
}
|
||||
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
package forge.game.player;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardView;
|
||||
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 {
|
||||
private final CardCollection cards;
|
||||
private final Collection<CardView> cards;
|
||||
private final ZoneType zone;
|
||||
private final Player owner;
|
||||
private final PlayerView owner;
|
||||
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);
|
||||
}
|
||||
public DelayedReveal(Iterable<Card> cards0, ZoneType zone0, Player owner0, String messagePrefix0) {
|
||||
cards = new CardCollection(cards0); //create copy of list to allow modification
|
||||
public DelayedReveal(Iterable<Card> cards0, ZoneType zone0, PlayerView owner0, String messagePrefix0) {
|
||||
cards = CardView.getCollection(cards0);
|
||||
zone = zone0;
|
||||
owner = owner0;
|
||||
messagePrefix = messagePrefix0;
|
||||
}
|
||||
|
||||
public Iterable<Card> getCards() {
|
||||
public Collection<CardView> getCards() {
|
||||
return cards;
|
||||
}
|
||||
|
||||
@@ -30,17 +34,16 @@ public class DelayedReveal {
|
||||
return zone;
|
||||
}
|
||||
|
||||
public Player getOwner() {
|
||||
public PlayerView getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void remove(Card card) {
|
||||
public String getMessagePrefix() {
|
||||
return messagePrefix;
|
||||
}
|
||||
|
||||
public void remove(CardView 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;
|
||||
}
|
||||
|
||||
public final void setMindSlaveMaster(Player mindSlaveMaster0) {
|
||||
public final void setMindSlaveMaster(final Player mindSlaveMaster0) {
|
||||
if (mindSlaveMaster == mindSlaveMaster0) {
|
||||
return;
|
||||
}
|
||||
@@ -2107,14 +2107,14 @@ public class Player extends GameEntity implements Comparable<Player> {
|
||||
view.updateMindSlaveMaster(this);
|
||||
|
||||
if (mindSlaveMaster != null) {
|
||||
LobbyPlayer oldLobbyPlayer = getLobbyPlayer();
|
||||
IGameEntitiesFactory master = (IGameEntitiesFactory)mindSlaveMaster.getLobbyPlayer();
|
||||
final LobbyPlayer oldLobbyPlayer = getLobbyPlayer();
|
||||
final PlayerController oldController = getController();
|
||||
final IGameEntitiesFactory master = (IGameEntitiesFactory)mindSlaveMaster.getLobbyPlayer();
|
||||
controller = master.createMindSlaveController(mindSlaveMaster, this);
|
||||
game.fireEvent(new GameEventPlayerControl(this, oldLobbyPlayer, getLobbyPlayer()));
|
||||
}
|
||||
else {
|
||||
game.fireEvent(new GameEventPlayerControl(this, oldLobbyPlayer, oldController, getLobbyPlayer(), controller));
|
||||
} else {
|
||||
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.CardCollectionView;
|
||||
import forge.game.card.CardShields;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.combat.Combat;
|
||||
import forge.game.cost.Cost;
|
||||
@@ -140,6 +141,8 @@ public abstract class PlayerController {
|
||||
reveal(cards, zone, owner, null);
|
||||
}
|
||||
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 */
|
||||
public abstract void notifyOfValue(SpellAbility saSource, GameObject realtedTarget, String value);
|
||||
public abstract ImmutablePair<CardCollection, CardCollection> arrangeForScry(CardCollection topN);
|
||||
|
||||
@@ -21,8 +21,9 @@ import forge.trackable.TrackableProperty;
|
||||
import forge.trackable.Tracker;
|
||||
import forge.util.FCollectionView;
|
||||
|
||||
|
||||
public class PlayerView extends GameEntityView {
|
||||
private static final long serialVersionUID = 7005892740909549086L;
|
||||
|
||||
public static PlayerView get(Player p) {
|
||||
return p == null ? null : p.getView();
|
||||
}
|
||||
|
||||
@@ -75,11 +75,11 @@ public abstract class Ability extends SpellAbility {
|
||||
|
||||
return this.getHostCard().isInPlay() && !this.getHostCard().isFaceDown();
|
||||
}
|
||||
|
||||
|
||||
public static final Ability PLAY_LAND_SURROGATE = new Ability(null, (Cost)null, null){
|
||||
@Override
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
return true; //if this ability is added anywhere, it can be assumed that land can be played
|
||||
return true; //if this ability is added anywhere, it can be assumed that land can be played
|
||||
}
|
||||
@Override
|
||||
public void resolve() {
|
||||
|
||||
@@ -147,12 +147,23 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
view0 = new SpellAbilityView(this);
|
||||
}
|
||||
view = view0;
|
||||
if (hostCard != null && hostCard.getGame() != null) {
|
||||
hostCard.getGame().addSpellAbility(id, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
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
|
||||
public void setHostCard(final Card c) {
|
||||
@@ -1247,6 +1258,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
}
|
||||
|
||||
public SpellAbilityView getView() {
|
||||
view.updateHostCard(this);
|
||||
view.updateDescription(this);
|
||||
view.updateCanPlay(this);
|
||||
view.updatePromptIfOnlyPossibleAbility(this);
|
||||
return view;
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,9 @@ import forge.trackable.TrackableCollection;
|
||||
import forge.trackable.TrackableObject;
|
||||
import forge.trackable.TrackableProperty;
|
||||
|
||||
|
||||
public class SpellAbilityView extends TrackableObject {
|
||||
private static final long serialVersionUID = 2514234930798754769L;
|
||||
|
||||
public static SpellAbilityView get(SpellAbility spab) {
|
||||
return spab == null ? null : spab.getView();
|
||||
}
|
||||
|
||||
@@ -7,8 +7,9 @@ import forge.trackable.TrackableObject;
|
||||
import forge.trackable.TrackableProperty;
|
||||
import forge.util.FCollectionView;
|
||||
|
||||
|
||||
public class StackItemView extends TrackableObject {
|
||||
private static final long serialVersionUID = 6733415646691356052L;
|
||||
|
||||
public static StackItemView get(SpellAbilityStackInstance si) {
|
||||
return si == null ? null : si.getView();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,16 @@
|
||||
*/
|
||||
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.google.common.collect.Iterables;
|
||||
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.ReplacementHandler;
|
||||
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.TriggerType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* MagicStack class.
|
||||
@@ -518,6 +531,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
|
||||
setResolving(false);
|
||||
unfreezeStack();
|
||||
sa.resetOnceResolved();
|
||||
game.updateStackForView();
|
||||
|
||||
//game.getAction().checkStaticAbilities();
|
||||
game.getPhaseHandler().onStackResolved();
|
||||
|
||||
@@ -5,6 +5,8 @@ import java.util.Collection;
|
||||
import forge.util.FCollection;
|
||||
|
||||
public class TrackableCollection<T extends TrackableObject> extends FCollection<T> {
|
||||
private static final long serialVersionUID = 1528674215758232314L;
|
||||
|
||||
public TrackableCollection() {
|
||||
}
|
||||
public TrackableCollection(T e) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package forge.trackable;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Map;
|
||||
@@ -8,7 +9,9 @@ import java.util.Set;
|
||||
import forge.game.IIdentifiable;
|
||||
|
||||
//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;
|
||||
protected final transient Tracker tracker;
|
||||
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
|
||||
protected final void flagAsChanged(final TrackableProperty key) {
|
||||
changedProps.add(key);
|
||||
|
||||
@@ -142,6 +142,7 @@ public enum TrackableProperty {
|
||||
MatchOver(TrackableTypes.BooleanType),
|
||||
NumGamesInMatch(TrackableTypes.IntegerType),
|
||||
NumPlayedGamesInMatch(TrackableTypes.IntegerType),
|
||||
Stack(TrackableTypes.StackItemViewListType),
|
||||
StormCount(TrackableTypes.IntegerType),
|
||||
GameOver(TrackableTypes.BooleanType),
|
||||
PoisonCountersToLose(TrackableTypes.IntegerType),
|
||||
|
||||
@@ -13,8 +13,8 @@ import forge.card.ColorSet;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.game.GameEntityView;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.card.CardView.CardStateView;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.keyword.KeywordCollection.KeywordCollectionView;
|
||||
import forge.game.player.PlayerView;
|
||||
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>() {
|
||||
@Override
|
||||
public ManaCost getDefaultValue() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package forge.util;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -12,7 +13,9 @@ import java.util.ListIterator;
|
||||
import java.util.Set;
|
||||
|
||||
//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 LinkedList<T> list = new LinkedList<T>();
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import forge.game.GameObject;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
|
||||
public class MessageUtil {
|
||||
@@ -17,6 +18,14 @@ public class MessageUtil {
|
||||
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
|
||||
public static String formatNotificationMessage(SpellAbility sa, Player player, GameObject target, String value) {
|
||||
if (sa == null || sa.getApi() == null || sa.getHostCard() == null) {
|
||||
@@ -50,4 +59,7 @@ public class MessageUtil {
|
||||
public static String mayBeYou(Player player, Object what) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user