Swap out old GameView structure for new one

This commit is contained in:
drdev
2014-10-10 05:52:18 +00:00
parent 42e3778778
commit 3538823e11
151 changed files with 1763 additions and 5291 deletions

View File

@@ -11,14 +11,16 @@ import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Sets;
import forge.game.GameView;
import forge.game.card.CardUtil;
import forge.game.card.CardView;
import forge.game.card.CardView.CardStateView;
import forge.game.card.CounterType;
import forge.item.InventoryItemFromSet;
import forge.item.PreconDeck;
import forge.item.SealedProduct;
import forge.match.MatchUtil;
import forge.util.Lang;
import forge.view.CardView;
import forge.view.CardView.CardStateView;
public class CardDetailUtil {
private CardDetailUtil() {
@@ -272,8 +274,8 @@ public class CardDetailUtil {
}
// text changes
final Map<String, String> changedColorWords = state.getChangedColorWords(),
changedTypes = state.getChangedTypes();
final Map<String, String> changedColorWords = card.getChangedColorWords();
final Map<String, String> changedTypes = card.getChangedTypes();
if (!(changedColorWords.isEmpty() && changedTypes.isEmpty())) {
if (area.length() != 0) {
area.append("\n");
@@ -302,13 +304,15 @@ public class CardDetailUtil {
}
// counter text
for (final Entry<CounterType, Integer> c : card.getCounters().entrySet()) {
if (c.getValue().intValue() != 0) {
if (area.length() != 0) {
area.append("\n");
if (card.getCounters() != null) {
for (final Entry<CounterType, Integer> c : card.getCounters().entrySet()) {
if (c.getValue().intValue() != 0) {
if (area.length() != 0) {
area.append("\n");
}
area.append(c.getKey().getName() + " counters: ");
area.append(c.getValue());
}
area.append(c.getKey().getName() + " counters: ");
area.append(c.getValue());
}
}
@@ -332,7 +336,7 @@ public class CardDetailUtil {
}
// Regeneration Shields
final int regenShields = card.getRegenerationShields();
final int regenShields = card.getShieldCount();
if (regenShields > 0) {
if (area.length() != 0) {
area.append("\n");
@@ -359,7 +363,7 @@ public class CardDetailUtil {
}
// chosen color
if (!card.getChosenColors().isEmpty()) {
if (card.getChosenColors() != null) {
if (area.length() != 0) {
area.append("\n");
}
@@ -397,7 +401,7 @@ public class CardDetailUtil {
}
// equipped by
if (card.getEquippedBy().iterator().hasNext()) {
if (card.isEquipped()) {
if (area.length() != 0) {
area.append("\n");
}
@@ -426,7 +430,7 @@ public class CardDetailUtil {
}
// enchanted by
if (card.getEnchantedBy().iterator().hasNext()) {
if (card.isEnchanted()) {
if (area.length() != 0) {
area.append("\n");
}
@@ -441,7 +445,7 @@ public class CardDetailUtil {
}
// controlling
if (card.getGainControlTargets().iterator().hasNext()) {
if (card.getGainControlTargets() != null) {
if (area.length() != 0) {
area.append("\n");
}
@@ -466,12 +470,12 @@ public class CardDetailUtil {
}
// Imprint
if (card.getImprinted().iterator().hasNext()) {
if (card.getImprintedCards() != null) {
if (area.length() != 0) {
area.append("\n");
}
area.append("Imprinting: ");
for (final Iterator<CardView> it = card.getImprinted().iterator(); it.hasNext();) {
for (final Iterator<CardView> it = card.getImprintedCards().iterator(); it.hasNext();) {
area.append(it.next());
if (it.hasNext()) {
area.append(", ");
@@ -480,7 +484,7 @@ public class CardDetailUtil {
}
// Haunt
if (card.getHauntedBy().iterator().hasNext()) {
if (card.getHauntedBy() != null) {
if (area.length() != 0) {
area.append("\n");
}
@@ -500,25 +504,24 @@ public class CardDetailUtil {
}
// must block
if (card.getMustBlock().iterator().hasNext()) {
if (card.getMustBlockCards() != null) {
if (area.length() != 0) {
area.append("\n");
}
final String mustBlockThese = Lang.joinHomogenous(card.getMustBlock());
final String mustBlockThese = Lang.joinHomogenous(card.getMustBlockCards());
area.append("Must block " + mustBlockThese);
}
/*show current storm count for storm cards
//show current storm count for storm cards
if (state.hasStorm()) {
Game game = GuiBase.getInterface().getGame();
if (game != null) {
GameView gameView = MatchUtil.getGameView();
if (gameView != null) {
if (area.length() != 0) {
area.append("\n\n");
}
area.append("Current Storm Count: " + game.getStack().getCardsCastThisTurn().size());
area.append("Current Storm Count: " + gameView.getStormCount());
}
}*/
}
return area.toString();
}
}

View File

@@ -14,6 +14,7 @@ import com.google.common.eventbus.Subscribe;
import forge.GuiBase;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardView;
import forge.game.event.GameEvent;
import forge.game.event.GameEventAnteCardsSelected;
import forge.game.event.GameEventAttackersDeclared;
@@ -44,6 +45,7 @@ import forge.game.event.GameEventTurnPhase;
import forge.game.event.GameEventZone;
import forge.game.event.IGameEventVisitor;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.zone.PlayerZone;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
@@ -52,18 +54,14 @@ import forge.match.MatchUtil;
import forge.match.input.ButtonUtil;
import forge.match.input.InputBase;
import forge.model.FModel;
import forge.player.PlayerControllerHuman;
import forge.properties.ForgePreferences.FPref;
import forge.util.Lang;
import forge.util.gui.SGuiChoose;
import forge.util.maps.MapOfLists;
import forge.view.CardView;
import forge.view.LocalGameView;
import forge.view.PlayerView;
public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
private final LocalGameView gameView;
private final HashSet<CardView> cardsProcessed = new HashSet<CardView>();
private final HashSet<PlayerView> playersProcessed = new HashSet<PlayerView>();
private final PlayerControllerHuman humanController;
private final HashSet<CardView> cardsUpdate = new HashSet<CardView>();
private final HashSet<CardView> cardsRefreshDetails = new HashSet<CardView>();
private final HashSet<PlayerView> livesUpdate = new HashSet<PlayerView>();
@@ -74,13 +72,8 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
private boolean gameOver, gameFinished;
private PlayerView turnUpdate;
public FControlGameEventHandler(final LocalGameView gameView0) {
gameView = gameView0;
// aggressively cache a view for each player (also caches cards)
for (Player player : gameView.getGame().getRegisteredPlayers()) {
gameView.getPlayerView(player, true);
}
public FControlGameEventHandler(final PlayerControllerHuman humanController0) {
humanController = humanController0;
}
private final Runnable processEvents = new Runnable() {
@@ -88,19 +81,6 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
public void run() {
processEventsQueued = false;
synchronized (cardsProcessed) {
if (!cardsProcessed.isEmpty()) {
gameView.updateCards(cardsProcessed);
cardsProcessed.clear();
}
}
synchronized (playersProcessed) {
if (!playersProcessed.isEmpty()) {
gameView.updatePlayers(playersProcessed);
playersProcessed.clear();
}
}
IMatchController controller = MatchUtil.getController();
synchronized (livesUpdate) {
if (!livesUpdate.isEmpty()) {
@@ -124,8 +104,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
}
if (needCombatUpdate) {
needCombatUpdate = false;
gameView.refreshCombat();
controller.showCombat(gameView.getCombat());
controller.showCombat();
}
if (needStackUpdate) {
needStackUpdate = false;
@@ -155,16 +134,16 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
}
if (gameOver) {
gameOver = false;
gameView.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete
humanController.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete
}
if (gameFinished) {
gameFinished = false;
PlayerView localPlayer = gameView.getLocalPlayerView();
PlayerView localPlayer = humanController.getLocalPlayerView();
InputBase.cancelAwaitNextInput(); //ensure "Waiting for opponent..." doesn't appear behind WinLo
controller.showPromptMessage(localPlayer, ""); //clear prompt behind WinLose overlay
ButtonUtil.update(localPlayer, "", "", false, false, false);
controller.finishGame();
gameView.updateAchievements();
humanController.updateAchievements();
}
}
};
@@ -182,38 +161,24 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
}
private Void processCard(Card card, HashSet<CardView> list) {
CardView view = gameView.getCardView(card, null); //delay update until later to avoid duplicating updates
synchronized (list) {
list.add(view);
}
synchronized (cardsProcessed) {
cardsProcessed.add(view);
list.add(card.getView());
}
return processEvent();
}
private Void processCards(Collection<Card> cards, HashSet<CardView> list) {
if (cards.isEmpty()) { return null; }
List<CardView> views = gameView.getCardViews(cards, null); //delay update until later to avoid duplicating updates
synchronized (list) {
list.addAll(views);
}
synchronized (cardsProcessed) {
cardsProcessed.addAll(views);
for (Card c : cards) {
list.add(c.getView());
}
}
return processEvent();
}
private PlayerView processPlayer(Player player) {
PlayerView view = gameView.getPlayerView(player, null); //delay update until later to avoid duplicating updates
synchronized (playersProcessed) {
playersProcessed.add(view);
}
return view;
}
private Void processPlayer(Player player, HashSet<PlayerView> list) {
PlayerView view = processPlayer(player);
synchronized (list) {
list.add(view);
list.add(player.getView());
}
return processEvent();
}
@@ -225,14 +190,13 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
private Void updateZone(Player p, ZoneType z) {
if (p == null || z == null) { return null; }
PlayerView view = processPlayer(p);
synchronized (zonesUpdate) {
for (Pair<PlayerView, ZoneType> pair : zonesUpdate) {
if (pair.getLeft() == view && pair.getRight() == z) {
if (pair.getLeft() == p.getView() && pair.getRight() == z) {
return null; //avoid adding the same pair multiple times
}
}
zonesUpdate.add(Pair.of(view, z));
zonesUpdate.add(Pair.of(p.getView(), z));
}
return processEvent();
}
@@ -251,8 +215,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
@Override
public Void visit(final GameEventTurnBegan event) {
turnUpdate = processPlayer(event.turnOwner);
turnUpdate = event.turnOwner.getView();
if (FModel.getPreferences().getPrefBoolean(FPref.UI_STACK_CREATURES) && event.turnOwner != null) {
// anything except stack will get here
updateZone(event.turnOwner, ZoneType.Battlefield);
@@ -264,10 +227,10 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
public Void visit(GameEventAnteCardsSelected ev) {
final List<CardView> options = Lists.newArrayList();
for (final Entry<Player, Card> kv : ev.cards.entries()) {
final CardView fakeCard = new CardView(-1); //use fake card so real cards appear with proper formatting
fakeCard.getOriginal().setName(" -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --");
//use fake card so real cards appear with proper formatting
final CardView fakeCard = new CardView(-1, " -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --");
options.add(fakeCard);
options.add(gameView.getCardView(kv.getValue(), true));
options.add(kv.getValue().getView());
}
SGuiChoose.reveal("These cards were chosen to ante", options);
return null;

View File

@@ -9,6 +9,7 @@ import com.google.common.eventbus.Subscribe;
import forge.FThreads;
import forge.GuiBase;
import forge.game.Game;
import forge.game.card.CardView;
import forge.game.event.GameEvent;
import forge.game.event.GameEventBlockersDeclared;
import forge.game.event.GameEventGameFinished;
@@ -19,9 +20,10 @@ import forge.game.event.GameEventSpellAbilityCast;
import forge.game.event.GameEventSpellResolved;
import forge.game.event.GameEventTurnPhase;
import forge.game.event.IGameEventVisitor;
import forge.game.player.PlayerView;
import forge.match.MatchUtil;
import forge.match.input.InputPlaybackControl;
import forge.view.LocalGameView;
import forge.player.PlayerControllerHuman;
public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
private InputPlaybackControl inputPlayback;
@@ -29,9 +31,9 @@ public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
private final CyclicBarrier gameThreadPauser = new CyclicBarrier(2);
private final LocalGameView gameView;
public FControlGamePlayback(final LocalGameView gameView0) {
gameView = gameView0;
private final PlayerControllerHuman humanController;
public FControlGamePlayback(final PlayerControllerHuman humanController0) {
humanController = humanController0;
}
private Game game;
@@ -75,8 +77,7 @@ public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
*/
@Override
public Void visit(GameEventTurnPhase ev) {
boolean isUiToStop = MatchUtil.getController().stopAtPhase(
gameView.getPlayerView(ev.playerTurn, true), ev.phase);
boolean isUiToStop = MatchUtil.getController().stopAtPhase(PlayerView.get(ev.playerTurn), ev.phase);
switch(ev.phase) {
case COMBAT_END:
@@ -101,13 +102,13 @@ public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
*/
@Override
public Void visit(GameEventGameFinished event) {
gameView.getInputQueue().removeInput(inputPlayback);
humanController.getInputQueue().removeInput(inputPlayback);
return null;
}
@Override
public Void visit(GameEventGameStarted event) {
gameView.getInputQueue().setInput(inputPlayback);
humanController.getInputQueue().setInput(inputPlayback);
return null;
}
@@ -122,7 +123,7 @@ public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
GuiBase.getInterface().setCard(gameView.getCardView(event.spell.getHostCard(), true));
GuiBase.getInterface().setCard(CardView.get(event.spell.getHostCard()));
}
});
pauseForEvent(resolveDelay);
@@ -137,7 +138,7 @@ public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
GuiBase.getInterface().setCard(gameView.getCardView(event.sa.getHostCard(), true));
GuiBase.getInterface().setCard(CardView.get(event.sa.getHostCard()));
}
});
pauseForEvent(castDelay);

View File

@@ -1,30 +1,24 @@
/**
*
*/
package forge.view;
package forge.control;
import forge.LobbyPlayer;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardView;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbility;
import forge.match.input.Input;
import forge.match.input.InputPlaybackControl;
import forge.match.input.InputQueue;
import forge.player.PlayerControllerHuman.DevModeCheats;
import forge.player.PlayerControllerHuman;
import forge.util.ITriggerEvent;
/**
* @author elcnesh
*
*/
public class WatchLocalGame extends LocalGameView {
/**
* @param game
* the @{link Game} to attach to.
* @param inputQueue
* the {@link InputQueue} of the game to enable playback
* controls, or {@code null} to disallow them.
*/
public WatchLocalGame(Game game0) {
super(game0);
public class WatchLocalGame extends PlayerControllerHuman {
public WatchLocalGame(Game game0, Player p, LobbyPlayer lp) {
super(game0, p, lp);
}
@Override
@@ -42,7 +36,7 @@ public class WatchLocalGame extends LocalGameView {
@Override
public void selectButtonOk() {
if (this.inputQueue == null) {
if (inputQueue == null) {
return;
}
final Input i = inputQueue.getInput();
@@ -53,7 +47,7 @@ public class WatchLocalGame extends LocalGameView {
@Override
public void selectButtonCancel() {
if (this.inputQueue == null) {
if (inputQueue == null) {
return;
}
final Input i = inputQueue.getInput();
@@ -90,7 +84,7 @@ public class WatchLocalGame extends LocalGameView {
}
@Override
public void selectAbility(final SpellAbilityView sa) {
public void selectAbility(final SpellAbility sa) {
}
@Override
@@ -148,11 +142,6 @@ public class WatchLocalGame extends LocalGameView {
return false;
}
@Override
public boolean canViewAllCards() {
return false;
}
@Override
public DevModeCheats cheat() {
return null;

View File

@@ -1,14 +1,10 @@
package forge.events;
import forge.view.CardView;
import forge.view.GameEntityView;
import forge.game.GameEntityView;
import forge.game.card.CardView;
/**
* TODO: Write javadoc for this type.
*
*/
public class UiEventAttackerDeclared extends UiEvent {
public final CardView attacker;
public final GameEntityView defender;

View File

@@ -1,9 +1,8 @@
package forge.events;
import forge.view.CardView;
import forge.game.card.CardView;
public class UiEventBlockerAssigned extends UiEvent {
public final CardView blocker;
public final CardView attackerBeingBlocked;
@@ -16,6 +15,4 @@ public class UiEventBlockerAssigned extends UiEvent {
public <T> T visit(final IUiEventVisitor<T> visitor) {
return visitor.visit(this);
}
}

View File

@@ -8,19 +8,19 @@ import forge.LobbyPlayer;
import forge.assets.FSkinProp;
import forge.deck.Deck;
import forge.game.GameType;
import forge.game.GameView;
import forge.game.player.RegisteredPlayer;
import forge.interfaces.IButton;
import forge.interfaces.IWinLoseView;
import forge.match.MatchUtil;
import forge.model.FModel;
import forge.player.GamePlayerUtil;
import forge.view.IGameView;
public abstract class GauntletWinLoseController {
private final IGameView lastGame;
private final GameView lastGame;
private final IWinLoseView<? extends IButton> view;
public GauntletWinLoseController(IWinLoseView<? extends IButton> view0, final IGameView game0) {
public GauntletWinLoseController(IWinLoseView<? extends IButton> view0, final GameView game0) {
view = view0;
lastGame = game0;
}

View File

@@ -11,14 +11,14 @@ import forge.assets.FSkinProp;
import forge.assets.ISkinImage;
import forge.deck.CardPool;
import forge.game.GameEntity;
import forge.game.GameEntityView;
import forge.game.card.CardView;
import forge.game.player.DelayedReveal;
import forge.game.player.IHasIcon;
import forge.item.PaperCard;
import forge.player.PlayerControllerHuman;
import forge.sound.IAudioClip;
import forge.sound.IAudioMusic;
import forge.view.CardView;
import forge.view.GameEntityView;
public interface IGuiBase {
boolean isRunningOnDesktop();

View File

@@ -1,19 +1,19 @@
package forge.limited;
import forge.game.GameView;
import forge.interfaces.IButton;
import forge.interfaces.IWinLoseView;
import forge.model.FModel;
import forge.player.GamePlayerUtil;
import forge.view.IGameView;
public abstract class LimitedWinLoseController {
private final IWinLoseView<? extends IButton> view;
private final IGameView lastGame;
private final GameView lastGame;
private final boolean wonMatch;
private GauntletMini gauntlet;
private boolean nextRound = false;
public LimitedWinLoseController(IWinLoseView<? extends IButton> view0, final IGameView game0) {
public LimitedWinLoseController(IWinLoseView<? extends IButton> view0, final GameView game0) {
view = view0;
lastGame = game0;
gauntlet = FModel.getGauntletMini();
@@ -31,7 +31,8 @@ public abstract class LimitedWinLoseController {
if (lastGame.isWinner(GamePlayerUtil.getGuiPlayer())) {
gauntlet.addWin();
} else {
}
else {
gauntlet.addLoss();
}

View File

@@ -7,17 +7,16 @@ import java.util.Map;
import org.apache.commons.lang3.tuple.Pair;
import forge.LobbyPlayer;
import forge.game.GameEntityView;
import forge.game.Match;
import forge.game.card.CardView;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbility;
import forge.game.zone.ZoneType;
import forge.interfaces.IButton;
import forge.util.ITriggerEvent;
import forge.view.CardView;
import forge.view.CombatView;
import forge.view.GameEntityView;
import forge.view.PlayerView;
import forge.view.SpellAbilityView;
public interface IMatchController {
void startNewMatch(Match match);
@@ -25,7 +24,7 @@ public interface IMatchController {
boolean hotSeatMode();
void openView(List<Player> sortedPlayers);
void afterGameEnd();
void showCombat(CombatView combat);
void showCombat();
void showPromptMessage(PlayerView playerView, String message);
boolean stopAtPhase(PlayerView playerTurn, PhaseType phase);
IButton getBtnOK(PlayerView playerView);
@@ -50,6 +49,6 @@ public interface IMatchController {
void updateLives(Iterable<PlayerView> livesUpdate);
void setPanelSelection(CardView hostCard);
void hear(LobbyPlayer player, String message);
int getAbilityToPlay(List<SpellAbilityView> abilities, ITriggerEvent triggerEvent);
SpellAbility getAbilityToPlay(List<SpellAbility> abilities, ITriggerEvent triggerEvent);
Map<CardView, Integer> assignDamage(CardView attacker, List<CardView> blockers, int damage, GameEntityView defender, boolean overrideOrder);
}

View File

@@ -26,21 +26,24 @@ import forge.ai.LobbyPlayerAi;
import forge.card.CardCharacteristicName;
import forge.control.FControlGameEventHandler;
import forge.control.FControlGamePlayback;
import forge.control.WatchLocalGame;
import forge.events.IUiEventVisitor;
import forge.events.UiEvent;
import forge.events.UiEventAttackerDeclared;
import forge.events.UiEventBlockerAssigned;
import forge.game.Game;
import forge.game.GameEntityView;
import forge.game.GameRules;
import forge.game.GameType;
import forge.game.GameView;
import forge.game.Match;
import forge.game.card.Card;
import forge.game.card.CardView;
import forge.game.card.CounterType;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.player.RegisteredPlayer;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.match.input.InputPlaybackControl;
@@ -56,33 +59,12 @@ import forge.sound.SoundSystem;
import forge.util.GuiDisplayUtil;
import forge.util.NameGenerator;
import forge.util.gui.SOptionPane;
import forge.view.Cache;
import forge.view.CardView;
import forge.view.CombatView;
import forge.view.GameEntityView;
import forge.view.LocalGameView;
import forge.view.PlayerView;
import forge.view.SpellAbilityView;
import forge.view.StackItemView;
import forge.view.WatchLocalGame;
public class MatchUtil {
private static IMatchController controller;
private static Game game;
private static Player currentPlayer;
private static final List<LocalGameView> gameViews = new ArrayList<LocalGameView>();
/** Cache of players. */
public static final Cache<Player, PlayerView> players = new Cache<>();
/** Cache of cards. */
public static final Cache<Card, CardView> cards = new Cache<>();
/** Cache of spellabilities. */
public static final Cache<SpellAbility, SpellAbilityView> spabs = new Cache<>();
/** Cache of stack items. */
public static final Cache<SpellAbilityStackInstance, StackItemView> stackItems = new Cache<>();
/** Cache of combat. */
public static CombatView cachedCombatView = null;
private static final List<PlayerControllerHuman> humanControllers = new ArrayList<PlayerControllerHuman>();
private static int humanCount;
private static final EventBus uiEvents;
private static FControlGamePlayback playbackControl;
@@ -177,23 +159,21 @@ public class MatchUtil {
p.getLobbyPlayer().setAvatarIndex(avatarIndex);
if (p.getController() instanceof PlayerControllerHuman) {
final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController();
LocalGameView gameView = controller.getGameView();
final PlayerControllerHuman humanController = (PlayerControllerHuman) p.getController();
if (humanCount == 0) {
currentPlayer = p;
game.subscribeToEvents(new FControlGameEventHandler(gameView));
game.subscribeToEvents(new FControlGameEventHandler(humanController));
}
gameViews.add(gameView);
humanControllers.add(humanController);
humanCount++;
}
}
if (humanCount == 0) { //watch game but do not participate
LocalGameView gameView = new WatchLocalGame(game);
currentPlayer = sortedPlayers.get(0);
gameView.setLocalPlayer(currentPlayer);
game.subscribeToEvents(new FControlGameEventHandler(gameView));
gameViews.add(gameView);
PlayerControllerHuman humanController = new WatchLocalGame(game, currentPlayer, currentPlayer.getLobbyPlayer());
game.subscribeToEvents(new FControlGameEventHandler(humanController));
humanControllers.add(humanController);
}
else if (humanCount == sortedPlayers.size() && controller.hotSeatMode()) {
//if there are no AI's, allow all players to see all cards (hotseat mode).
@@ -205,16 +185,11 @@ public class MatchUtil {
controller.openView(sortedPlayers);
if (humanCount == 0) {
playbackControl = new FControlGamePlayback(getGameView());
playbackControl = new FControlGamePlayback(getHumanController());
playbackControl.setGame(game);
game.subscribeToEvents(playbackControl);
}
//ensure opponents set properly
for (PlayerView pv : gameViews.get(0).getPlayers()) {
pv.setOpponents(gameViews.get(0).getPlayerViews(players.getKey(pv.getId()).getOpponents(), false));
}
// It's important to run match in a different thread to allow GUI inputs to be invoked from inside game.
// Game is set on pause while gui player takes decisions
game.getAction().invoke(new Runnable() {
@@ -236,18 +211,21 @@ public class MatchUtil {
public static Game getGame() {
return game;
}
public static LocalGameView getGameView() {
return getGameView(currentPlayer);
public static GameView getGameView() {
return game == null ? null : game.getView();
}
public static LocalGameView getGameView(Player player) {
switch (gameViews.size()) {
public static PlayerControllerHuman getHumanController() {
return getHumanController(currentPlayer);
}
public static PlayerControllerHuman getHumanController(Player player) {
switch (humanControllers.size()) {
case 1:
return gameViews.get(0);
return humanControllers.get(0);
case 0:
return null;
default:
return gameViews.get(player.getId());
return humanControllers.get(player.getId());
}
}
@@ -255,28 +233,28 @@ public class MatchUtil {
return humanCount;
}
public static LocalGameView getOtherGameView() {
public static PlayerControllerHuman getOtherHumanController() {
//return other game view besides current game view
if (gameViews.size() < 2) {
if (humanControllers.size() < 2) {
return null;
}
LocalGameView gameView = getGameView();
if (gameView == gameViews.get(0)) {
return gameViews.get(1);
PlayerControllerHuman humanController = getHumanController();
if (humanController == humanControllers.get(0)) {
return humanControllers.get(1);
}
return gameViews.get(0);
return humanControllers.get(0);
}
public static InputQueue getInputQueue() {
LocalGameView gameView = getGameView();
if (gameView != null) {
return gameView.getInputQueue();
PlayerControllerHuman humanController = getHumanController();
if (humanController != null) {
return humanController.getInputQueue();
}
return null;
}
public static void endCurrentTurn() {
getGameView().passPriorityUntilEndOfTurn();
getHumanController().passPriorityUntilEndOfTurn();
}
public static Player getCurrentPlayer() {
@@ -285,13 +263,13 @@ public class MatchUtil {
public static void setCurrentPlayer(Player currentPlayer0) {
if (currentPlayer == currentPlayer0) { return; }
currentPlayer = currentPlayer0;
if (gameViews.size() > 1) {
gameViews.get(0).updateAllCards(); //ensure card views updated when current player changes to account for changes in card visibility
if (humanControllers.size() > 1) {
//TODO: ensure card views updated when current player changes to account for changes in card visibility
}
}
public static void alphaStrike() {
getGameView().alphaStrike();
getHumanController().alphaStrike();
}
public static Map<CardView, Integer> getDamageToAssign(final CardView attacker, final List<CardView> blockers, final int damage, final GameEntityView defender, final boolean overrideOrder) {
@@ -380,11 +358,7 @@ public class MatchUtil {
game = null;
currentPlayer = null;
gameViews.clear();
players.clear();
cards.clear();
spabs.clear();
stackItems.clear();
humanControllers.clear();
controller.afterGameEnd();
}

View File

@@ -17,9 +17,9 @@
*/
package forge.match.input;
import forge.game.player.PlayerView;
import forge.interfaces.IButton;
import forge.match.MatchUtil;
import forge.view.PlayerView;
/**
* Manages match UI OK/Cancel button enabling and focus

View File

@@ -2,9 +2,9 @@ package forge.match.input;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbility;
import forge.util.ITriggerEvent;
import forge.view.PlayerView;
public interface Input {
PlayerView getOwner();

View File

@@ -28,19 +28,21 @@ import com.google.common.collect.Sets;
import forge.events.UiEventAttackerDeclared;
import forge.game.GameEntity;
import forge.game.GameEntityView;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CardPredicates.Presets;
import forge.game.card.CardView;
import forge.game.combat.AttackingBand;
import forge.game.combat.Combat;
import forge.game.combat.CombatUtil;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.zone.ZoneType;
import forge.match.MatchUtil;
import forge.player.PlayerControllerHuman;
import forge.util.ITriggerEvent;
import forge.view.CardView;
/**
* <p>
@@ -51,7 +53,6 @@ import forge.view.CardView;
* @version $Id: InputAttack.java 24769 2014-02-09 13:56:04Z Hellfish $
*/
public class InputAttack extends InputSyncronizedBase {
/** Constant <code>serialVersionUID=7849903731842214245L</code>. */
private static final long serialVersionUID = 7849903731842214245L;
private final Combat combat;
@@ -67,7 +68,6 @@ public class InputAttack extends InputSyncronizedBase {
defenders = combat.getDefenders();
}
/** {@inheritDoc} */
@Override
public final void showMessage() {
// TODO still seems to have some issues with multiple planeswalkers
@@ -83,8 +83,8 @@ public class InputAttack extends InputSyncronizedBase {
for (Pair<Card, GameEntity> attacker : mandatoryAttackers) {
combat.addAttacker(attacker.getLeft(), attacker.getRight());
MatchUtil.fireEvent(new UiEventAttackerDeclared(
getController().getCardView(attacker.getLeft()),
getController().getGameEntityView(attacker.getRight())));
CardView.get(attacker.getLeft()),
GameEntityView.get(attacker.getRight())));
}
updateMessage();
}
@@ -108,7 +108,6 @@ public class InputAttack extends InputSyncronizedBase {
}
}
/** {@inheritDoc} */
@Override
protected final void onOk() {
// TODO Add check to see if each must attack creature is attacking
@@ -118,7 +117,6 @@ public class InputAttack extends InputSyncronizedBase {
stop();
}
/** {@inheritDoc} */
@Override
protected final void onCancel() {
//either alpha strike or undeclare all attackers based on whether any attackers have been declared
@@ -128,14 +126,15 @@ public class InputAttack extends InputSyncronizedBase {
for (Card c : attackers) {
undeclareAttacker(c);
}
} else {
}
else {
alphaStrike();
}
updateMessage();
}
void alphaStrike() {
//alpha strike
//alpha strike
final List<Player> defenders = playerAttacks.getOpponents();
final Set<CardView> refreshCards = Sets.newHashSet();
@@ -147,7 +146,7 @@ public class InputAttack extends InputSyncronizedBase {
for (Player defender : defenders) {
if (CombatUtil.canAttack(c, defender, combat)) {
combat.addAttacker(c, defender);
refreshCards.add(getController().getCardView(c));
refreshCards.add(CardView.get(c));
break;
}
}
@@ -166,7 +165,6 @@ public class InputAttack extends InputSyncronizedBase {
}
}
/** {@inheritDoc} */
@Override
protected final boolean onCardSelected(final Card card, final ITriggerEvent triggerEvent) {
final List<Card> att = combat.getAttackers();
@@ -240,8 +238,8 @@ public class InputAttack extends InputSyncronizedBase {
activateBand(activeBand);
MatchUtil.fireEvent(new UiEventAttackerDeclared(
getController().getCardView(card),
getController().getGameEntityView(currentDefender)));
CardView.get(card),
GameEntityView.get(currentDefender)));
}
private boolean canUndeclareAttacker(Card card) {
@@ -255,12 +253,12 @@ public class InputAttack extends InputSyncronizedBase {
if (canUndeclareAttacker(card)) {
// TODO Is there no way to attacks each turn cards to attack Planeswalkers?
combat.removeFromCombat(card);
MatchUtil.setUsedToPay(getController().getCardView(card), false);
MatchUtil.setUsedToPay(CardView.get(card), false);
// When removing an attacker clear the attacking band
activateBand(null);
MatchUtil.fireEvent(new UiEventAttackerDeclared(
getController().getCardView(card), null));
CardView.get(card), null));
return true;
}
return false;
@@ -270,10 +268,10 @@ public class InputAttack extends InputSyncronizedBase {
currentDefender = def;
for (final GameEntity ge : defenders) {
if (ge instanceof Card) {
MatchUtil.setUsedToPay(getController().getCardView((Card) ge), ge == def);
MatchUtil.setUsedToPay(CardView.get((Card) ge), ge == def);
}
else if (ge instanceof Player) {
MatchUtil.setHighlighted(getController().getPlayerView((Player) ge), ge == def);
MatchUtil.setHighlighted(PlayerView.get((Player) ge), ge == def);
}
}
@@ -283,14 +281,14 @@ public class InputAttack extends InputSyncronizedBase {
private final void activateBand(final AttackingBand band) {
if (activeBand != null) {
for (final Card card : activeBand.getAttackers()) {
MatchUtil.setUsedToPay(getController().getCardView(card), false);
MatchUtil.setUsedToPay(CardView.get(card), false);
}
}
activeBand = band;
if (activeBand != null) {
for (final Card card : activeBand.getAttackers()) {
MatchUtil.setUsedToPay(getController().getCardView(card), true);
MatchUtil.setUsedToPay(CardView.get(card), true);
}
}
}
@@ -314,6 +312,6 @@ public class InputAttack extends InputSyncronizedBase {
showMessage(message);
updatePrompt();
MatchUtil.getController().showCombat(getController().getCombat()); // redraw sword icons
MatchUtil.getController().showCombat(); // redraw sword icons
}
}

View File

@@ -25,12 +25,11 @@ import forge.game.Game;
import forge.game.card.Card;
import forge.game.phase.PhaseHandler;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbility;
import forge.match.MatchUtil;
import forge.player.PlayerControllerHuman;
import forge.util.ITriggerEvent;
import forge.view.LocalGameView;
import forge.view.PlayerView;
/**
* <p>
@@ -51,11 +50,8 @@ public abstract class InputBase implements java.io.Serializable, Input {
public final PlayerControllerHuman getController() {
return controller;
}
public LocalGameView getGameView() {
return controller.getGameView();
}
public PlayerView getOwner() {
return controller.getPlayerView(controller.getPlayer());
return controller.getPlayer().getView();
}
private boolean finished = false;
@@ -64,7 +60,7 @@ public abstract class InputBase implements java.io.Serializable, Input {
finished = true;
if (allowAwaitNextInput()) {
awaitNextInput(getGameView());
awaitNextInput(controller);
}
}
@@ -75,7 +71,7 @@ public abstract class InputBase implements java.io.Serializable, Input {
private static final Timer awaitNextInputTimer = new Timer();
private static TimerTask awaitNextInputTask;
public static void awaitNextInput(final LocalGameView gameView) {
public static void awaitNextInput(final PlayerControllerHuman controller) {
//delay updating prompt to await next input briefly so buttons don't flicker disabled then enabled
awaitNextInputTask = new TimerTask() {
@Override
@@ -85,7 +81,7 @@ public abstract class InputBase implements java.io.Serializable, Input {
public void run() {
synchronized (awaitNextInputTimer) {
if (awaitNextInputTask != null) {
updatePromptForAwait(gameView);
updatePromptForAwait(controller);
awaitNextInputTask = null;
}
}
@@ -97,20 +93,20 @@ public abstract class InputBase implements java.io.Serializable, Input {
}
public static void waitForOtherPlayer() {
final LocalGameView gameView = MatchUtil.getOtherGameView();
if (gameView == null) { return; }
final PlayerControllerHuman controller = MatchUtil.getOtherHumanController();
if (controller == null) { return; }
cancelAwaitNextInput();
FThreads.invokeInEdtNowOrLater(new Runnable() {
@Override
public void run() {
updatePromptForAwait(gameView);
updatePromptForAwait(controller);
}
});
}
private static void updatePromptForAwait(final LocalGameView gameView) {
PlayerView playerView = gameView.getLocalPlayerView();
private static void updatePromptForAwait(final PlayerControllerHuman controller) {
PlayerView playerView = controller.getLocalPlayerView();
MatchUtil.getController().showPromptMessage(playerView, "Waiting for opponent...");
ButtonUtil.update(playerView, false, false, false);
}

View File

@@ -22,6 +22,7 @@ import forge.events.UiEventBlockerAssigned;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates.Presets;
import forge.game.card.CardView;
import forge.game.combat.Combat;
import forge.game.combat.CombatUtil;
import forge.game.event.GameEventCombatChanged;
@@ -32,7 +33,6 @@ import forge.player.PlayerControllerHuman;
import forge.util.ITriggerEvent;
import forge.util.ThreadUtil;
import forge.util.gui.SGuiDialog;
import forge.view.CardView;
/**
* <p>
@@ -87,7 +87,7 @@ public class InputBlock extends InputSyncronizedBase {
showMessage(message);
}
MatchUtil.getController().showCombat(getController().getCombat());
MatchUtil.getController().showCombat();
}
/** {@inheritDoc} */
@@ -117,7 +117,7 @@ public class InputBlock extends InputSyncronizedBase {
if (triggerEvent != null && triggerEvent.getButton() == 3 && card.getController() == defender) {
combat.removeFromCombat(card);
MatchUtil.fireEvent(new UiEventBlockerAssigned(
getController().getCardView(card), (CardView) null));
CardView.get(card), (CardView) null));
isCorrectAction = true;
}
else {
@@ -133,7 +133,7 @@ public class InputBlock extends InputSyncronizedBase {
//if creature already blocking current attacker, remove blocker from combat
combat.removeBlockAssignment(currentAttacker, card);
MatchUtil.fireEvent(new UiEventBlockerAssigned(
getController().getCardView(card), (CardView) null));
CardView.get(card), (CardView) null));
isCorrectAction = true;
}
else {
@@ -141,8 +141,8 @@ public class InputBlock extends InputSyncronizedBase {
if (isCorrectAction) {
combat.addBlocker(currentAttacker, card);
MatchUtil.fireEvent(new UiEventBlockerAssigned(
getController().getCardView(card),
getController().getCardView(currentAttacker)));
CardView.get(card),
CardView.get(currentAttacker)));
}
}
}
@@ -162,7 +162,7 @@ public class InputBlock extends InputSyncronizedBase {
private void setCurrentAttacker(final Card card) {
currentAttacker = card;
for (final Card c : combat.getAttackers()) {
MatchUtil.setUsedToPay(getController().getCardView(c), card == c);
MatchUtil.setUsedToPay(CardView.get(c), card == c);
}
}
}

View File

@@ -22,6 +22,7 @@ import java.util.List;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.card.CardView;
import forge.game.player.Player;
import forge.game.zone.ZoneType;
import forge.match.MatchUtil;
@@ -30,7 +31,6 @@ import forge.util.ITriggerEvent;
import forge.util.Lang;
import forge.util.ThreadUtil;
import forge.util.gui.SGuiDialog;
import forge.view.CardView;
/**
* <p>
@@ -102,7 +102,7 @@ public class InputConfirmMulligan extends InputSyncronizedBase {
if (isCommander) {
// Clear the "selected" icon after clicking the done button
for (final Card c : this.selected) {
MatchUtil.setUsedToPay(getController().getCardView(c), false);
MatchUtil.setUsedToPay(c.getView(), false);
}
}
stop();
@@ -120,7 +120,7 @@ public class InputConfirmMulligan extends InputSyncronizedBase {
return false;
}
final CardView cView = getController().getCardView(c0);
final CardView cView = c0.getView();
if (isSerumPowder && SGuiDialog.confirm(cView, "Use " + cView + "'s ability?")) {
cardSelectLocked = true;
ThreadUtil.invokeInGameThread(new Runnable() {
@@ -138,11 +138,11 @@ public class InputConfirmMulligan extends InputSyncronizedBase {
if (isCommander) { // allow to choose cards for partial paris
if (selected.contains(c0)) {
MatchUtil.setUsedToPay(getController().getCardView(c0), false);
MatchUtil.setUsedToPay(c0.getView(), false);
selected.remove(c0);
}
else {
MatchUtil.setUsedToPay(getController().getCardView(c0), true);
MatchUtil.setUsedToPay(c0.getView(), true);
selected.add(c0);
}
ButtonUtil.update(getOwner(), "Keep", "Exile", true, !selected.isEmpty(), true);

View File

@@ -6,11 +6,11 @@ import forge.FThreads;
import forge.game.Game;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbility;
import forge.match.MatchUtil;
import forge.util.ITriggerEvent;
import forge.util.ThreadUtil;
import forge.view.PlayerView;
public class InputLockUI implements Input {
private final AtomicInteger iCall = new AtomicInteger();

View File

@@ -18,6 +18,7 @@ import forge.game.card.Card;
import forge.game.card.CardUtil;
import forge.game.mana.ManaCostBeingPaid;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.replacement.ReplacementEffect;
import forge.game.spellability.AbilityManaPart;
import forge.game.spellability.SpellAbility;
@@ -54,13 +55,13 @@ public abstract class InputPayMana extends InputSyncronizedBase {
//if player is floating mana, show mana pool to make it easier to use that mana
wasFloatingMana = !player.getManaPool().isEmpty();
zoneToRestore = wasFloatingMana ? MatchUtil.getController().showManaPool(getController().getPlayerView(player)) : null;
zoneToRestore = wasFloatingMana ? MatchUtil.getController().showManaPool(PlayerView.get(player)) : null;
}
@Override
protected void onStop() {
if (wasFloatingMana) { //hide mana pool if it was shown due to floating mana
MatchUtil.getController().hideManaPool(getController().getPlayerView(player), zoneToRestore);
MatchUtil.getController().hideManaPool(PlayerView.get(player), zoneToRestore);
}
}

View File

@@ -3,9 +3,8 @@ package forge.match.input;
import forge.control.FControlGamePlayback;
import forge.game.Game;
import forge.game.phase.PhaseHandler;
import forge.game.player.PlayerView;
import forge.match.MatchUtil;
import forge.view.LocalGameView;
import forge.view.PlayerView;
public class InputPlaybackControl extends InputSyncronizedBase implements InputSynchronized {
private static final long serialVersionUID = 7979208993306642072L;
@@ -23,18 +22,11 @@ public class InputPlaybackControl extends InputSyncronizedBase implements InputS
setPause(false);
}
@Override
public LocalGameView getGameView() {
return MatchUtil.getGameView();
}
@Override
public PlayerView getOwner() {
return getGameView().getLocalPlayerView();
return MatchUtil.getHumanController().getLocalPlayerView();
}
/* (non-Javadoc)
* @see forge.gui.input.InputBase#showMessage()
*/
@Override
protected void showMessage() {
setPause(false);

View File

@@ -23,13 +23,12 @@ import java.util.concurrent.atomic.AtomicReference;
import forge.FThreads;
import forge.game.card.Card;
import forge.game.card.CardView;
import forge.game.player.Player;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbility;
import forge.player.PlayerControllerHuman;
import forge.util.ITriggerEvent;
import forge.view.CardView;
import forge.view.LocalGameView;
import forge.view.PlayerView;
import forge.view.SpellAbilityView;
/**
* <p>
@@ -43,17 +42,17 @@ public class InputProxy implements Observer {
/** The input. */
private AtomicReference<Input> input = new AtomicReference<Input>();
private final LocalGameView gameView;
private final PlayerControllerHuman controller;
// private static final boolean DEBUG_INPUT = true; // false;
public InputProxy(final LocalGameView gameView0) {
gameView = gameView0;
public InputProxy(final PlayerControllerHuman controller0) {
controller = controller0;
}
@Override
public final void update(final Observable observable, final Object obj) {
final Input nextInput = gameView.getInputQueue().getActualInput(gameView);
final Input nextInput = controller.getInputQueue().getActualInput(controller);
/* if(DEBUG_INPUT)
System.out.printf("%s ... \t%s on %s, \tstack = %s%n",
FThreads.debugGetStackTraceItem(6, true), nextInput == null ? "null" : nextInput.getClass().getSimpleName(),
@@ -64,7 +63,7 @@ public class InputProxy implements Observer {
@Override
public void run() {
Input current = getInput();
gameView.getInputQueue().syncPoint();
controller.getInputQueue().syncPoint();
//System.out.printf("\t%s > showMessage @ %s/%s during %s%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), current.getClass().getSimpleName(), game.getPhaseHandler().debugPrintState());
current.showMessageInitial();
}
@@ -99,7 +98,7 @@ public class InputProxy implements Observer {
public final void selectPlayer(final PlayerView playerView, final ITriggerEvent triggerEvent) {
final Input inp = getInput();
if (inp != null) {
final Player player = gameView.getPlayer(playerView);
final Player player = Player.get(playerView);
if (player != null) {
inp.selectPlayer(player, triggerEvent);
}
@@ -109,7 +108,7 @@ public class InputProxy implements Observer {
public final boolean selectCard(final CardView cardView, final ITriggerEvent triggerEvent) {
final Input inp = getInput();
if (inp != null) {
final Card card = gameView.getCard(cardView);
final Card card = Card.get(cardView);
if (card != null) {
return inp.selectCard(card, triggerEvent);
}
@@ -117,10 +116,9 @@ public class InputProxy implements Observer {
return false;
}
public final void selectAbility(final SpellAbilityView ab) {
public final void selectAbility(final SpellAbility sa) {
final Input inp = getInput();
if (inp != null) {
final SpellAbility sa = gameView.getSpellAbility(ab);
if (sa != null) {
inp.selectAbility(sa);
}

View File

@@ -22,8 +22,9 @@ import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import forge.game.Game;
import forge.game.player.Player;
import forge.match.MatchUtil;
import forge.view.IGameView;
import forge.player.PlayerControllerHuman;
/**
* <p>
@@ -60,16 +61,9 @@ public class InputQueue extends Observable {
updateObservers();
}
/**
* <p>
* updateInput.
* </p>
*
* @return a {@link forge.gui.input.InputBase} object.
*/
public final Input getActualInput(final IGameView gameView) {
public final Input getActualInput(final PlayerControllerHuman controller) {
Input topMost = inputStack.peek(); // incoming input to Control
if (topMost != null && !gameView.isGameOver()) {
if (topMost != null && !controller.getGame().isGameOver()) {
return topMost;
}
return inputLock;
@@ -82,7 +76,7 @@ public class InputQueue extends Observable {
public void setInput(final InputSynchronized input) {
if (MatchUtil.getHumanCount() > 1) { //update current player if needed
MatchUtil.setCurrentPlayer(MatchUtil.players.getKey(input.getOwner().getId()));
MatchUtil.setCurrentPlayer(Player.get(input.getOwner()));
}
inputStack.push(input);
InputBase.waitForOtherPlayer();
@@ -96,9 +90,6 @@ public class InputQueue extends Observable {
}
}
/**
* TODO: Write javadoc for this method.
*/
public void onGameOver(boolean releaseAllInputs) {
for (InputSynchronized inp : inputStack) {
inp.relaseLatchWhenGameIsOver();
@@ -107,4 +98,4 @@ public class InputQueue extends Observable {
}
}
}
} // InputControl
}

View File

@@ -6,6 +6,7 @@ import com.google.common.collect.Iterables;
import forge.game.GameEntity;
import forge.game.card.Card;
import forge.game.card.CardView;
import forge.match.MatchUtil;
import forge.player.PlayerControllerHuman;
@@ -75,14 +76,14 @@ public abstract class InputSelectManyBase<T extends GameEntity> extends InputSyn
protected void onSelectStateChanged(final GameEntity c, final boolean newState) {
if (c instanceof Card) {
MatchUtil.setUsedToPay(getController().getCardView((Card) c), newState); // UI supports card highlighting though this abstraction-breaking mechanism
MatchUtil.setUsedToPay(CardView.get((Card) c), newState); // UI supports card highlighting though this abstraction-breaking mechanism
}
}
private void resetUsedToPay() {
for (final GameEntity c : getSelected()) {
if (c instanceof Card) {
MatchUtil.setUsedToPay(getController().getCardView((Card) c), false);
MatchUtil.setUsedToPay(CardView.get((Card) c), false);
}
}
}

View File

@@ -10,6 +10,7 @@ import forge.game.GameEntity;
import forge.game.GameObject;
import forge.game.ability.ApiType;
import forge.game.card.Card;
import forge.game.card.CardView;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.TargetRestrictions;
@@ -229,7 +230,7 @@ public final class InputSelectTargets extends InputSyncronizedBase {
private void addTarget(final GameEntity ge) {
sa.getTargets().add(ge);
if (ge instanceof Card) {
MatchUtil.setUsedToPay(getController().getCardView((Card) ge), true);
MatchUtil.setUsedToPay(CardView.get((Card) ge), true);
lastTarget = (Card) ge;
}
final Integer val = targetDepth.get(ge);
@@ -246,7 +247,7 @@ public final class InputSelectTargets extends InputSyncronizedBase {
private void done() {
for (final GameEntity c : targetDepth.keySet()) {
if (c instanceof Card) {
MatchUtil.setUsedToPay(getController().getCardView((Card) c), false);
MatchUtil.setUsedToPay(CardView.get((Card) c), false);
}
}

View File

@@ -30,7 +30,7 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn
}
public void showAndWait() {
getGameView().getInputQueue().setInput(this);
getController().getInputQueue().setInput(this);
awaitLatchRelease();
}
@@ -46,7 +46,7 @@ public abstract class InputSyncronizedBase extends InputBase implements InputSyn
});
// thread irrelevant
getGameView().getInputQueue().removeInput(InputSyncronizedBase.this);
getController().getInputQueue().removeInput(InputSyncronizedBase.this);
cdlDone.countDown();
}

View File

@@ -12,6 +12,7 @@ import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.card.CardPredicates;
import forge.game.card.CardPredicates.Presets;
import forge.game.card.CardView;
import forge.game.card.CounterType;
import forge.game.cost.*;
import forge.game.player.Player;
@@ -25,14 +26,11 @@ import forge.util.ITriggerEvent;
import forge.util.Lang;
import forge.util.gui.SGuiChoose;
import forge.util.gui.SGuiDialog;
import forge.view.CardView;
import forge.view.PlayerView;
import java.util.*;
import java.util.Map.Entry;
public class HumanCostDecision extends CostDecisionMakerBase {
private final PlayerControllerHuman controller;
private final SpellAbility ability;
private final Card source;
@@ -68,7 +66,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
@Override
public PaymentDecision visit(CostChooseCreatureType cost) {
String choice = controller.chooseSomeType("Creature", ability, new ArrayList<String>(CardType.getCreatureTypes()), new ArrayList<String>(), true);
if( null == choice )
if (null == choice)
return null;
return PaymentDecision.type(choice);
}
@@ -294,9 +292,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
if (nNeeded == 0) {
return PaymentDecision.number(0);
}
final PlayerView view = SGuiChoose.oneOrNone(String.format("Exile from whose %s?", cost.getFrom()),
controller.getPlayerViews(payableZone));
final Player p = controller.getPlayer(view);
final Player p = SGuiChoose.oneOrNone(String.format("Exile from whose %s?", cost.getFrom()), payableZone);
if (p == null) {
return null;
}
@@ -342,7 +338,8 @@ public class HumanCostDecision extends CostDecisionMakerBase {
// Generalize this
if (sVar.equals("XChoice")) {
c = chooseXValue(saList.size());
} else {
}
else {
c = AbilityUtils.calculateAmount(source, amount, ability);
}
}
@@ -378,33 +375,26 @@ public class HumanCostDecision extends CostDecisionMakerBase {
if (list.size() > nNeeded || !player.getController().confirmPayment(cost, "Exile " + Lang.nounWithAmount(nNeeded, "card") + " from the top of your library?")) {
return null;
}
return PaymentDecision.card(list);
}
private PaymentDecision exileFromMiscZone(CostExile cost, SpellAbility sa, int nNeeded, List<Card> typeList) {
if (typeList.size() < nNeeded)
return null;
if (typeList.size() < nNeeded) { return null; }
List<Card> exiled = new ArrayList<Card>();
for (int i = 0; i < nNeeded; i++) {
final CardView view = SGuiChoose.oneOrNone("Exile from " + cost.getFrom(), controller.getCardViews(typeList));
final Card c = controller.getCard(view);
final Card c = SGuiChoose.oneOrNone("Exile from " + cost.getFrom(), typeList);
if (c == null) { return null; }
if (c != null) {
typeList.remove(c);
exiled.add(c);
} else {
return null;
}
typeList.remove(c);
exiled.add(c);
}
return PaymentDecision.card(exiled);
}
private PaymentDecision exileFromTopGraveType(SpellAbility sa, int nNeeded, List<Card> typeList) {
if (typeList.size() < nNeeded)
return null;
if (typeList.size() < nNeeded) { return null; }
Collections.reverse(typeList);
return PaymentDecision.card(Lists.newArrayList(Iterables.limit(typeList, nNeeded)));
}
@@ -420,12 +410,11 @@ public class HumanCostDecision extends CostDecisionMakerBase {
List<Card> list = activator.getGame().getCardsIn(ZoneType.Exile);
list = CardLists.getValidCards(list, cost.getType().split(";"), activator, source);
if (list.size() < c)
if (list.size() < c) {
return null;
final List<CardView> choice = SGuiChoose.many("Choose an exiled card to put into graveyard", "To graveyard", c,
controller.getCardViews(list), controller.getCardView(source));
return PaymentDecision.card(controller.getCards(choice));
}
final List<Card> choice = SGuiChoose.many("Choose an exiled card to put into graveyard", "To graveyard", c, list, CardView.get(source));
return PaymentDecision.card(choice);
}
@Override
@@ -496,12 +485,11 @@ public class HumanCostDecision extends CostDecisionMakerBase {
final StringBuilder sb = new StringBuilder();
sb.append(source.getName()).append(" - Choose an opponent to gain ").append(c).append(" life:");
final PlayerView chosenToGainView = SGuiChoose.oneOrNone(sb.toString(), controller.getPlayerViews(oppsThatCanGainLife));
final Player chosenToGain = controller.getPlayer(chosenToGainView);
if (null == chosenToGain)
final Player chosenToGain = SGuiChoose.oneOrNone(sb.toString(), oppsThatCanGainLife);
if (chosenToGain == null) {
return null;
else
return PaymentDecision.players(Lists.newArrayList(chosenToGain));
}
return PaymentDecision.players(Lists.newArrayList(chosenToGain));
}
@Override
@@ -579,7 +567,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
if (cost.from == ZoneType.Hand) {
InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, list);
inp.setMessage("Put %d card(s) from your " + cost.from );
inp.setMessage("Put %d card(s) from your " + cost.from);
inp.setCancelAllowed(true);
inp.showAndWait();
return inp.hasCancelled() ? null : PaymentDecision.card(inp.getSelected());
@@ -602,23 +590,18 @@ public class HumanCostDecision extends CostDecisionMakerBase {
}
}
private PaymentDecision putFromMiscZone(SpellAbility sa, int nNeeded, List<Card> typeList, ZoneType fromZone) {
if (typeList.size() < nNeeded) {
return null;
}
final List<CardView> viewList = controller.getCardViews(typeList);
List<Card> chosen = new ArrayList<Card>();
for (int i = 0; i < nNeeded; i++) {
final CardView view = SGuiChoose.oneOrNone("Put from " + fromZone + " to library", viewList);
final Card c = controller.getCard(view);
final Card c = SGuiChoose.oneOrNone("Put from " + fromZone + " to library", typeList);
if (c == null) {
return null;
}
viewList.remove(view);
typeList.remove(c);
chosen.add(c);
}
return PaymentDecision.card(chosen);
@@ -628,10 +611,8 @@ public class HumanCostDecision extends CostDecisionMakerBase {
if (nNeeded == 0) {
return PaymentDecision.number(0);
}
final List<PlayerView> players = controller.getPlayerViews(payableZone);
final PlayerView pView = SGuiChoose.oneOrNone(String.format("Put cards from whose %s?", fromZone), players);
final Player p = controller.getPlayer(pView);
final Player p = SGuiChoose.oneOrNone(String.format("Put cards from whose %s?", fromZone), payableZone);
if (p == null) {
return null;
}
@@ -641,17 +622,13 @@ public class HumanCostDecision extends CostDecisionMakerBase {
return null;
}
final List<CardView> viewList = controller.getCardViews(typeList);
List<Card> chosen = new ArrayList<Card>();
for (int i = 0; i < nNeeded; i++) {
final CardView view = SGuiChoose.oneOrNone("Put cards from " + fromZone + " to Library", viewList);
final Card c = controller.getCard(view);
final Card c = SGuiChoose.oneOrNone("Put cards from " + fromZone + " to Library", typeList);
if (c == null) {
return null;
}
viewList.remove(view);
typeList.remove(c);
chosen.add(c);
}
return PaymentDecision.card(chosen);
@@ -674,7 +651,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
inp.setCancelAllowed(true);
inp.showAndWait();
if(inp.hasCancelled())
if (inp.hasCancelled())
return null;
return PaymentDecision.card(inp.getSelected());
@@ -698,7 +675,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
if (cost.payCostFromSource()) {
final Card card = ability.getHostCard();
if (card.getController() == player && card.isInPlay()) {
final CardView view = controller.getCardView(card);
final CardView view = CardView.get(card);
return player.getController().confirmPayment(cost, "Return " + view + " to hand?") ? PaymentDecision.card(card) : null;
}
}
@@ -708,25 +685,24 @@ public class HumanCostDecision extends CostDecisionMakerBase {
InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, validCards);
inp.setMessage("Return %d " + cost.getType() + " " + cost.getType() + " card(s) to hand");
inp.showAndWait();
if (inp.hasCancelled())
if (inp.hasCancelled()) {
return null;
}
return PaymentDecision.card(inp.getSelected());
}
return null;
}
@Override
public PaymentDecision visit(CostReveal cost) {
final String amount = cost.getAmount();
if (cost.payCostFromSource())
if (cost.payCostFromSource()) {
return PaymentDecision.card(source);
if (cost.getType().equals("Hand"))
}
if (cost.getType().equals("Hand")) {
return PaymentDecision.card(player.getCardsIn(ZoneType.Hand));
}
InputSelectCardsFromList inp = null;
if (cost.getType().equals("SameColor")) {
Integer num = cost.convertAmount();
@@ -743,9 +719,9 @@ public class HumanCostDecision extends CostDecisionMakerBase {
return false;
}
});
if (num == 0)
if (num == 0) {
return PaymentDecision.number(0);
}
inp = new InputSelectCardsFromList(controller, num, handList) {
private static final long serialVersionUID = 8338626212893374798L;
@@ -758,9 +734,9 @@ public class HumanCostDecision extends CostDecisionMakerBase {
return super.onCardSelected(c, triggerEvent);
}
};
inp.setMessage("Select " + Lang.nounWithAmount(num, "card" ) + " of same color to reveal.");
} else {
inp.setMessage("Select " + Lang.nounWithAmount(num, "card") + " of same color to reveal.");
}
else {
Integer num = cost.convertAmount();
List<Card> handList = player.getCardsIn(ZoneType.Hand);
@@ -774,7 +750,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
num = AbilityUtils.calculateAmount(source, amount, ability);
}
}
if ( num == 0 )
if (num == 0)
return PaymentDecision.number(0);;
inp = new InputSelectCardsFromList(controller, num, num, handList);
@@ -873,7 +849,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
private int getDistibutedCounters() {
int sum = 0;
for(Entry<Card, Integer> kv : cardsChosen.entrySet()) {
for (Entry<Card, Integer> kv : cardsChosen.entrySet()) {
sum += kv.getValue().intValue();
}
return sum;
@@ -911,13 +887,13 @@ public class HumanCostDecision extends CostDecisionMakerBase {
if (cost.payCostFromSource()) {
int maxCounters = source.getCounters(cost.counter);
if (amount.equals("All")) {
final CardView view = controller.getCardView(ability.getHostCard());
final CardView view = CardView.get(ability.getHostCard());
if (!SGuiDialog.confirm(view, "Remove all counters?")) {
return null;
}
cntRemoved = maxCounters;
}
else if ( c == null && "XChoice".equals(sVarAmount)) {
else if (c == null && "XChoice".equals(sVarAmount)) {
cntRemoved = chooseXValue(maxCounters);
}
@@ -953,7 +929,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
for (Card crd : inp.getSelected()) {
int removed = inp.getTimesSelected(crd);
// sum += removed;
if(removed < 2) continue;
if (removed < 2) continue;
int oldVal = crd.getCounters().get(cost.counter).intValue();
crd.getCounters().put(cost.counter, Integer.valueOf(oldVal - removed + 1));
}
@@ -964,12 +940,12 @@ public class HumanCostDecision extends CostDecisionMakerBase {
List<CardView> suspended = Lists.newArrayList();
for (final Card crd : validCards) {
if (crd.getCounters(cost.counter) > 0) {
suspended.add(controller.getCardView(crd));
suspended.add(CardView.get(crd));
}
}
final CardView view = SGuiChoose.oneOrNone("Remove counter(s) from a card in " + cost.zone, suspended);
final Card card = controller.getCard(view);
final Card card = Card.get(view);
return null == card ? null : PaymentDecision.card(card, c);
}
@@ -1014,7 +990,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
inp.setMessage("Select a " + cost.getDescriptiveType() + " to sacrifice (%d left)");
inp.setCancelAllowed(true);
inp.showAndWait();
if ( inp.hasCancelled() )
if (inp.hasCancelled())
return null;
return PaymentDecision.card(inp.getSelected());
@@ -1115,7 +1091,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, typeList);
inp.setMessage("Select a " + cost.getDescriptiveType() + " to tap (%d left)");
inp.showAndWait();
if ( inp.hasCancelled() )
if (inp.hasCancelled())
return null;
return PaymentDecision.card(inp.getSelected());
@@ -1143,7 +1119,7 @@ public class HumanCostDecision extends CostDecisionMakerBase {
InputSelectCardsFromList inp = new InputSelectCardsFromList(controller, c, c, typeList);
inp.setMessage("Select a " + cost.getDescriptiveType() + " to untap (%d left)");
inp.showAndWait();
if( inp.hasCancelled() || inp.getSelected().size() != c )
if (inp.hasCancelled() || inp.getSelected().size() != c)
return null;
return PaymentDecision.card(inp.getSelected());
}

View File

@@ -23,7 +23,6 @@ public class LobbyPlayerHuman extends LobbyPlayer implements IGameEntitiesFactor
Player player = new Player(GuiDisplayUtil.personalizeHuman(getName()), game, id);
PlayerControllerHuman controller = new PlayerControllerHuman(game, player, this);
player.setFirstController(controller);
controller.getGameView().setLocalPlayer(player);
return player;
}

View File

@@ -30,6 +30,7 @@ import forge.game.GameEntity;
import forge.game.GameObject;
import forge.game.card.Card;
import forge.game.card.CardLists;
import forge.game.player.PlayerView;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.spellability.TargetRestrictions;
@@ -39,9 +40,6 @@ import forge.match.MatchUtil;
import forge.match.input.InputSelectTargets;
import forge.util.Aggregates;
import forge.util.gui.SGuiChoose;
import forge.view.CardView;
import forge.view.PlayerView;
import forge.view.StackItemView;
/**
* <p>
@@ -66,13 +64,6 @@ public class TargetSelection {
private boolean bTargetingDone = false;
/**
* <p>
* resetTargets.
* </p>
*/
public final boolean chooseTargets(Integer numTargets) {
final TargetRestrictions tgt = getTgt();
final boolean canTarget = tgt != null && tgt.doesTarget();
@@ -140,7 +131,7 @@ public class TargetSelection {
}
final Map<PlayerView, Object> playersWithValidTargets = Maps.newHashMap();
for (Card card : validTargets) {
playersWithValidTargets.put(controller.getPlayerView(card.getController()), null);
playersWithValidTargets.put(PlayerView.get(card.getController()), null);
}
if (MatchUtil.getController().openZones(zone, playersWithValidTargets)) {
InputSelectTargets inp = new InputSelectTargets(controller, validTargets, ability, mandatory);
@@ -162,13 +153,6 @@ public class TargetSelection {
// parameters for target selection.
// however, due to the changes necessary for SA_Requirements this is much
// different than the original
/**
* <p>
* chooseValidInput.
* </p>
* @return
*/
private final List<Card> getValidCardsToTarget() {
final TargetRestrictions tgt = this.getTgt();
final Game game = ability.getActivatingPlayer().getGame();
@@ -217,37 +201,24 @@ public class TargetSelection {
return choices;
}
/**
* <p>
* chooseCardFromList.
* </p>
*
* @param choices
* a {@link forge.CardList} object.
* @param targeted
* a boolean.
* @param mandatory
* a boolean.
*/
private final boolean chooseCardFromList(final List<Card> choices, final boolean targeted, final boolean mandatory) {
// Send in a list of valid cards, and popup a choice box to target
final Game game = ability.getActivatingPlayer().getGame();
final List<CardView> crdsBattle = Lists.newArrayList();
final List<CardView> crdsExile = Lists.newArrayList();
final List<CardView> crdsGrave = Lists.newArrayList();
final List<CardView> crdsLibrary = Lists.newArrayList();
final List<CardView> crdsStack = Lists.newArrayList();
final List<CardView> crdsAnte = Lists.newArrayList();
final List<Card> crdsBattle = Lists.newArrayList();
final List<Card> crdsExile = Lists.newArrayList();
final List<Card> crdsGrave = Lists.newArrayList();
final List<Card> crdsLibrary = Lists.newArrayList();
final List<Card> crdsStack = Lists.newArrayList();
final List<Card> crdsAnte = Lists.newArrayList();
for (final Card inZone : choices) {
final CardView view = controller.getCardView(inZone);
Zone zz = game.getZoneOf(inZone);
if (zz.is(ZoneType.Battlefield)) crdsBattle.add(view);
else if (zz.is(ZoneType.Exile)) crdsExile.add(view);
else if (zz.is(ZoneType.Graveyard)) crdsGrave.add(view);
else if (zz.is(ZoneType.Library)) crdsLibrary.add(view);
else if (zz.is(ZoneType.Stack)) crdsStack.add(view);
else if (zz.is(ZoneType.Ante)) crdsAnte.add(view);
if (zz.is(ZoneType.Battlefield)) crdsBattle.add(inZone);
else if (zz.is(ZoneType.Exile)) crdsExile.add(inZone);
else if (zz.is(ZoneType.Graveyard)) crdsGrave.add(inZone);
else if (zz.is(ZoneType.Library)) crdsLibrary.add(inZone);
else if (zz.is(ZoneType.Stack)) crdsStack.add(inZone);
else if (zz.is(ZoneType.Ante)) crdsAnte.add(inZone);
}
List<Object> choicesFiltered = new ArrayList<Object>();
if (!crdsBattle.isEmpty()) {
@@ -284,7 +255,8 @@ public class TargetSelection {
Object chosen = null;
if (!choices.isEmpty() && mandatory) {
chosen = SGuiChoose.one(getTgt().getVTSelection(), choicesFiltered);
} else {
}
else {
chosen = SGuiChoose.oneOrNone(getTgt().getVTSelection(), choicesFiltered);
}
if (chosen == null) {
@@ -295,21 +267,12 @@ public class TargetSelection {
return true;
}
if (chosen instanceof CardView) {
final Card chosenCard = controller.getCard((CardView) chosen);
ability.getTargets().add(chosenCard);
if (chosen instanceof Card) {
ability.getTargets().add((Card) chosen);
}
return true;
}
/**
* <p>
* chooseCardFromStack.
* </p>
*
* @param mandatory
* a boolean.
*/
private final boolean chooseCardFromStack(final boolean mandatory) {
final TargetRestrictions tgt = this.getTgt();
final String message = tgt.getVTSelection();
@@ -322,8 +285,9 @@ public class TargetSelection {
if (ability.equals(abilityOnStack)) {
// By peeking at stack item, target is set to its SI state. So set it back before adding targets
ability.resetTargets();
} else if (ability.canTargetSpellAbility(abilityOnStack)) {
selectOptions.add(controller.getStackItemView(si));
}
else if (ability.canTargetSpellAbility(abilityOnStack)) {
selectOptions.add(si);
}
}
@@ -340,15 +304,18 @@ public class TargetSelection {
if (selectOptions.isEmpty()) {
// Not enough targets, cancel targeting
return false;
} else {
}
else {
final Object madeChoice = SGuiChoose.oneOrNone(message, selectOptions);
if (madeChoice == null) {
return false;
}
if (madeChoice instanceof StackItemView) {
ability.getTargets().add(controller.getStackItem((StackItemView)madeChoice).getSpellAbility(true));
} else // 'FINISH TARGETING' chosen
if (madeChoice instanceof SpellAbilityStackInstance) {
ability.getTargets().add(((SpellAbilityStackInstance)madeChoice).getSpellAbility(true));
}
else {// 'FINISH TARGETING' chosen
bTargetingDone = true;
}
}
}
return true;

View File

@@ -8,9 +8,11 @@ import forge.card.UnOpenedProduct;
import forge.game.GameEndReason;
import forge.game.GameFormat;
import forge.game.GameOutcome;
import forge.game.GameView;
import forge.game.player.GameLossReason;
import forge.game.player.PlayerOutcome;
import forge.game.player.PlayerStatistics;
import forge.game.player.PlayerView;
import forge.interfaces.IButton;
import forge.interfaces.IWinLoseView;
import forge.item.*;
@@ -23,8 +25,6 @@ import forge.quest.data.QuestPreferences.DifficultyPrefs;
import forge.quest.data.QuestPreferences.QPref;
import forge.util.MyRandom;
import forge.util.gui.SGuiChoose;
import forge.view.IGameView;
import forge.view.PlayerView;
import org.apache.commons.lang3.StringUtils;
@@ -35,13 +35,13 @@ import java.util.List;
import java.util.Map.Entry;
public abstract class QuestWinLoseController {
private final IGameView lastGame;
private final GameView lastGame;
private final transient boolean wonMatch;
private final transient boolean isAnte;
private final transient QuestController qData;
private final transient QuestEvent qEvent;
public QuestWinLoseController(final IGameView game0) {
public QuestWinLoseController(final GameView game0) {
lastGame = game0;
qData = FModel.getQuest();
qEvent = qData.getCurrentEvent();
@@ -88,7 +88,7 @@ public abstract class QuestWinLoseController {
public void run() {
if (isAnte) {
// Won/lost cards should already be calculated (even in a draw)
GameOutcome.AnteResult anteResult = lastGame.getAnteResult();
GameOutcome.AnteResult anteResult = lastGame.getAnteResult(questPlayer);
if (anteResult != null) {
if (anteResult.wonCards != null) {
qc.getCards().addAllCards(anteResult.wonCards);

View File

@@ -14,7 +14,7 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.GuiBase;
import forge.view.CardView;
import forge.game.card.CardView;
public class SGuiChoose {
/**

View File

@@ -2,7 +2,7 @@ package forge.util.gui;
import org.apache.commons.lang3.StringUtils;
import forge.view.CardView;
import forge.game.card.CardView;
/**
* Holds player interactions using standard windows

View File

@@ -2,7 +2,7 @@ package forge.util.gui;
import forge.GuiBase;
import forge.assets.FSkinProp;
import forge.view.CardView;
import forge.game.card.CardView;
public class SOptionPane {
public static final FSkinProp QUESTION_ICON = FSkinProp.ICO_QUESTION;

View File

@@ -1,173 +0,0 @@
package forge.view;
import java.util.Collection;
import java.util.Map;
import com.google.common.collect.Collections2;
import com.google.common.collect.Maps;
import forge.game.IIdentifiable;
/**
* Implementation of a two-way cache, containing bidirectional mappings from
* keys of type {@code K} to values of type {@code V}.
*
* Keys and values are checked for equality using the
* {@link Object#equals(Object)} method.
*
* @author elcnesh
*
* @param <K>
* the type of this Cache's keys.
* @param <V>
* the type of this Cache's values.
*/
public class Cache<K extends IIdentifiable, V extends IIdentifiable> {
private final Map<Integer, V> cache;
private final Map<Integer, K> inverseCache;
/**
* Create a new, empty Cache instance.
*/
public Cache() {
this.cache = Maps.newTreeMap();
this.inverseCache = Maps.newTreeMap();
}
/**
* @param key
* a key.
* @return {@code true} if and only if this Cache contains the specified
* key.
*/
public boolean containsKey(final int keyId) {
return cache.containsKey(keyId);
}
/**
* Get the value associated to a key.
*
* @param key
* a key.
* @return the value associated to key, or {@code null} if no such value
* exists.
*/
public V get(final int keyId) {
return cache.get(keyId);
}
/**
* Get the key associated to a value.
*
* @param value
* a value.
* @return the key associated to value, or {@code null} if no such key
* exists.
*/
public K getKey(final int valueId) {
return inverseCache.get(valueId);
}
/**
* Get a value as it is present in this Cache, compared using the equals
* method.
*
* @param value
* @return a value equal to value, if such a value is present in the Cache;
* {@code null} otherwise.
*/
public synchronized V getCurrentValue(final V value) {
for (final V currentValue : cache.values()) {
if (currentValue.equals(value)) {
return currentValue;
}
}
return null;
}
/**
* Add a mapping to this Cache.
*
* If either argument is {@code null}, this method silently returns.
* Otherwise, any existing mapping from the provided key to the provided
* value is removed, as well as its inverse. After that, the provided
* mapping and its inverse are added to this Cache.
*
* @param key
* the key of the new mapping.
* @param value
* the value to map to.
* @see java.util.Map#put(java.lang.Object, java.lang.Object)
*/
public void put(final K key, final V value) {
if (key == null || value == null) {
return;
}
synchronized (this) {
final int keyId = key.getId(), valueId = value.getId();
// remove value mapping if it exists already
if (inverseCache.containsKey(valueId)) {
cache.values().remove(value);
inverseCache.remove(valueId);
}
// remove key mapping if it exists already
if (cache.containsKey(keyId)) {
inverseCache.values().remove(key);
cache.remove(keyId);
}
// put the new values
cache.put(keyId, value);
inverseCache.put(valueId, key);
}
}
/**
* Update the key of a particular entry. If the supplied key is {@code null}
* or if the Cache didn't already contain a mapping for the supplied id,
* this method silently returns.
*
* @param valueId
* the id of the value to which the key is associated.
* @param key
* the new key.
*/
public void updateKey(final int valueId, final K key) {
if (key == null || !inverseCache.containsKey(valueId)) {
return;
}
synchronized (this) {
inverseCache.put(valueId, key);
}
}
public Iterable<K> getKeys() {
return inverseCache.values();
}
public Iterable<V> getValues() {
return cache.values();
}
/**
* Clear all the mappings in this Cache, except for any key that exists in
* the argument.
*
* @param keys
* the keys to retain.
*/
public synchronized void retainAllKeys(final Collection<K> keys) {
cache.keySet().retainAll(Collections2.transform(keys, IIdentifiable.FN_GET_ID));
inverseCache.values().retainAll(keys);
}
public void clear() {
cache.clear();
inverseCache.clear();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,131 +0,0 @@
package forge.view;
import java.util.List;
import java.util.Map;
import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* Representation of a {@link forge.game.combat.Combat}, containing only the
* information relevant to a user interface.
*
* Conversion from and to Combat happens through {@link LocalGameView}.
*
* @author elcnesh
*/
public class CombatView {
private Map<CardView, GameEntityView> attackersWithDefenders = Maps.newHashMap();
private Map<CardView, Iterable<CardView>> attackersWithBlockers = Maps.newHashMap();
private Map<Iterable<CardView>, GameEntityView> bandsWithDefenders = Maps.newHashMap();
private Map<Iterable<CardView>, Iterable<CardView>> bandsWithBlockers = Maps.newHashMap();
private Map<CardView, Iterable<CardView>> attackersWithPlannedBlockers = Maps.newHashMap();
private Map<Iterable<CardView>, Iterable<CardView>> bandsWithPlannedBlockers = Maps.newHashMap();
public CombatView() {
}
public int getNumAttackers() {
return attackersWithDefenders.size();
}
public boolean isAttacking(final CardView card) {
return attackersWithDefenders.containsKey(card);
}
public Iterable<CardView> getAttackers() {
return attackersWithDefenders.keySet();
}
public Iterable<GameEntityView> getDefenders() {
return Sets.newHashSet(attackersWithDefenders.values());
}
public GameEntityView getDefender(final CardView attacker) {
return attackersWithDefenders.get(attacker);
}
public boolean isBlocking(final CardView card) {
for (final Iterable<CardView> blockers : attackersWithBlockers.values()) {
if (blockers == null) {
continue;
}
if (Iterables.contains(blockers, card)) {
return true;
}
}
return false;
}
/**
* @param attacker
* @return the blockers associated with an attacker, or {@code null} if the
* attacker is unblocked.
*/
public Iterable<CardView> getBlockers(final CardView attacker) {
return attackersWithBlockers.get(attacker);
}
/**
* @param attacker
* @return the blockers associated with an attacker, or {@code null} if the
* attacker is unblocked (planning stage, for targeting overlay).
*/
public Iterable<CardView> getPlannedBlockers(final CardView attacker) {
return attackersWithPlannedBlockers.get(attacker);
}
/**
* Get an {@link Iterable} of the blockers of the specified band, or
* {@code null} if that band is unblocked.
*
* @param attackingBand
* an {@link Iterable} representing an attacking band.
* @return an {@link Iterable} of {@link CardView} objects, or {@code null}.
*/
public Iterable<CardView> getBlockers(final Iterable<CardView> attackingBand) {
return bandsWithBlockers.get(attackingBand);
}
/**
* Get an {@link Iterable} of the blockers of the specified band, or
* {@code null} if that band is unblocked (planning stage, for targeting overlay).
*
* @param attackingBand
* an {@link Iterable} representing an attacking band.
* @return an {@link Iterable} of {@link CardView} objects, or {@code null}.
*/
public Iterable<CardView> getPlannedBlockers(final Iterable<CardView> attackingBand) {
return bandsWithPlannedBlockers.get(attackingBand);
}
public Iterable<CardView> getAttackersOf(final GameEntityView defender) {
return Maps.filterValues(attackersWithDefenders, Predicates.equalTo(defender)).keySet();
}
public Iterable<Iterable<CardView>> getAttackingBandsOf(final GameEntityView defender) {
return Maps.filterValues(bandsWithDefenders, Predicates.equalTo(defender)).keySet();
}
public void addAttackingBand(final Iterable<CardView> attackingBand, final GameEntityView defender, final Iterable<CardView> blockers, final Iterable<CardView> plannedBlockers) {
final List<CardView> attackingBandCopy = Lists.newArrayList(attackingBand),
blockersCopy, plannedBlockersCopy;
blockersCopy = blockers == null ? null : Lists.newArrayList(blockers);
plannedBlockersCopy = plannedBlockers == null ? null : Lists.newArrayList(plannedBlockers);
for (final CardView attacker : attackingBandCopy) {
this.attackersWithDefenders.put(attacker, defender);
this.attackersWithBlockers.put(attacker, blockersCopy);
this.attackersWithPlannedBlockers.put(attacker, plannedBlockersCopy);
}
this.bandsWithDefenders.put(attackingBandCopy, defender);
this.bandsWithBlockers.put(attackingBandCopy, blockersCopy);
this.bandsWithPlannedBlockers.put(attackingBandCopy, plannedBlockersCopy);
}
}

View File

@@ -1,14 +0,0 @@
package forge.view;
import forge.game.IIdentifiable;
/**
* Representation of a {@link forge.game.GameEntity}. Contains no methods, but
* {@link toString} may be assumed to be overridden in subclasses to provide a
* user-friendly string representation of the object.
*
* @author elcnesh
*/
public abstract class GameEntityView implements IIdentifiable {
}

View File

@@ -1,246 +0,0 @@
package forge.view;
import java.util.List;
import java.util.Observer;
import forge.LobbyPlayer;
import forge.card.MagicColor;
import forge.deck.Deck;
import forge.game.GameLog;
import forge.game.GameLogEntry;
import forge.game.GameLogEntryType;
import forge.game.GameOutcome;
import forge.game.GameType;
import forge.game.phase.PhaseType;
import forge.match.input.Input;
import forge.match.input.InputConfirm;
import forge.player.PlayerControllerHuman.DevModeCheats;
import forge.util.ITriggerEvent;
/**
* Interface providing access to a game from a client. The access is assumed to
* be based on a single player.
*
* @author elcnesh
*/
public interface IGameView {
// Game-related methods
public abstract boolean isCommander();
public abstract GameType getGameType();
public abstract int getTurnNumber();
public abstract boolean isCommandZoneNeeded();
public abstract boolean isWinner(LobbyPlayer p);
public abstract LobbyPlayer getWinningPlayer();
public abstract int getWinningTeam();
// Match-related methods
public abstract boolean isFirstGameInMatch();
public abstract boolean isMatchOver();
public abstract int getNumGamesInMatch();
public abstract int getNumPlayedGamesInMatch();
public abstract Iterable<GameOutcome> getOutcomesOfMatch();
public abstract boolean isMatchWonBy(LobbyPlayer p);
public abstract int getGamesWonBy(LobbyPlayer p);
public abstract GameOutcome.AnteResult getAnteResult();
public abstract Deck getDeck(LobbyPlayer player);
public abstract boolean isGameOver();
public abstract void updateAchievements();
public abstract int getPoisonCountersToLose();
public abstract void subscribeToEvents(Object subscriber);
/**
* Get the game's current combat.
*
* @return a representation of the combat, or {@code null} if there is
* currently no ongoing combat.
*/
public abstract CombatView getCombat();
/**
* Add an observer to the game log.
*
* @param o
* the {@link Observer} to be sent log updates.
* @see GameLog
*/
public abstract void addLogObserver(Observer o);
/**
* Get all log entries up to a certain level.
*
* @param maxLogLevel
* the maximum {@link GameLogEntryType} of log entries to return.
* @return a list of {@link GameLogEntry}.
* @see GameLog
* @see GameLogEntry
* @see GameLogEntryType
*/
public abstract List<GameLogEntry> getLogEntries(GameLogEntryType maxLogLevel);
/**
* Get all log entries of a certain level.
*
* @param logLevel
* the {@link GameLogEntryType} of log entries to return.
* @return a list of {@link GameLogEntry}, each of which is of type
* logLevel.
* @see GameLog
* @see GameLogEntry
* @see GameLogEntryType
*/
public abstract List<GameLogEntry> getLogEntriesExact(GameLogEntryType logLevel);
// Input controls
/**
* @return {@code true} if and only if the last action performed by this
* player can be undone.
*/
public abstract boolean canUndoLastAction();
/**
* Try to undo the last action performed by this player.
*
* @return {@code true} if and only if the action was successfully reverted.
* @see IGameView#canUndoLastAction()
*/
public abstract boolean tryUndoLastAction();
/**
* Have this player perform the action currently associated with pressing
* the "OK" button.
*/
public abstract void selectButtonOk();
/**
* Have this player perform the action currently associated with pressing
* the "Cancel" button.
*/
public abstract void selectButtonCancel();
/**
* Have this player press the "OK" button if and only if the top
* {@link Input} is an instance of {@link InputConfirm}.
*/
public abstract void confirm();
/**
* Have this player pass priority.
* @return whether priority was successfully passed.
*/
public abstract boolean passPriority();
/**
* Have this player silently pass priority until the end of the current
* turn, unless an event occurs.
*
* @return whether priority was successfully passed.
*/
public abstract boolean passPriorityUntilEndOfTurn();
/**
* If possible, have this player use one mana of the specified kind.
*
* @param mana
* the mana to spend.
* @see MagicColor
*/
public abstract void useMana(byte mana);
/**
* If possible, have this player select a player.
*
* @param player
* the player to select.
* @param triggerEvent
* the event used to select the player.
*/
public abstract void selectPlayer(PlayerView player, ITriggerEvent triggerEvent);
/**
* If possible, have this player select a card.
*
* @param card
* the card to select.
* @param triggerEvent
* the event used to select the card.
*/
public abstract boolean selectCard(CardView card, ITriggerEvent triggerEvent);
/**
* If possible, have this player select a spellability.
*
* @param sa
* the spellability to select.
* @param triggerEvent
* the event used to select the spellability.
*/
public abstract void selectAbility(SpellAbilityView sa);
/**
* If possible, have this player attack with as many creatures that can do
* so.
*/
public abstract void alphaStrike();
/**
* Ask for a list containing the players involved in this game.
*
* @return a list of players.
*/
public abstract List<PlayerView> getPlayers();
/**
* Get the player whose turn it currently is.
*
* @return the player whose turn it is, or {@code null} if it is no-one's
* turn (eg. because the current player has lost the game this
* turn).
*/
public abstract PlayerView getPlayerTurn();
/**
* @return the current phase the game is in.
*/
public abstract PhaseType getPhase();
/**
* @return a list of items currently on the stack.
*/
public abstract List<StackItemView> getStack();
/**
* @return the top item on the stack, or {@code null} if the stack is empty.
*/
public abstract StackItemView peekStack();
// Auto-yield related methods
public abstract Iterable<String> getAutoYields();
public abstract boolean shouldAutoYield(String key);
public abstract void setShouldAutoYield(String key, boolean autoYield);
public abstract boolean getDisableAutoYields();
public abstract void setDisableAutoYields(boolean b);
public abstract boolean shouldAlwaysAcceptTrigger(Integer trigger);
public abstract boolean shouldAlwaysDeclineTrigger(Integer trigger);
public abstract boolean shouldAlwaysAskTrigger(Integer trigger);
public abstract void setShouldAlwaysAcceptTrigger(Integer trigger);
public abstract void setShouldAlwaysDeclineTrigger(Integer trigger);
public abstract void setShouldAlwaysAskTrigger(Integer trigger);
/**
* Request cancellation of a previous request to pass priority
* automatically.
*/
public abstract void autoPassCancel();
public abstract boolean canPlayUnlimitedLands();
public abstract boolean canViewAllCards();
//method used to wrap all functions that cheat
public abstract DevModeCheats cheat();
}

View File

@@ -1,574 +0,0 @@
package forge.view;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Observer;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.LobbyPlayer;
import forge.card.MagicColor;
import forge.deck.Deck;
import forge.game.Game;
import forge.game.GameEntity;
import forge.game.GameLogEntry;
import forge.game.GameLogEntryType;
import forge.game.GameOutcome;
import forge.game.GameType;
import forge.game.card.Card;
import forge.game.card.CardFactoryUtil;
import forge.game.combat.AttackingBand;
import forge.game.combat.Combat;
import forge.game.phase.PhaseType;
import forge.game.player.Player;
import forge.game.player.RegisteredPlayer;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
import forge.game.zone.ZoneType;
import forge.match.MatchUtil;
import forge.match.input.InputProxy;
import forge.match.input.InputQueue;
public abstract class LocalGameView implements IGameView {
protected final Game game;
protected final InputQueue inputQueue;
protected final InputProxy inputProxy;
private PlayerView localPlayerView;
public LocalGameView(Game game0) {
game = game0;
inputProxy = new InputProxy(this);
inputQueue = new InputQueue(game, inputProxy);
}
public final Game getGame() {
return game;
}
public final InputQueue getInputQueue() {
return inputQueue;
}
public InputProxy getInputProxy() {
return inputProxy;
}
public PlayerView getLocalPlayerView() {
return localPlayerView;
}
public void setLocalPlayer(Player localPlayer) {
localPlayerView = getPlayerView(localPlayer, false);
}
/* (non-Javadoc)
* @see forge.view.IGameView#isCommander()
*/
@Override
public boolean isCommander() {
return game.getRules().hasAppliedVariant(GameType.Commander);
}
/* (non-Javadoc)
* @see forge.view.IGameView#getGameType()
*/
@Override
public GameType getGameType() {
return game.getMatch().getRules().getGameType();
}
@Override
public int getTurnNumber() {
return game.getPhaseHandler().getTurn();
}
@Override
public boolean isCommandZoneNeeded() {
return game.getMatch().getRules().getGameType().isCommandZoneNeeded();
}
@Override
public boolean isWinner(final LobbyPlayer p) {
return game.getOutcome() == null ? null : game.getOutcome().isWinner(p);
}
@Override
public LobbyPlayer getWinningPlayer() {
return game.getOutcome() == null ? null : game.getOutcome().getWinningLobbyPlayer();
}
@Override
public int getWinningTeam() {
return game.getOutcome() == null ? -1 : game.getOutcome().getWinningTeam();
}
/* (non-Javadoc)
* @see forge.view.IGameView#isFirstGameInMatch()
*/
@Override
public boolean isFirstGameInMatch() {
return game.getMatch().getPlayedGames().isEmpty();
}
@Override
public boolean isMatchOver() {
return game.getMatch().isMatchOver();
}
@Override
public int getNumGamesInMatch() {
return game.getMatch().getRules().getGamesPerMatch();
}
@Override
public int getNumPlayedGamesInMatch() {
return game.getMatch().getPlayedGames().size();
}
@Override
public Iterable<GameOutcome> getOutcomesOfMatch() {
return Iterables.unmodifiableIterable(game.getMatch().getPlayedGames());
}
@Override
public boolean isMatchWonBy(final LobbyPlayer p) {
return game.getMatch().isWonBy(p);
}
@Override
public int getGamesWonBy(final LobbyPlayer p) {
return game.getMatch().getGamesWonBy(p);
}
@Override
public GameOutcome.AnteResult getAnteResult() {
return null;
}
@Override
public Deck getDeck(final LobbyPlayer player) {
for (final RegisteredPlayer rp : game.getMatch().getPlayers()) {
if (rp.getPlayer().equals(player)) {
return rp.getDeck();
}
}
return null;
}
/* (non-Javadoc)
* @see forge.view.IGameView#isGameOver()
*/
@Override
public boolean isGameOver() {
return game.isGameOver();
}
@Override
public int getPoisonCountersToLose() {
return game.getRules().getPoisonCountersToLose();
}
/* (non-Javadoc)
* @see forge.view.IGameView#subscribeToEvents(java.lang.Object)
*/
@Override
public void subscribeToEvents(final Object subscriber) {
game.subscribeToEvents(subscriber);
}
@Override
public CombatView getCombat() {
synchronized (MatchUtil.class) {
if (MatchUtil.cachedCombatView != null) {
return MatchUtil.cachedCombatView;
}
final Combat combat = game.getCombat();
final CombatView combatView;
if (combat == null) {
combatView = null;
} else {
combatView = new CombatView();
for (final AttackingBand b : combat.getAttackingBands()) {
if (b == null) continue;
final GameEntity defender = combat.getDefenderByAttacker(b);
final List<Card> blockers = combat.getBlockers(b);
final boolean isBlocked = b.isBlocked() == Boolean.TRUE;
combatView.addAttackingBand(
getCardViews(b.getAttackers(), true),
getGameEntityView(defender, true),
blockers == null || !isBlocked ? null : getCardViews(blockers, true),
blockers == null ? null : getCardViews(blockers, true));
}
}
MatchUtil.cachedCombatView = combatView;
return combatView;
}
}
public final void refreshCombat() {
synchronized (MatchUtil.class) {
MatchUtil.cachedCombatView = null;
this.getCombat();
}
}
@Override
public void addLogObserver(final Observer o) {
game.getGameLog().addObserver(o);
}
@Override
public List<GameLogEntry> getLogEntries(final GameLogEntryType maxLogLevel) {
return game.getGameLog().getLogEntries(maxLogLevel);
}
@Override
public List<GameLogEntry> getLogEntriesExact(final GameLogEntryType logLevel) {
return game.getGameLog().getLogEntriesExact(logLevel);
}
/* (non-Javadoc)
* @see forge.view.IGameView#getRegisteredPlayers()
*/
@Override
public List<PlayerView> getPlayers() {
return getPlayerViews(game.getRegisteredPlayers(), false);
}
public List<PlayerView> getPlayers(Boolean update) {
return getPlayerViews(game.getRegisteredPlayers(), update);
}
@Override
public PlayerView getPlayerTurn() {
return getPlayerView(game.getPhaseHandler().getPlayerTurn(), false);
}
@Override
public PhaseType getPhase() {
return game.getPhaseHandler().getPhase();
}
/* (non-Javadoc)
* @see forge.view.IGameView#getStack()
*/
@Override
public List<StackItemView> getStack() {
final List<SpellAbilityStackInstance> stack = Lists.newArrayList(game.getStack());
final List<StackItemView> items = Collections.unmodifiableList(getStack(stack));
// clear the cache
MatchUtil.stackItems.retainAllKeys(stack);
return items;
}
/* (non-Javadoc)
* @see forge.view.IGameView#peekStack()
*/
@Override
public StackItemView peekStack() {
final SpellAbilityStackInstance top = game.getStack().peek();
if (top == null) {
return null;
}
return getStack(Lists.newArrayList(top)).iterator().next();
}
private List<StackItemView> getStack(final Iterable<SpellAbilityStackInstance> stack) {
MatchUtil.stackItems.retainAllKeys(Lists.newArrayList(stack));
final List<StackItemView> items = Lists.newLinkedList();
for (final SpellAbilityStackInstance si : stack) {
final int id = si.getId();
if (MatchUtil.stackItems.containsKey(id)) {
items.add(MatchUtil.stackItems.get(id));
} else {
items.add(getStackItemView(si));
}
}
return items;
}
public StackItemView getStackItemView(final SpellAbilityStackInstance si) {
if (si == null) {
return null;
}
final StackItemView newItem = new StackItemView(si, this);
MatchUtil.stackItems.put(si, newItem);
return newItem;
}
public SpellAbilityStackInstance getStackItem(final StackItemView view) {
if (view == null) {
return null;
}
return MatchUtil.stackItems.getKey(view.getId());
}
public final GameEntityView getGameEntityView(final GameEntity e, final Boolean update) {
if (e instanceof Card) {
return getCardView((Card)e, update);
}
if (e instanceof Player) {
return getPlayerView((Player)e, update);
}
return null;
}
public final List<GameEntityView> getGameEntityViews(final Iterable<? extends GameEntity> entities, final Boolean update) {
List<GameEntityView> views = new ArrayList<GameEntityView>();
for (GameEntity e : entities) {
views.add(getGameEntityView(e, update));
}
return views;
}
public final GameEntity getGameEntity(final GameEntityView view) {
if (view instanceof CardView) {
return getCard((CardView) view);
}
if (view instanceof PlayerView) {
return getPlayer((PlayerView) view);
}
return null;
}
public void updatePlayers(Iterable<PlayerView> views) {
for (PlayerView pv : views) {
writePlayerToView(getPlayer(pv), pv, true);
}
}
public final List<PlayerView> getPlayerViews(final Iterable<Player> players, final Boolean update) {
List<PlayerView> views = new ArrayList<PlayerView>();
for (Player p : players) {
views.add(getPlayerView(p, update));
}
return views;
}
public Player getPlayer(final PlayerView p) {
if (p == null) {
return null;
}
return MatchUtil.players.getKey(p.getId());
}
public PlayerView getPlayerView(final Player p, final Boolean update) {
if (p == null) {
return null;
}
PlayerView view = MatchUtil.players.get(p.getId());
if (view == null) {
view = new PlayerView(p.getLobbyPlayer(), p.getId());
if (update != null) { //passing null signifies to delay writing card to view even first time
writePlayerToView(p, view, update);
}
MatchUtil.players.put(p, view);
}
else if (Boolean.TRUE.equals(update)) {
writePlayerToView(p, view, true);
}
return view;
}
private void writePlayerToView(final Player p, final PlayerView view, final Boolean update) {
view.setCommanderInfo(CardFactoryUtil.getCommanderInfo(p).trim().replace("\r\n", "; "));
view.setKeywords(p.getKeywords());
view.setLife(p.getLife());
view.setMaxHandSize(p.getMaxHandSize());
view.setNumDrawnThisTurn(p.getNumDrawnThisTurn());
view.setPoisonCounters(p.getPoisonCounters());
view.setPreventNextDamage(p.getPreventNextDamageTotalShields());
view.setHasUnlimitedHandSize(p.isUnlimitedHandSize());
view.setAnteCards(getCardViews(p.getCardsIn(ZoneType.Ante), update));
view.setBfCards(getCardViews(p.getCardsIn(ZoneType.Battlefield, false), update));
view.setCommandCards(getCardViews(p.getCardsIn(ZoneType.Command), update));
view.setExileCards(getCardViews(p.getCardsIn(ZoneType.Exile), update));
view.setFlashbackCards(getCardViews(p.getCardsActivableInExternalZones(false), update));
view.setGraveCards(getCardViews(p.getCardsIn(ZoneType.Graveyard), update));
final List<Card> handCards = p.getCardsIn(ZoneType.Hand),
libraryCards = p.getCardsIn(ZoneType.Library);
view.setHandCards(getCardViews(handCards, update));
view.setLibraryCards(getCardViews(libraryCards, update));
view.setnHandCards(handCards.size());
view.setnLibraryCards(libraryCards.size());
for (final byte b : MagicColor.WUBRGC) {
view.setMana(b, p.getManaPool().getAmountOfColor(b));
}
}
public CardView getCardView(final Card c, final Boolean update) {
if (c == null || c != c.getCardForUi()) {
return null;
}
CardView view = MatchUtil.cards.get(c.getId());
if (view == null) {
view = new CardView(c.getId());
if (update != null) { //passing null signifies to delay writing card to view even first time
writeCardToView(c, view, MatchUtil.getGameView());
}
MatchUtil.cards.put(c, view);
}
else {
if (Boolean.TRUE.equals(update)) {
writeCardToView(c, view, MatchUtil.getGameView());
}
MatchUtil.cards.updateKey(view.getId(), c); //ensure the Card reference in the cache is not outdated
}
return view;
}
public void updateCards(Iterable<CardView> views) {
LocalGameView gameView = MatchUtil.getGameView();
for (CardView cv : views) {
writeCardToView(getCard(cv), cv, gameView);
}
}
public void updateAllCards() {
LocalGameView gameView = MatchUtil.getGameView();
for (Card c : MatchUtil.cards.getKeys()) {
writeCardToView(c, getCardView(c, false), gameView);
}
}
public final List<CardView> getCardViews(final Iterable<Card> cards, final Boolean update) {
List<CardView> cardViews = new ArrayList<CardView>();
for (Card c : cards) {
CardView cv = getCardView(c, update);
if (cv != null) {
cardViews.add(cv);
}
}
return cardViews;
}
public Card getCard(final CardView c) {
if (c == null) {
return null;
}
return MatchUtil.cards.getKey(c.getId());
}
private final Function<CardView, Card> FN_GET_CARD = new Function<CardView, Card>() {
@Override
public Card apply(final CardView input) {
return getCard(input);
}
};
public final List<Card> getCards(final List<CardView> cards) {
return ViewUtil.transformIfNotNull(cards, FN_GET_CARD);
}
private void writeCardToView(final Card c, final CardView view, final LocalGameView gameView) {
// First, write the values independent of other views
ViewUtil.writeNonDependentCardViewProperties(c, view, gameView.mayShowCard(c), gameView.mayShowCardFace(c));
// Next, write the values that depend on other views
final Combat combat = game.getCombat();
view.setOwner(getPlayerView(c.getOwner(), false));
view.setController(getPlayerView(c.getController(), false));
view.setAttacking(combat != null && combat.isAttacking(c));
view.setBlocking(combat != null && combat.isBlocking(c));
view.setChosenPlayer(getPlayerView(c.getChosenPlayer(), false));
view.setEquipping(getCardView(c.getEquipping(), false));
view.setEquippedBy(getCardViews(c.getEquippedBy(false), false));
view.setEnchantingCard(getCardView(c.getEnchantingCard(), false));
view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer(), false));
view.setEnchantedBy(getCardViews(c.getEnchantedBy(false), false));
view.setFortifiedBy(getCardViews(c.getFortifiedBy(false), false));
view.setGainControlTargets(getCardViews(c.getGainControlTargets(), false));
view.setCloneOrigin(getCardView(c.getCloneOrigin(), false));
view.setImprinted(getCardViews(c.getImprintedCards(), false));
view.setHauntedBy(getCardViews(c.getHauntedBy(), false));
view.setHaunting(getCardView(c.getHaunting(), false));
view.setMustBlock(c.getMustBlockCards() == null ? Collections.<CardView>emptySet() : getCardViews(c.getMustBlockCards(), false));
view.setPairedWith(getCardView(c.getPairedWith(), false));
}
public SpellAbilityView getSpellAbilityView(final SpellAbility sa) {
if (sa == null) {
return null;
}
final SpellAbilityView view;
if (MatchUtil.spabs.containsKey(sa.getId())) {
view = MatchUtil.spabs.get(sa.getId());
writeSpellAbilityToView(sa, view);
} else {
view = new SpellAbilityView(sa.getId());
writeSpellAbilityToView(sa, view);
MatchUtil.spabs.put(sa, view);
}
return view;
}
private final Function<SpellAbility, SpellAbilityView> FN_GET_SPAB_VIEW = new Function<SpellAbility, SpellAbilityView>() {
@Override
public SpellAbilityView apply(final SpellAbility input) {
return getSpellAbilityView(input);
}
};
public final List<SpellAbilityView> getSpellAbilityViews(final List<? extends SpellAbility> cards) {
return ViewUtil.transformIfNotNull(cards, FN_GET_SPAB_VIEW);
}
public SpellAbility getSpellAbility(final SpellAbilityView spabView) {
if (spabView == null) {
return null;
}
return getSpellAbility(spabView.getId());
}
public SpellAbility getSpellAbility(final int id) {
return id >= 0 ? MatchUtil.spabs.getKey(id) : null;
}
private final Function<SpellAbilityView, SpellAbility> FN_GET_SPAB = new Function<SpellAbilityView, SpellAbility>() {
@Override
public SpellAbility apply(final SpellAbilityView input) {
return getSpellAbility(input);
}
};
public final List<SpellAbility> getSpellAbilities(final List<SpellAbilityView> cards) {
return ViewUtil.transformIfNotNull(cards, FN_GET_SPAB);
}
private void writeSpellAbilityToView(final SpellAbility sa, final SpellAbilityView view) {
view.setHostCard(getCardView(sa.getHostCard(), false));
view.setDescription(sa.toUnsuppressedString());
view.setCanPlay(sa.canPlay());
view.setPromptIfOnlyPossibleAbility(sa.promptIfOnlyPossibleAbility());
}
@Override
public boolean getDisableAutoYields() {
return this.game.getDisableAutoYields();
}
@Override
public void setDisableAutoYields(final boolean b) {
this.game.setDisableAutoYields(b);
}
/**
* @param c
* a card.
* @return whether this player may view the specified card.
*/
protected abstract boolean mayShowCard(Card c);
/**
* @param c
* a card.
* @return whether this player may view the front card face of the specified
* card.
*/
protected abstract boolean mayShowCardFace(Card c);
}

View File

@@ -1,384 +0,0 @@
package forge.view;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import forge.LobbyPlayer;
import forge.card.MagicColor;
import forge.game.zone.ZoneType;
/**
* Representation of a {@link forge.game.player.Player}, containing only the
* information relevant to a user interface.
*
* Conversion from and to Players happens through {@link LocalGameView}.
*
* @author elcnesh
*/
public class PlayerView extends GameEntityView {
private final LobbyPlayer lobbyPlayer;
private final int id;
private Set<PlayerView> opponents;
private int life, poisonCounters, maxHandSize, numDrawnThisTurn, preventNextDamage;
private List<String> keywords;
private String commanderInfo;
private List<CardView>
anteCards = Lists.newArrayList(),
bfCards = Lists.newArrayList(),
commandCards = Lists.newArrayList(),
exileCards = Lists.newArrayList(),
flashbackCards = Lists.newArrayList(),
graveCards = Lists.newArrayList(),
handCards = Lists.newArrayList(),
libraryCards = Lists.newArrayList();
private int
nHandCards,
nLibraryCards;
private boolean hasUnlimitedHandSize;
private Map<Byte, Integer> mana = Maps.newHashMapWithExpectedSize(MagicColor.NUMBER_OR_COLORS + 1);
public PlayerView(final LobbyPlayer lobbyPlayer, final int id) {
this.lobbyPlayer = lobbyPlayer;
this.id = id;
}
/**
* @return the lobbyPlayer
*/
public LobbyPlayer getLobbyPlayer() {
return lobbyPlayer;
}
@Override
public int getId() {
return id;
}
@Override
public boolean equals(final Object obj) {
return obj instanceof PlayerView && this.getId() == ((PlayerView) obj).getId();
}
@Override
public int hashCode() {
return id;
}
public void setOpponents(final Iterable<PlayerView> opponents) {
this.opponents = Sets.newHashSet(opponents);
}
public boolean isOpponentOf(final PlayerView other) {
return opponents.contains(other);
}
public String getName() {
return this.getLobbyPlayer().getName();
}
@Override
public String toString() {
return this.getName();
}
/**
* @return the life
*/
public int getLife() {
return life;
}
/**
* @param life the life to set
*/
public void setLife(final int life) {
this.life = life;
}
/**
* @return the poisonCounters
*/
public int getPoisonCounters() {
return poisonCounters;
}
/**
* @param poisonCounters the poisonCounters to set
*/
public void setPoisonCounters(final int poisonCounters) {
this.poisonCounters = poisonCounters;
}
/**
* @return the maxHandSize
*/
public int getMaxHandSize() {
return maxHandSize;
}
/**
* @param maxHandSize the maxHandSize to set
*/
public void setMaxHandSize(final int maxHandSize) {
this.maxHandSize = maxHandSize;
}
/**
* @return the numDrawnThisTurn
*/
public int getNumDrawnThisTurn() {
return numDrawnThisTurn;
}
/**
* @param numDrawnThisTurn the numDrawnThisTurn to set
*/
public void setNumDrawnThisTurn(final int numDrawnThisTurn) {
this.numDrawnThisTurn = numDrawnThisTurn;
}
/**
* @return the preventNextDamage
*/
public int getPreventNextDamage() {
return preventNextDamage;
}
/**
* @param preventNextDamage the preventNextDamage to set
*/
public void setPreventNextDamage(final int preventNextDamage) {
this.preventNextDamage = preventNextDamage;
}
/**
* @return the keywords
*/
public List<String> getKeywords() {
return keywords;
}
/**
* @param keywords the keywords to set
*/
public void setKeywords(final Iterable<String> keywords) {
this.keywords = ImmutableList.copyOf(keywords);
}
/**
* @return the commanderInfo
*/
public String getCommanderInfo() {
return commanderInfo;
}
/**
* @param commanderInfo the commanderInfo to set
*/
public void setCommanderInfo(final String commanderInfo) {
this.commanderInfo = commanderInfo;
}
/**
* @return the anteCards
*/
public List<CardView> getAnteCards() {
return anteCards;
}
/**
* @param anteCards the anteCards to set
*/
public void setAnteCards(final List<CardView> anteCards) {
this.anteCards = ImmutableList.copyOf(anteCards);
}
/**
* @return the bfCards
*/
public List<CardView> getBfCards() {
return bfCards;
}
/**
* @param bfCards the bfCards to set
*/
public void setBfCards(final List<CardView> bfCards) {
this.bfCards = ImmutableList.copyOf(bfCards);
}
/**
* @return the commandCards
*/
public List<CardView> getCommandCards() {
return commandCards;
}
/**
* @param commandCards the commandCards to set
*/
public void setCommandCards(List<CardView> commandCards) {
this.commandCards = ImmutableList.copyOf(commandCards);
}
/**
* @return the exileCards
*/
public List<CardView> getExileCards() {
return exileCards;
}
/**
* @param exileCards the exileCards to set
*/
public void setExileCards(final List<CardView> exileCards) {
this.exileCards = ImmutableList.copyOf(exileCards);
}
/**
* @return the flashbackCards
*/
public List<CardView> getFlashbackCards() {
return flashbackCards;
}
/**
* @param flashbackCards the flashbackCards to set
*/
public void setFlashbackCards(final List<CardView> flashbackCards) {
this.flashbackCards = ImmutableList.copyOf(flashbackCards);
}
/**
* @return the graveCards
*/
public List<CardView> getGraveCards() {
return graveCards;
}
/**
* @param graveCards the graveCards to set
*/
public void setGraveCards(final List<CardView> graveCards) {
this.graveCards = ImmutableList.copyOf(graveCards);
}
/**
* @return the handCards
*/
public List<CardView> getHandCards() {
return handCards;
}
/**
* @param handCards the handCards to set
*/
public void setHandCards(final List<CardView> handCards) {
this.handCards = ImmutableList.copyOf(handCards);
}
/**
* @return the libraryCards
*/
public List<CardView> getLibraryCards() {
return libraryCards;
}
/**
* @param libraryCards the libraryCards to set
*/
public void setLibraryCards(final List<CardView> libraryCards) {
this.libraryCards = ImmutableList.copyOf(libraryCards);
}
public List<CardView> getCards(final ZoneType zone) {
switch (zone) {
case Ante:
return getAnteCards();
case Battlefield:
return getBfCards();
case Command:
return getCommandCards();
case Exile:
return getExileCards();
case Graveyard:
return getGraveCards();
case Hand:
return getHandCards();
case Library:
return getLibraryCards();
default:
return ImmutableList.of();
}
}
public int getNCards(final ZoneType zone) {
switch (zone) {
case Hand:
return getnHandCards();
case Library:
return getnLibraryCards();
default:
return getCards(zone).size();
}
}
/**
* @return the nHandCards
*/
public int getnHandCards() {
return nHandCards;
}
/**
* @param nHandCards the nHandCards to set
*/
public void setnHandCards(int nHandCards) {
this.nHandCards = nHandCards;
}
/**
* @return the nLibraryCards
*/
public int getnLibraryCards() {
return nLibraryCards;
}
/**
* @param nLibraryCards the nLibraryCards to set
*/
public void setnLibraryCards(int nLibraryCards) {
this.nLibraryCards = nLibraryCards;
}
/**
* @return the hasUnlimitedHandSize
*/
public boolean hasUnlimitedHandSize() {
return hasUnlimitedHandSize;
}
/**
* @param hasUnlimitedHandSize the hasUnlimitedHandSize to set
*/
public void setHasUnlimitedHandSize(final boolean hasUnlimitedHandSize) {
this.hasUnlimitedHandSize = hasUnlimitedHandSize;
}
public int getMana(final Byte color) {
return this.mana.containsKey(color) ? this.mana.get(color).intValue() : 0;
}
public void setMana(final byte color, final int mana) {
this.mana.put(Byte.valueOf(color), Integer.valueOf(mana));
}
}

View File

@@ -1,90 +0,0 @@
package forge.view;
import forge.game.IIdentifiable;
/**
* Representation of a {@link forge.game.spellability.SpellAbility}, containing
* only the information relevant to a user interface.
*
* Conversion from and to SpellAbilities happens through {@link LocalGameView}.
*
* @author elcnesh
*/
public class SpellAbilityView implements IIdentifiable {
private final int id;
private CardView hostCard;
private String description;
private boolean canPlay, promptIfOnlyPossibleAbility;
public SpellAbilityView(final int id) {
this.id = id;
}
@Override
public int getId() {
return id;
}
@Override
public String toString() {
return this.getDescription();
}
/**
* @return the hostCard
*/
public CardView getHostCard() {
return hostCard;
}
/**
* @param hostCard the hostCard to set
*/
public void setHostCard(CardView hostCard) {
this.hostCard = hostCard;
}
/**
* @return the description
*/
public String getDescription() {
return description;
}
/**
* @param description the description to set
*/
public void setDescription(String description) {
this.description = description;
}
/**
* @return the canPlay
*/
public boolean canPlay() {
return canPlay;
}
/**
* @param canPlay the canPlay to set
*/
public void setCanPlay(boolean canPlay) {
this.canPlay = canPlay;
}
/**
* @return the promptIfOnlyPossibleAbility
*/
public boolean isPromptIfOnlyPossibleAbility() {
return promptIfOnlyPossibleAbility;
}
/**
* @param promptIfOnlyPossibleAbility the promptIfOnlyPossibleAbility to set
*/
public void setPromptIfOnlyPossibleAbility(boolean promptIfOnlyPossibleAbility) {
this.promptIfOnlyPossibleAbility = promptIfOnlyPossibleAbility;
}
}

View File

@@ -1,91 +0,0 @@
package forge.view;
import forge.game.IIdentifiable;
import forge.game.spellability.SpellAbilityStackInstance;
/**
* Representation of a {@link forge.game.spellability.SpellAbilityStackInstance}
* , containing only the information relevant to a user interface.
*
* Conversion from and to SpellAbilityStackInstances happens through
* {@link LocalGameView}.
*
* @author elcnesh
*/
public class StackItemView implements IIdentifiable {
private final int id;
private final String key;
private final int sourceTrigger;
private final String text;
private final CardView source;
private final PlayerView activatingPlayer;
private final Iterable<CardView> targetCards;
private final Iterable<PlayerView> targetPlayers;
private final boolean ability, optionalTrigger;
private final StackItemView subInstance;
public StackItemView(SpellAbilityStackInstance si, LocalGameView gameView) {
id = si.getId();
key = si.getSpellAbility(false).toUnsuppressedString();
sourceTrigger = si.getSpellAbility(false).getSourceTrigger();
text = si.getStackDescription();
source = gameView.getCardView(si.getSourceCard(), true);
activatingPlayer = gameView.getPlayerView(si.getActivator(), false);
targetCards = gameView.getCardViews(si.getTargetChoices().getTargetCards(), false);
targetPlayers = gameView.getPlayerViews(si.getTargetChoices().getTargetPlayers(), false);
ability = si.isAbility();
optionalTrigger = si.isOptionalTrigger();
subInstance = si.getSubInstance() == null ? null : new StackItemView(si.getSubInstance(), gameView);
}
@Override
public int getId() {
return id;
}
public String getKey() {
return key;
}
public int getSourceTrigger() {
return sourceTrigger;
}
public String getText() {
return text;
}
public CardView getSource() {
return source;
}
public PlayerView getActivatingPlayer() {
return activatingPlayer;
}
public Iterable<CardView> getTargetCards() {
return targetCards;
}
public Iterable<PlayerView> getTargetPlayers() {
return targetPlayers;
}
public StackItemView getSubInstance() {
return subInstance;
}
public boolean isAbility() {
return ability;
}
public boolean isOptionalTrigger() {
return optionalTrigger;
}
@Override
public String toString() {
return text;
}
}

View File

@@ -1,164 +0,0 @@
package forge.view;
import java.util.LinkedList;
import java.util.List;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import forge.card.CardCharacteristicName;
import forge.game.card.Card;
import forge.game.card.CardCharacteristics;
import forge.item.IPaperCard;
import forge.view.CardView.CardStateView;
/**
* Static class providing utility methods to the view classes.
*
* @author elcnesh
*/
public final class ViewUtil {
private ViewUtil() {
}
/**
* Write those properties of a {@link Card} to a {@link CardView} that do
* <i>not</i> depend on other cards.
*
* @param c
* the {@link Card} to read from.
* @param view
* the {@link CardView} to write to.
*/
public static void writeNonDependentCardViewProperties(final Card c, final CardView view, final boolean mayShowCard, final boolean mayShowCardFace) {
final boolean hasAltState = c.isDoubleFaced() || c.isFlipCard() || c.isSplitCard() || (c.isFaceDown() && mayShowCardFace);
view.setMayBeShown(mayShowCard);
view.setZone(c.getZone() == null ? null : c.getZone().getZoneType());
view.setHasAltState(hasAltState);
view.setFaceDown(c.isFaceDown());
view.setCloned(c.isCloned());
view.setFlipCard(c.isFlipCard());
view.setFlipped(c.getCurState().equals(CardCharacteristicName.Flipped));
view.setSplitCard(c.isSplitCard());
view.setTransformed(c.getCurState().equals(CardCharacteristicName.Transformed));
view.setSetCode(c.getCurSetCode());
view.setRarity(c.getRarity());
view.setPhasedOut(c.isPhasedOut());
view.setSick(c.isInPlay() && c.isSick());
view.setTapped(c.isTapped());
view.setToken(c.isToken());
view.setCounters(c.getCounters());
view.setDamage(c.getDamage());
view.setAssignedDamage(c.getTotalAssignedDamage());
view.setRegenerationShields(c.getShieldCount());
view.setPreventNextDamage(c.getPreventNextDamageTotalShields());
view.setChosenType(c.getChosenType());
view.setChosenColors(Lists.newArrayList(c.getChosenColors()));
view.setNamedCard(c.getNamedCard());
if (c.isSplitCard()) {
final CardCharacteristicName orig, alt;
if (c.getCurState() == CardCharacteristicName.RightSplit) {
// If right half on stack, place it first
orig = CardCharacteristicName.RightSplit;
alt = CardCharacteristicName.LeftSplit;
} else {
orig = CardCharacteristicName.LeftSplit;
alt = CardCharacteristicName.RightSplit;
}
writeCardStateViewProperties(c, view.getOriginal(), orig);
writeCardStateViewProperties(c, view.getAlternate(), alt);
return;
}
final CardStateView origView = view.getOriginal();
origView.setName(c.getName());
origView.setColors(c.determineColor());
origView.setImageKey(c.getImageKey() );
origView.setType(c.getType());
origView.setManaCost(c.getManaCost());
origView.setPower(c.getNetAttack());
origView.setToughness(c.getNetDefense());
origView.setLoyalty(c.getCurrentLoyalty());
origView.setText(c.getText());
origView.setChangedColorWords(c.getChangedTextColorWords());
origView.setChangedTypes(c.getChangedTextTypeWords());
origView.setManaCost(c.getManaCost());
origView.setHasDeathtouch(c.hasKeyword("Deathtouch"));
origView.setHasInfect(c.hasKeyword("Infect"));
origView.setHasStorm(c.hasKeyword("Storm"));
origView.setHasTrample(c.hasKeyword("Trample"));
origView.setFoilIndex(c.getCharacteristics().getFoil());
final CardStateView altView = view.getAlternate();
CardCharacteristicName altState = null;
if (hasAltState) {
if (c.isFlipCard() && !c.getCurState().equals(CardCharacteristicName.Flipped)) {
altState = CardCharacteristicName.Flipped;
} else if (c.isDoubleFaced() && !c.getCurState().equals(CardCharacteristicName.Transformed)) {
altState = CardCharacteristicName.Transformed;
} else {
altState = CardCharacteristicName.Original;
}
if (altState != null) {
writeCardStateViewProperties(c, altView, altState);
}
}
if (altState == null) {
altView.reset();
}
}
private static void writeCardStateViewProperties(final Card c, final CardStateView view, final CardCharacteristicName state) {
final CardCharacteristics chars = c.getState(state);
view.setName(chars.getName());
view.setColors(chars.determineColor());
view.setImageKey(chars.getImageKey());
view.setType(chars.getType());
view.setManaCost(chars.getManaCost());
view.setPower(chars.getBaseAttack());
view.setToughness(chars.getBaseDefense());
view.setLoyalty(0); // Q why is loyalty not a property of CardCharacteristic? A: because no alt states have a base loyalty (only candidate is Garruk Relentless).
view.setText(chars.getOracleText());
view.setFoilIndex(chars.getFoil());
}
public static CardView getCardForUi(final IPaperCard pc) {
final Card c = Card.getCardForUi(pc);
if (c.getCardForUi() != c) {
return null;
}
final CardView view = new CardView(c.getId());
writeNonDependentCardViewProperties(c, view, true, true);
return view;
}
public static <T,V> List<V> transformIfNotNull(final Iterable<? extends T> input, final Function<T, V> transformation) {
return transformIfNotNull(input, transformation, new LinkedList<V>());
}
public static <T, V, L extends List<V>> L transformIfNotNull(final Iterable<? extends T> input, final Function<T, V> transformation, L ret) {
synchronized (input) {
for (final T t : input) {
final V v = transformation.apply(t);
if (v != null) {
ret.add(v);
}
}
}
return ret;
}
public static boolean mayViewAny(final Iterable<CardView> cards) {
return Iterables.any(cards, new Predicate<CardView>() {
@Override
public boolean apply(final CardView input) {
return input.getId() >= 0;
}
});
}
}