Commit large scale CardView refactoring to support head-to-head better, handle hidden and face down cards better, and reduce flickering of P/T and other attributes

This commit is contained in:
drdev
2014-10-01 14:15:25 +00:00
parent b12ca2f1dc
commit 4978e34262
23 changed files with 267 additions and 347 deletions

View File

@@ -53,7 +53,7 @@ public class CardDetailUtil {
if (card == null) {
return getBorderColors(null, false, false, false).iterator().next();
}
return getBorderColors(card.getColors(), card.isLand(), card.getCard().isUiDisplayable(), false).iterator().next();
return getBorderColors(card.getColors(), card.isLand(), card.getCard().mayBeShown(), false).iterator().next();
}
public static DetailColors getBorderColor(final ColorSet cardColors, final boolean isLand, boolean canShow) {
return getBorderColors(cardColors, isLand, canShow, false).get(0);
@@ -62,7 +62,7 @@ public class CardDetailUtil {
if (card == null) {
return getBorderColors(null, false, false, true);
}
return getBorderColors(card.getColors(), card.isLand(), card.getCard().isUiDisplayable(), true);
return getBorderColors(card.getColors(), card.isLand(), card.getCard().mayBeShown(), true);
}
private static List<DetailColors> getBorderColors(final ColorSet cardColors, final boolean isLand, boolean canShow, boolean supportMultiple) {
List<DetailColors> borderColors = new ArrayList<DetailColors>();

View File

@@ -32,6 +32,7 @@ import forge.game.event.GameEventCombatChanged;
import forge.game.event.GameEventCombatEnded;
import forge.game.event.GameEventGameFinished;
import forge.game.event.GameEventGameOutcome;
import forge.game.event.GameEventGameStarted;
import forge.game.event.GameEventManaPool;
import forge.game.event.GameEventPlayerControl;
import forge.game.event.GameEventPlayerLivesChanged;
@@ -74,9 +75,16 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
@Subscribe
public void receiveGameEvent(final GameEvent ev) {
gameView.updateViews();
ev.visit(this);
}
@Override
public Void visit(GameEventGameStarted event) {
gameView.endUpdateDelay(); //allow views to update once game starts
return null;
}
private final AtomicBoolean phaseUpdPlanned = new AtomicBoolean(false);
@Override
public Void visit(final GameEventTurnPhase ev) {
@@ -142,7 +150,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
final List<CardView> options = Lists.newArrayList();
for (final Entry<Player, Card> kv : ev.cards.entries()) {
final CardView fakeCard = new CardView(true); //use fake card so real cards appear with proper formatting
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 --");
options.add(fakeCard);
options.add(gameView.getCardView(kv.getValue()));
@@ -294,8 +302,7 @@ public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
@Override
public void run() {
synchronized (cardsToUpdate) {
final Iterable<CardView> newCardsToUpdate = gameView.getRefreshedCardViews(cardsToUpdate);
MatchUtil.updateCards(newCardsToUpdate);
MatchUtil.updateCards(cardsToUpdate);
cardsToUpdate.clear();
}
}

View File

@@ -46,7 +46,6 @@ import forge.game.trigger.TriggerType;
import forge.game.zone.ZoneType;
import forge.match.input.InputPlaybackControl;
import forge.match.input.InputQueue;
import forge.match.input.InputSynchronized;
import forge.model.FModel;
import forge.player.GamePlayerUtil;
import forge.player.LobbyPlayerHuman;
@@ -71,6 +70,7 @@ 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. */
@@ -180,6 +180,10 @@ public class MatchUtil {
if (p.getController() instanceof PlayerControllerHuman) {
final PlayerControllerHuman controller = (PlayerControllerHuman) p.getController();
LocalGameView gameView = controller.getGameView();
if (humanCount == 0) {
currentPlayer = p;
gameView.startUpdateDelay(); //delay updating views until game finishes initializing
}
game.subscribeToEvents(new FControlGameEventHandler(gameView, humanCount == 0));
gameViews.add(gameView);
humanCount++;
@@ -188,7 +192,9 @@ public class MatchUtil {
if (humanCount == 0) { //watch game but do not participate
LocalGameView gameView = new WatchLocalGame(GuiBase.getInterface(), game);
gameView.setLocalPlayer(sortedPlayers.get(0));
currentPlayer = sortedPlayers.get(0);
gameView.setLocalPlayer(currentPlayer);
gameView.startUpdateDelay();
game.subscribeToEvents(new FControlGameEventHandler(gameView, true));
gameViews.add(gameView);
}
@@ -235,7 +241,7 @@ public class MatchUtil {
}
public static LocalGameView getGameView() {
return getGameView(getCurrentPlayer());
return getGameView(currentPlayer);
}
public static LocalGameView getGameView(Player player) {
switch (gameViews.size()) {
@@ -244,10 +250,7 @@ public class MatchUtil {
case 0:
return null;
default:
if (player != null && player.getController() instanceof PlayerControllerHuman) {
return ((PlayerControllerHuman)player.getController()).getGameView();
}
return gameViews.get(0);
return gameViews.get(player.getId());
}
}
@@ -280,23 +283,14 @@ public class MatchUtil {
}
public static Player getCurrentPlayer() {
if (game == null) { return null; }
LobbyPlayer lobbyPlayer = getGuiPlayer();
return currentPlayer;
}
public static void setCurrentPlayer(Player currentPlayer0) {
if (currentPlayer == currentPlayer0) { return; }
currentPlayer = currentPlayer0;
if (gameViews.size() > 1) {
//account for if second human player is currently being prompted
InputSynchronized activeInput = InputQueue.getActiveInput();
if (activeInput != null) {
lobbyPlayer = activeInput.getOwner().getLobbyPlayer();
}
gameViews.get(currentPlayer.getId()).updateViews(); //ensure views updated when current player changes to account for changes in card visibility
}
for (Player p : game.getPlayers()) {
if (p.getLobbyPlayer() == lobbyPlayer) {
return p;
}
}
return null;
}
public static void alphaStrike() {
@@ -368,7 +362,7 @@ public class MatchUtil {
}
Player priorityPlayer = game.getPhaseHandler().getPriorityPlayer();
boolean humanHasPriority = priorityPlayer == null || priorityPlayer.getLobbyPlayer() == getGuiPlayer();
boolean humanHasPriority = priorityPlayer == null || priorityPlayer.getLobbyPlayer() instanceof LobbyPlayerHuman;
if (humanCount > 0 && humanHasPriority) {
game.getAction().checkGameOverCondition();
@@ -388,6 +382,7 @@ public class MatchUtil {
if (game == null) { return; }
game = null;
currentPlayer = null;
gameViews.clear();
players.clear();
cards.clear();

View File

@@ -22,6 +22,9 @@ import java.util.Observer;
import java.util.concurrent.atomic.AtomicReference;
import forge.FThreads;
import forge.game.card.Card;
import forge.game.player.Player;
import forge.game.spellability.SpellAbility;
import forge.interfaces.IGuiBase;
import forge.util.ITriggerEvent;
import forge.view.CardView;
@@ -97,34 +100,23 @@ public class InputProxy implements Observer {
}
}
/**
* <p>
* selectPlayer.
* </p>
*
* @param player
* a {@link forge.game.player.Player} object.
*/
public final void selectPlayer(final PlayerView player, final ITriggerEvent triggerEvent) {
public final void selectPlayer(final PlayerView playerView, final ITriggerEvent triggerEvent) {
final Input inp = getInput();
if (inp != null) {
inp.selectPlayer(gameView.getPlayer(player), triggerEvent);
final Player player = gameView.getPlayer(playerView);
if (player != null) {
inp.selectPlayer(player, triggerEvent);
}
}
}
/**
* <p>
* selectCard.
* </p>
*
* @param cardView
* a {@link forge.game.card.Card} object.
* @param triggerEvent
*/
public final boolean selectCard(final CardView cardView, final ITriggerEvent triggerEvent) {
final Input inp = getInput();
if (inp != null) {
return inp.selectCard(gameView.getCard(cardView), triggerEvent);
final Card card = gameView.getCard(cardView);
if (card != null) {
return inp.selectCard(card, triggerEvent);
}
}
return false;
}
@@ -132,7 +124,10 @@ public class InputProxy implements Observer {
public final void selectAbility(final SpellAbilityView ab) {
final Input inp = getInput();
if (inp != null) {
inp.selectAbility(gameView.getSpellAbility(ab));
final SpellAbility sa = gameView.getSpellAbility(ab);
if (sa != null) {
inp.selectAbility(sa);
}
}
}

View File

@@ -22,6 +22,7 @@ import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;
import forge.game.Game;
import forge.match.MatchUtil;
import forge.view.IGameView;
/**
@@ -33,12 +34,6 @@ import forge.view.IGameView;
* @version $Id: InputQueue.java 24769 2014-02-09 13:56:04Z Hellfish $
*/
public class InputQueue extends Observable {
private static InputSynchronized activeInput;
public static InputSynchronized getActiveInput() {
return activeInput;
}
private final BlockingDeque<InputSynchronized> inputStack = new LinkedBlockingDeque<InputSynchronized>();
private final InputLockUI inputLock;
@@ -62,9 +57,6 @@ public class InputQueue extends Observable {
if (topMostInput != inp) {
throw new RuntimeException("Cannot remove input " + inp.getClass().getSimpleName() + " because it's not on top of stack. Stack = " + inputStack );
}
if (inp == activeInput) {
activeInput = null;
}
updateObservers();
}
@@ -89,7 +81,9 @@ public class InputQueue extends Observable {
}
public void setInput(final InputSynchronized input) {
activeInput = input;
if (MatchUtil.getHumanCount() > 1) { //update current player if needed
MatchUtil.setCurrentPlayer(MatchUtil.players.getKey(input.getOwner().getId()));
}
inputStack.push(input);
inputLock.setGui(input.getGui());
InputBase.waitForOtherPlayer();

View File

@@ -11,11 +11,10 @@ import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.Range;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
@@ -29,8 +28,6 @@ import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import forge.FThreads;
import forge.LobbyPlayer;
import forge.achievement.AchievementCollection;
@@ -124,7 +121,6 @@ public class PlayerControllerHuman extends PlayerController {
* Cards this player may look at right now, for example when searching a
* library.
*/
private final Set<Card> mayLookAt = Sets.newHashSet();
private boolean mayLookAtAllCards = false;
public PlayerControllerHuman(Game game0, Player p, LobbyPlayer lp, IGuiBase gui) {
@@ -163,6 +159,30 @@ public class PlayerControllerHuman extends PlayerController {
return mayLookAtAllCards;
}
private final HashSet<Card> tempShownCards = new HashSet<Card>();
private void tempShowCard(Card c) {
CardView cv = MatchUtil.cards.get(c.getId());
if (!cv.mayBeShown()) {
cv.setMayBeShown(true);
tempShownCards.add(c);
}
}
private void tempShowCards(Iterable<Card> cards) {
if (mayLookAtAllCards) { return; } //no needed if this is set
for (Card c : cards) {
tempShowCard(c);
}
}
private void endTempShowCards() {
if (tempShownCards.isEmpty()) { return; }
for (Card c : tempShownCards) {
MatchUtil.cards.get(c.getId()).setMayBeShown(false);
}
tempShownCards.clear();
}
/**
* Set this to {@code true} to enable this player to see all cards any other
* player can see.
@@ -355,9 +375,9 @@ public class PlayerControllerHuman extends PlayerController {
return Lists.newArrayList(sc.getSelected());
}
this.mayLookAt.addAll(sourceList);
tempShowCards(sourceList);
final List<CardView> choices = SGuiChoose.many(getGui(), title, "Chosen Cards", min, max, gameView.getCardViews(sourceList), gameView.getCardView(sa.getHostCard()));
this.mayLookAt.removeAll(sourceList);
endTempShowCards();
return getCards(choices);
}
@@ -398,11 +418,11 @@ public class PlayerControllerHuman extends PlayerController {
for (final T t : options) {
if (t instanceof Card) {
// assume you may see any card passed through here
mayLookAt.add((Card) t);
tempShowCard((Card) t);
}
}
final GameEntityView result = isOptional ? SGuiChoose.oneOrNone(getGui(), title, gameView.getGameEntityViews((Iterable<GameEntity>) options)) : SGuiChoose.one(getGui(), title, gameView.getGameEntityViews((Iterable<GameEntity>) options));
mayLookAt.clear();
endTempShowCards();
return (T) gameView.getGameEntity(result);
}
@@ -540,9 +560,9 @@ public class PlayerControllerHuman extends PlayerController {
}
String fm = formatMessage(message, owner);
if (!cards.isEmpty()) {
mayLookAt.addAll(cards);
tempShowCards(cards);
SGuiChoose.reveal(getGui(), fm, gameView.getCardViews(cards));
mayLookAt.clear();
endTempShowCards();
}
else {
SGuiDialog.message(getGui(), formatMessage("There are no cards in {player's} " +
@@ -555,7 +575,7 @@ public class PlayerControllerHuman extends PlayerController {
List<Card> toBottom = null;
List<Card> toTop = null;
mayLookAt.addAll(topN);
tempShowCards(topN);
if (topN.size() == 1) {
if (willPutCardOnTop(topN.get(0))) {
toTop = topN;
@@ -579,7 +599,7 @@ public class PlayerControllerHuman extends PlayerController {
toTop = gameView.getCards(toTopViews);
}
}
mayLookAt.clear();
endTempShowCards();
return ImmutablePair.of(toTop, toBottom);
}
@@ -594,7 +614,7 @@ public class PlayerControllerHuman extends PlayerController {
@Override
public List<Card> orderMoveToZoneList(List<Card> cards, ZoneType destinationZone) {
List<CardView> choices;
mayLookAt.addAll(cards);
tempShowCards(cards);
switch (destinationZone) {
case Library:
choices = SGuiChoose.order(getGui(), "Choose order of cards to put into the library", "Closest to top", getCardViews(cards), null);
@@ -616,20 +636,20 @@ public class PlayerControllerHuman extends PlayerController {
break;
default:
System.out.println("ZoneType " + destinationZone + " - Not Ordered");
mayLookAt.clear();
endTempShowCards();
return cards;
}
mayLookAt.clear();
endTempShowCards();
return getCards(choices);
}
@Override
public List<Card> chooseCardsToDiscardFrom(Player p, SpellAbility sa, List<Card> valid, int min, int max) {
if (p != player) {
mayLookAt.addAll(valid);
tempShowCards(valid);
final List<CardView> choices = SGuiChoose.many(getGui(), "Choose " + min + " card" + (min != 1 ? "s" : "") + " to discard",
"Discarded", min, min, gameView.getCardViews(valid), null);
mayLookAt.clear();
endTempShowCards();
return getCards(choices);
}
@@ -1245,28 +1265,17 @@ public class PlayerControllerHuman extends PlayerController {
return SGuiDialog.confirm(getGui(), gameView.getCardView(sa.getHostCard()), "Choose a Pile", possibleValues);
}
mayLookAt.addAll(pile1);
mayLookAt.addAll(pile2);
tempShowCards(pile1);
tempShowCards(pile2);
final int idPile1 = Integer.MIN_VALUE, idPile2 = Integer.MIN_VALUE + 1;
final List<CardView> cards = Lists.newArrayListWithCapacity(pile1.size() + pile2.size() + 2);
final CardView pileView1 = new CardView(true) {
@Override
public String toString() {
return "--- Pile 1 ---";
}
};
pileView1.setId(idPile1);
final CardView pileView1 = new CardView(Integer.MIN_VALUE);
pileView1.getOriginal().setName("--- Pile 1 ---");
cards.add(pileView1);
cards.addAll(getCardViews(pile1));
final CardView pileView2 = new CardView(true) {
@Override
public String toString() {
return "--- Pile 2 ---";
}
};
pileView2.setId(idPile2);
final CardView pileView2 = new CardView(Integer.MIN_VALUE + 1);
pileView2.getOriginal().setName("--- Pile 2 ---");
cards.add(pileView2);
cards.addAll(getCardViews(pile2));
@@ -1277,13 +1286,14 @@ public class PlayerControllerHuman extends PlayerController {
if (chosen.equals(pileView1)) {
result = true;
break;
} else if (chosen.equals(pileView2)) {
}
if (chosen.equals(pileView2)) {
result = false;
break;
}
}
mayLookAt.clear();
endTempShowCards();
return result;
}
@@ -1359,7 +1369,7 @@ public class PlayerControllerHuman extends PlayerController {
@Override
public boolean canUndoLastAction() {
if (!game.stack.canUndo()) {
if (!game.stack.canUndo(player)) {
return false;
}
final Player priorityPlayer = game.getPhaseHandler().getPriorityPlayer();
@@ -1467,15 +1477,15 @@ public class PlayerControllerHuman extends PlayerController {
*/
@Override
public boolean mayShowCard(final Card c) {
if (mayLookAtAllCards()) {
if (mayLookAtAllCards) {
return true;
}
return c == null || mayLookAt.contains(c) || c.canBeShownTo(player);
return c == null || tempShownCards.contains(c) || c.canBeShownTo(player);
}
@Override
public boolean mayShowCardFace(final Card c) {
if (mayLookAtAllCards()) {
if (mayLookAtAllCards) {
return true;
}
return c == null || !c.isFaceDown() || c.canCardFaceBeShownTo(player);

View File

@@ -146,6 +146,14 @@ public class Cache<K extends IIdentifiable, V extends IIdentifiable> {
}
}
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.

View File

@@ -30,18 +30,14 @@ import forge.game.zone.ZoneType;
* @author elcnesh
*/
public class CardView extends GameEntityView {
public static final CardView EMPTY = new CardView(true);
private final CardStateView
original = new CardStateView(),
alternate = new CardStateView();
private boolean hasAltState;
private int id;
/** Will be false for {@link forge.game.ability.effects.DetachedCardEffect}. */
private final boolean isUiDisplayable;
private final int id;
private boolean mayBeShown;
private PlayerView owner, controller;
private ZoneType zone;
private boolean isCloned, isFaceDown, isFlipCard, isFlipped, isSplitCard, isTransformed;
@@ -68,14 +64,14 @@ public class CardView extends GameEntityView {
private Iterable<CardView> mustBlock;
private CardView pairedWith;
public CardView(final boolean isUiDisplayable) {
this.isUiDisplayable = isUiDisplayable;
public CardView(int id0) {
this.id = id0;
this.reset();
}
public void reset() {
final Iterable<CardView> emptyIterable = ImmutableSet.of();
this.id = 0;
this.mayBeShown = false;
this.hasAltState = false;
this.owner = null;
this.controller = null;
@@ -120,12 +116,11 @@ public class CardView extends GameEntityView {
return id;
}
public void setId(final int id) {
this.id = id;
public boolean mayBeShown() {
return this.mayBeShown;
}
public boolean isUiDisplayable() {
return isUiDisplayable;
public void setMayBeShown(boolean b0) {
this.mayBeShown = b0;
}
/**
@@ -726,12 +721,19 @@ public class CardView extends GameEntityView {
@Override
public String toString() {
if (this.getId() <= 0) { //if fake card, just return name
return this.getOriginal().getName();
}
if (!mayBeShown) {
return "(Unknown card)";
}
if (StringUtils.isEmpty(this.getOriginal().getName())) {
if (this.getId() <= 0) {
return "(Unknown card)";
} else if (this.hasAltState()) {
if (this.hasAltState()) {
return "Face-down card (" + this.getAlternate().getName() + ")";
}
return "(" + this.getId() + ")";
}
return this.getOriginal().getName() + " (" + this.getId() + ")";
@@ -765,7 +767,7 @@ public class CardView extends GameEntityView {
public void reset() {
this.name = "";
this.colors = ColorSet.getNullColor();
this.imageKey = ImageKeys.TOKEN_PREFIX + ImageKeys.MORPH_IMAGE;
this.imageKey = ImageKeys.HIDDEN_CARD;
this.type = Collections.emptyList();
this.manaCost = ManaCost.NO_COST;
this.power = 0;
@@ -822,7 +824,7 @@ public class CardView extends GameEntityView {
* @return the imageKey
*/
public String getImageKey() {
return imageKey;
return mayBeShown ? imageKey : ImageKeys.HIDDEN_CARD;
}
/**

View File

@@ -38,6 +38,7 @@ public abstract class LocalGameView implements IGameView {
protected final InputQueue inputQueue;
protected final InputProxy inputProxy;
private PlayerView localPlayerView;
private int updateDelays;
public LocalGameView(IGuiBase gui0, Game game0) {
game = game0;
@@ -349,30 +350,6 @@ public abstract class LocalGameView implements IGameView {
return ViewUtil.transformIfNotNull(players, FN_GET_PLAYER_VIEW);
}
public PlayerView getPlayerView(final Player p) {
if (p == null) {
return null;
}
PlayerView view = MatchUtil.players.get(p.getId());
if (view != null) {
getPlayerView(p, view);
}
else {
view = new PlayerView(p.getLobbyPlayer(), p.getId());
MatchUtil.players.put(p, view);
getPlayerView(p, view);
}
return view;
}
private PlayerView getPlayerViewFast(final Player p) {
if (p == null) {
return null;
}
return MatchUtil.players.get(p.getId());
}
public Player getPlayer(final PlayerView p) {
if (p == null) {
return null;
@@ -380,7 +357,23 @@ public abstract class LocalGameView implements IGameView {
return MatchUtil.players.getKey(p.getId());
}
private void getPlayerView(final Player p, final PlayerView view) {
public PlayerView getPlayerView(final Player p) {
if (p == null) {
return null;
}
PlayerView view = MatchUtil.players.get(p.getId());
if (view == null) {
view = new PlayerView(p.getLobbyPlayer(), p.getId());
if (updateDelays == 0) {
writePlayerToView(p, view);
}
MatchUtil.players.put(p, view);
}
return view;
}
private void writePlayerToView(final Player p, final PlayerView view) {
view.setCommanderInfo(CardFactoryUtil.getCommanderInfo(p).trim().replace("\r\n", "; "));
view.setKeywords(p.getKeywords());
view.setLife(p.getLife());
@@ -408,46 +401,41 @@ public abstract class LocalGameView implements IGameView {
}
public CardView getCardView(final Card c) {
if (c == null) {
if (c == null || c != c.getCardForUi()) {
return null;
}
final Card cUi = c.getCardForUi();
final boolean isDisplayable = cUi == c;
final boolean mayShow = mayShowCard(c);
CardView view = MatchUtil.cards.get(c.getId());
final boolean isNewView;
if (view != null) {
// Update to ensure the Card reference in the cache
// is not an outdated Card.
if (view.getId() > 0) {
MatchUtil.cards.updateKey(view.getId(), c);
if (view == null) {
view = new CardView(c.getId());
if (updateDelays == 0) {
writeCardToView(c, view, MatchUtil.getGameView());
}
isNewView = false;
} else if (isDisplayable && mayShow) {
view = new CardView(isDisplayable);
view.setId(c.getId());
MatchUtil.cards.put(c, view);
isNewView = true;
} else {
return CardView.EMPTY;
}
if (mayShow) {
writeCardToView(cUi, view);
}
else if (isDisplayable) {
if (!isNewView) {
view.reset();
}
}
else {
return null;
}
return view;
}
public void startUpdateDelay() {
updateDelays++;
}
public void endUpdateDelay() {
if (updateDelays > 0 && --updateDelays == 0) {
updateViews();
}
}
public void updateViews() {
if (updateDelays > 0) { return; }
for (Player p : MatchUtil.players.getKeys()) {
writePlayerToView(p, getPlayerView(p));
}
LocalGameView gameView = MatchUtil.getGameView();
for (Card c : MatchUtil.cards.getKeys()) {
writeCardToView(c, getCardView(c), gameView);
}
}
private final Function<Card, CardView> FN_GET_CARD_VIEW = new Function<Card, CardView>() {
@Override
@@ -460,41 +448,6 @@ public abstract class LocalGameView implements IGameView {
return ViewUtil.transformIfNotNull(cards, FN_GET_CARD_VIEW);
}
public final List<CardView> getRefreshedCardViews(final Iterable<CardView> cardViews) {
return ViewUtil.transformIfNotNull(cardViews, new Function<CardView, CardView>() {
@Override
public CardView apply(final CardView input) {
return MatchUtil.cards.getCurrentValue(input);
}
});
}
private CardView getCardViewFast(final Card c) {
if (c == null) {
return null;
}
final CardView view = MatchUtil.cards.get(c.getId());
if (mayShowCard(c)) {
return view;
} else if (view.isUiDisplayable()) {
return CardView.EMPTY;
}
return null;
}
private final Function<Card, CardView> FN_GET_CARDVIEW_FAST = new Function<Card, CardView>() {
@Override
public CardView apply(Card input) {
return getCardViewFast(input);
}
};
private List<CardView> getCardViewsFast(final Iterable<Card> cards) {
return ViewUtil.transformIfNotNull(cards, FN_GET_CARDVIEW_FAST);
}
public Card getCard(final CardView c) {
if (c == null) {
return null;
@@ -513,29 +466,29 @@ public abstract class LocalGameView implements IGameView {
return ViewUtil.transformIfNotNull(cards, FN_GET_CARD);
}
private void writeCardToView(final Card c, final CardView view) {
private void writeCardToView(final Card c, final CardView view, final LocalGameView gameView) {
// First, write the values independent of other views.
ViewUtil.writeNonDependentCardViewProperties(c, view, mayShowCardFace(c));
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(getPlayerViewFast(c.getOwner()));
view.setController(getPlayerViewFast(c.getController()));
view.setOwner(getPlayerView(c.getOwner()));
view.setController(getPlayerView(c.getController()));
view.setAttacking(combat != null && combat.isAttacking(c));
view.setBlocking(combat != null && combat.isBlocking(c));
view.setChosenPlayer(getPlayerViewFast(c.getChosenPlayer()));
view.setEquipping(getCardViewFast(Iterables.getFirst(c.getEquipping(), null)));
view.setEquippedBy(getCardViewsFast(c.getEquippedBy()));
view.setEnchantingCard(getCardViewFast(c.getEnchantingCard()));
view.setEnchantingPlayer(getPlayerViewFast(c.getEnchantingPlayer()));
view.setEnchantedBy(getCardViewsFast(c.getEnchantedBy()));
view.setFortifiedBy(getCardViewsFast(c.getFortifiedBy()));
view.setGainControlTargets(getCardViewsFast(c.getGainControlTargets()));
view.setCloneOrigin(getCardViewFast(c.getCloneOrigin()));
view.setImprinted(getCardViewsFast(c.getImprinted()));
view.setHauntedBy(getCardViewsFast(c.getHauntedBy()));
view.setHaunting(getCardViewFast(c.getHaunting()));
view.setMustBlock(c.getMustBlockCards() == null ? Collections.<CardView>emptySet() : getCardViewsFast(c.getMustBlockCards()));
view.setPairedWith(getCardViewFast(c.getPairedWith()));
view.setChosenPlayer(getPlayerView(c.getChosenPlayer()));
view.setEquipping(getCardView(Iterables.getFirst(c.getEquipping(), null)));
view.setEquippedBy(getCardViews(c.getEquippedBy()));
view.setEnchantingCard(getCardView(c.getEnchantingCard()));
view.setEnchantingPlayer(getPlayerView(c.getEnchantingPlayer()));
view.setEnchantedBy(getCardViews(c.getEnchantedBy()));
view.setFortifiedBy(getCardViews(c.getFortifiedBy()));
view.setGainControlTargets(getCardViews(c.getGainControlTargets()));
view.setCloneOrigin(getCardView(c.getCloneOrigin()));
view.setImprinted(getCardViews(c.getImprinted()));
view.setHauntedBy(getCardViews(c.getHauntedBy()));
view.setHaunting(getCardView(c.getHaunting()));
view.setMustBlock(c.getMustBlockCards() == null ? Collections.<CardView>emptySet() : getCardViews(c.getMustBlockCards()));
view.setPairedWith(getCardView(c.getPairedWith()));
}
public SpellAbilityView getSpellAbilityView(final SpellAbility sa) {

View File

@@ -33,9 +33,9 @@ public final class ViewUtil {
* @param view
* the {@link CardView} to write to.
*/
public static void writeNonDependentCardViewProperties(final Card c, final CardView view, final boolean mayShowCardFace) {
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.setId(c.getUniqueNumber());
view.setMayBeShown(mayShowCard);
view.setZone(c.getZone() == null ? null : c.getZone().getZoneType());
view.setHasAltState(hasAltState);
view.setFaceDown(c.isFaceDown());
@@ -130,8 +130,11 @@ public final class ViewUtil {
public static CardView getCardForUi(final IPaperCard pc) {
final Card c = Card.getCardForUi(pc);
final CardView view = new CardView(true);
writeNonDependentCardViewProperties(c, view, c.getCardForUi() == c);
if (c.getCardForUi() != c) {
return null;
}
final CardView view = new CardView(c.getId());
writeNonDependentCardViewProperties(c, view, true, true);
return view;
}