Add reveal button to mobile-gui

- currently it gets all cards that was revealed by via reveal(...)
- update menutab to show scroll indicator as default
This commit is contained in:
Anthony Calosa
2022-12-10 09:20:41 +08:00
parent d15a505081
commit ccc985654c
19 changed files with 841 additions and 367 deletions

View File

@@ -18,6 +18,7 @@ import forge.game.player.PlayerView;
import forge.game.player.RegisteredPlayer; import forge.game.player.RegisteredPlayer;
import forge.game.spellability.StackItemView; import forge.game.spellability.StackItemView;
import forge.game.zone.MagicStack; import forge.game.zone.MagicStack;
import forge.trackable.TrackableCollection;
import forge.trackable.TrackableObject; import forge.trackable.TrackableObject;
import forge.trackable.TrackableProperty; import forge.trackable.TrackableProperty;
import forge.util.collect.FCollectionView; import forge.util.collect.FCollectionView;
@@ -64,15 +65,19 @@ public class GameView extends TrackableObject {
public String getTitle() { public String getTitle() {
return get(TrackableProperty.Title); return get(TrackableProperty.Title);
} }
public boolean isCommander() { public boolean isCommander() {
return get(TrackableProperty.IsCommander); return get(TrackableProperty.IsCommander);
} }
public GameType getGameType() { public GameType getGameType() {
return get(TrackableProperty.GameType); return get(TrackableProperty.GameType);
} }
public int getPoisonCountersToLose() { public int getPoisonCountersToLose() {
return get(TrackableProperty.PoisonCountersToLose); return get(TrackableProperty.PoisonCountersToLose);
} }
public int getNumGamesInMatch() { public int getNumGamesInMatch() {
return get(TrackableProperty.NumGamesInMatch); return get(TrackableProperty.NumGamesInMatch);
} }
@@ -80,31 +85,39 @@ public class GameView extends TrackableObject {
public int getTurn() { public int getTurn() {
return get(TrackableProperty.Turn); return get(TrackableProperty.Turn);
} }
void updateTurn(PhaseHandler phaseHandler) { void updateTurn(PhaseHandler phaseHandler) {
set(TrackableProperty.Turn, phaseHandler.getTurn()); set(TrackableProperty.Turn, phaseHandler.getTurn());
} }
public PhaseType getPhase() { public PhaseType getPhase() {
return get(TrackableProperty.Phase); return get(TrackableProperty.Phase);
} }
void updatePhase(PhaseHandler phaseHandler) { void updatePhase(PhaseHandler phaseHandler) {
set(TrackableProperty.Phase, phaseHandler.getPhase()); set(TrackableProperty.Phase, phaseHandler.getPhase());
} }
public PlayerView getPlayerTurn() { public PlayerView getPlayerTurn() {
return get(TrackableProperty.PlayerTurn); return get(TrackableProperty.PlayerTurn);
} }
void updatePlayerTurn(PhaseHandler phaseHandler) { void updatePlayerTurn(PhaseHandler phaseHandler) {
set(TrackableProperty.PlayerTurn, PlayerView.get(phaseHandler.getPlayerTurn())); set(TrackableProperty.PlayerTurn, PlayerView.get(phaseHandler.getPlayerTurn()));
} }
public void updateNeedsPhaseRedrawn(PlayerView p, PhaseType ph) { public void updateNeedsPhaseRedrawn(PlayerView p, PhaseType ph) {
set(TrackableProperty.PlayerTurn, p); set(TrackableProperty.PlayerTurn, p);
set(TrackableProperty.Phase, ph); set(TrackableProperty.Phase, ph);
set(TrackableProperty.NeedsPhaseRedrawn, true); set(TrackableProperty.NeedsPhaseRedrawn, true);
} }
public boolean getNeedsPhaseRedrawn() { public boolean getNeedsPhaseRedrawn() {
if (get(TrackableProperty.NeedsPhaseRedrawn) == null) if (get(TrackableProperty.NeedsPhaseRedrawn) == null)
return false; return false;
return get(TrackableProperty.NeedsPhaseRedrawn); return get(TrackableProperty.NeedsPhaseRedrawn);
} }
public void clearNeedsPhaseRedrawn() { public void clearNeedsPhaseRedrawn() {
set(TrackableProperty.NeedsPhaseRedrawn, false); set(TrackableProperty.NeedsPhaseRedrawn, false);
} }
@@ -112,18 +125,23 @@ public class GameView extends TrackableObject {
public void updatePlanarPlayer(PlayerView p) { public void updatePlanarPlayer(PlayerView p) {
set(TrackableProperty.PlanarPlayer, p); set(TrackableProperty.PlanarPlayer, p);
} }
public PlayerView getPlanarPlayer() { public PlayerView getPlanarPlayer() {
return get(TrackableProperty.PlanarPlayer); return get(TrackableProperty.PlanarPlayer);
} }
public FCollectionView<StackItemView> getStack() { public FCollectionView<StackItemView> getStack() {
return get(TrackableProperty.Stack); return get(TrackableProperty.Stack);
} }
public StackItemView peekStack() { public StackItemView peekStack() {
return Iterables.getFirst(getStack(), null); return Iterables.getFirst(getStack(), null);
} }
public int getStormCount() { public int getStormCount() {
return get(TrackableProperty.StormCount); return get(TrackableProperty.StormCount);
} }
void updateStack(final MagicStack stack) { void updateStack(final MagicStack stack) {
set(TrackableProperty.Stack, StackItemView.getCollection(stack)); set(TrackableProperty.Stack, StackItemView.getCollection(stack));
set(TrackableProperty.StormCount, stack.getSpellsCastThisTurn().size()); set(TrackableProperty.StormCount, stack.getSpellsCastThisTurn().size());
@@ -132,6 +150,7 @@ public class GameView extends TrackableObject {
public boolean isFirstGameInMatch() { public boolean isFirstGameInMatch() {
return getNumPlayedGamesInMatch() == 0; return getNumPlayedGamesInMatch() == 0;
} }
public int getNumPlayedGamesInMatch() { public int getNumPlayedGamesInMatch() {
return get(TrackableProperty.NumPlayedGamesInMatch); return get(TrackableProperty.NumPlayedGamesInMatch);
} }
@@ -139,23 +158,29 @@ public class GameView extends TrackableObject {
public boolean isGameOver() { public boolean isGameOver() {
return get(TrackableProperty.GameOver); return get(TrackableProperty.GameOver);
} }
public boolean isMatchOver() { public boolean isMatchOver() {
return get(TrackableProperty.MatchOver); return get(TrackableProperty.MatchOver);
} }
public boolean isMulligan() { public boolean isMulligan() {
if (get(TrackableProperty.Mulligan) == null) if (get(TrackableProperty.Mulligan) == null)
return false; return false;
return get(TrackableProperty.Mulligan); return get(TrackableProperty.Mulligan);
} }
public void updateIsMulligan(boolean value) { public void updateIsMulligan(boolean value) {
set(TrackableProperty.Mulligan, value); set(TrackableProperty.Mulligan, value);
} }
public String getWinningPlayerName() { public String getWinningPlayerName() {
return get(TrackableProperty.WinningPlayerName); return get(TrackableProperty.WinningPlayerName);
} }
public int getWinningTeam() { public int getWinningTeam() {
return get(TrackableProperty.WinningTeam); return get(TrackableProperty.WinningTeam);
} }
void updateGameOver(final Game game) { void updateGameOver(final Game game) {
set(TrackableProperty.GameOver, game.isGameOver()); set(TrackableProperty.GameOver, game.isGameOver());
set(TrackableProperty.MatchOver, game.getMatch().isMatchOver()); set(TrackableProperty.MatchOver, game.getMatch().isMatchOver());
@@ -168,16 +193,27 @@ public class GameView extends TrackableObject {
public GameLog getGameLog() { public GameLog getGameLog() {
return get(TrackableProperty.GameLog); return get(TrackableProperty.GameLog);
} }
void updateGameLog(GameLog gameLog) { void updateGameLog(GameLog gameLog) {
flagAsChanged(TrackableProperty.GameLog); //don't need to set the property since it won't change flagAsChanged(TrackableProperty.GameLog); //don't need to set the property since it won't change
} }
public TrackableCollection<CardView> getRevealedCollection() {
return get(TrackableProperty.RevealedCardsCollection);
}
public void updateRevealedCards(TrackableCollection<CardView> collection) {
set(TrackableProperty.RevealedCardsCollection, collection);
}
public CombatView getCombat() { public CombatView getCombat() {
return get(TrackableProperty.CombatView); return get(TrackableProperty.CombatView);
} }
public void updateCombatView(CombatView combatView) { public void updateCombatView(CombatView combatView) {
set(TrackableProperty.CombatView, combatView); set(TrackableProperty.CombatView, combatView);
} }
void updateCombat(Combat combat) { void updateCombat(Combat combat) {
if (combat == null) { if (combat == null) {
set(TrackableProperty.CombatView, null); set(TrackableProperty.CombatView, null);

View File

@@ -43,6 +43,7 @@ public enum TrackableProperty {
SplitCard(TrackableTypes.BooleanType), SplitCard(TrackableTypes.BooleanType),
MergedCards(TrackableTypes.StringType), MergedCards(TrackableTypes.StringType),
MergedCardsCollection(TrackableTypes.CardViewCollectionType, FreezeMode.IgnoresFreeze), MergedCardsCollection(TrackableTypes.CardViewCollectionType, FreezeMode.IgnoresFreeze),
RevealedCardsCollection(TrackableTypes.CardViewCollectionType, FreezeMode.IgnoresFreeze),
PaperCardBackup(TrackableTypes.IPaperCardType), PaperCardBackup(TrackableTypes.IPaperCardType),
Attacking(TrackableTypes.BooleanType), Attacking(TrackableTypes.BooleanType),
@@ -278,6 +279,7 @@ public enum TrackableProperty {
TrackableProperty(TrackableType<?> type0) { TrackableProperty(TrackableType<?> type0) {
this(type0, FreezeMode.RespectsFreeze); this(type0, FreezeMode.RespectsFreeze);
} }
TrackableProperty(TrackableType<?> type0, FreezeMode freezeMode0) { TrackableProperty(TrackableType<?> type0, FreezeMode freezeMode0) {
type = type0; type = type0;
freezeMode = freezeMode0; freezeMode = freezeMode0;
@@ -293,7 +295,7 @@ public enum TrackableProperty {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> void updateObjLookup(Tracker tracker, T newObj) { public <T> void updateObjLookup(Tracker tracker, T newObj) {
((TrackableType<T>)type).updateObjLookup(tracker, newObj); ((TrackableType<T>) type).updateObjLookup(tracker, newObj);
} }
public void copyChangedProps(TrackableObject from, TrackableObject to) { public void copyChangedProps(TrackableObject from, TrackableObject to) {
@@ -302,15 +304,17 @@ public enum TrackableProperty {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T getDefaultValue() { public <T> T getDefaultValue() {
return ((TrackableType<T>)type).getDefaultValue(); return ((TrackableType<T>) type).getDefaultValue();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T deserialize(TrackableDeserializer td, T oldValue) { public <T> T deserialize(TrackableDeserializer td, T oldValue) {
return ((TrackableType<T>)type).deserialize(td, oldValue); return ((TrackableType<T>) type).deserialize(td, oldValue);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> void serialize(TrackableSerializer ts, T value) { public <T> void serialize(TrackableSerializer ts, T value) {
((TrackableType<T>)type).serialize(ts, value); ((TrackableType<T>) type).serialize(ts, value);
} }
//cache array of all properties to allow quick lookup by ordinal, //cache array of all properties to allow quick lookup by ordinal,
@@ -318,9 +322,11 @@ public enum TrackableProperty {
//we don't need to worry about the values changing since we will ensure //we don't need to worry about the values changing since we will ensure
//both players are on the same version of Forge before allowing them to connect //both players are on the same version of Forge before allowing them to connect
private static TrackableProperty[] props = values(); private static TrackableProperty[] props = values();
public static int serialize(TrackableProperty prop) { public static int serialize(TrackableProperty prop) {
return prop.ordinal(); return prop.ordinal();
} }
public static TrackableProperty deserialize(int ordinal) { public static TrackableProperty deserialize(int ordinal) {
return props[ordinal]; return props[ordinal];
} }

View File

@@ -1132,7 +1132,8 @@ public class Forge implements ApplicationListener {
return false; return false;
} }
} }
public static float mouseMovedX = 0;
public static float mouseMovedY = 0;
private static class MainInputProcessor extends FGestureAdapter { private static class MainInputProcessor extends FGestureAdapter {
private static final List<FDisplayObject> potentialListeners = new ArrayList<>(); private static final List<FDisplayObject> potentialListeners = new ArrayList<>();
private static char lastKeyTyped; private static char lastKeyTyped;
@@ -1216,7 +1217,7 @@ public class Forge implements ApplicationListener {
return false; return false;
} }
private void updatePotentialListeners(int x, int y) { private void updatePotentialListeners(float x, float y) {
potentialListeners.clear(); potentialListeners.clear();
//base potential listeners on object containing touch down point //base potential listeners on object containing touch down point
@@ -1391,8 +1392,6 @@ public class Forge implements ApplicationListener {
} }
//mouseMoved and scrolled events for desktop version //mouseMoved and scrolled events for desktop version
private int mouseMovedX, mouseMovedY;
@Override @Override
public boolean mouseMoved(int screenX, int screenY) { public boolean mouseMoved(int screenX, int screenY) {
magnify = true; magnify = true;

View File

@@ -338,6 +338,9 @@ public enum FSkinImage implements FImage {
FAVICON (FSkinProp.ICO_FAVICON, SourceFile.ICONS), FAVICON (FSkinProp.ICO_FAVICON, SourceFile.ICONS),
LOCK (FSkinProp.ICO_LOCK, SourceFile.ICONS), LOCK (FSkinProp.ICO_LOCK, SourceFile.ICONS),
//reveal icons
SEE (FSkinProp.ICO_SEE, SourceFile.ICONS),
UNSEE (FSkinProp.ICO_UNSEE, SourceFile.ICONS),
//Layout images //Layout images
HANDLE (FSkinProp.IMG_HANDLE, SourceFile.ICONS), HANDLE (FSkinProp.IMG_HANDLE, SourceFile.ICONS),

View File

@@ -774,9 +774,7 @@ public class CardRenderer {
} }
//Darken unselectable cards //Darken unselectable cards
if (unselectable) { if (unselectable) {
g.setAlphaComposite(0.6f); g.fillRect(FSkinColor.getStandardColor(Color.BLACK).alphaColor(0.6f), cx, cy, cw, ch);
g.fillRect(Color.BLACK, cx, cy, cw, ch);
g.setAlphaComposite(oldAlpha);
} }
//Magenta outline when card is chosen //Magenta outline when card is chosen
if (MatchController.instance.isUsedToPay(card)) { if (MatchController.instance.isUsedToPay(card)) {

View File

@@ -7,8 +7,13 @@ import forge.Graphics;
import forge.assets.FSkinColor; import forge.assets.FSkinColor;
import forge.assets.FSkinColor.Colors; import forge.assets.FSkinColor.Colors;
import forge.assets.FSkinTexture; import forge.assets.FSkinTexture;
import forge.gui.GuiBase;
import forge.screens.FScreen; import forge.screens.FScreen;
import forge.screens.match.views.VDevMenu;
import forge.screens.match.views.VGameMenu;
import forge.screens.match.views.VLog;
import forge.screens.match.views.VPlayers;
import forge.screens.match.views.VReveal;
import forge.screens.match.views.VStack;
import forge.toolbox.FContainer; import forge.toolbox.FContainer;
import forge.toolbox.FDisplayObject; import forge.toolbox.FDisplayObject;
import forge.toolbox.FOverlay; import forge.toolbox.FOverlay;
@@ -34,6 +39,7 @@ public abstract class FDropDown extends FScrollPane {
public FMenuTab getMenuTab() { public FMenuTab getMenuTab() {
return menuTab; return menuTab;
} }
public void setMenuTab(FMenuTab menuTab0) { public void setMenuTab(FMenuTab menuTab0) {
menuTab = menuTab0; menuTab = menuTab0;
} }
@@ -41,6 +47,7 @@ public abstract class FDropDown extends FScrollPane {
public FContainer getDropDownContainer() { public FContainer getDropDownContainer() {
return dropDownContainer; return dropDownContainer;
} }
public void setDropDownContainer(FContainer dropDownContainer0) { public void setDropDownContainer(FContainer dropDownContainer0) {
dropDownContainer = dropDownContainer0; dropDownContainer = dropDownContainer0;
} }
@@ -69,9 +76,11 @@ public abstract class FDropDown extends FScrollPane {
public void hide() { public void hide() {
setVisible(false); setVisible(false);
} }
public void setNextSelected() { public void setNextSelected() {
scrollToHoveredChild(true); scrollToHoveredChild(true);
} }
public void setPreviousSelected() { public void setPreviousSelected() {
scrollToHoveredChild(false); scrollToHoveredChild(false);
} }
@@ -101,7 +110,9 @@ public abstract class FDropDown extends FScrollPane {
@Override @Override
public void setVisible(boolean visible0) { public void setVisible(boolean visible0) {
if (isVisible() == visible0) { return; } if (isVisible() == visible0) {
return;
}
//add/remove drop down from its container, current screen, or top overlay when its visibility changes //add/remove drop down from its container, current screen, or top overlay when its visibility changes
FContainer container = getContainer(); FContainer container = getContainer();
@@ -114,8 +125,7 @@ public abstract class FDropDown extends FScrollPane {
container.add(backdrop); container.add(backdrop);
} }
container.add(this); container.add(this);
} } else {
else {
container.remove(this); container.remove(this);
if (backdrop != null) { if (backdrop != null) {
backdrop.setVisible(false); backdrop.setVisible(false);
@@ -131,10 +141,13 @@ public abstract class FDropDown extends FScrollPane {
} }
protected abstract boolean autoHide(); protected abstract boolean autoHide();
protected abstract ScrollBounds updateAndGetPaneSize(float maxWidth, float maxVisibleHeight); protected abstract ScrollBounds updateAndGetPaneSize(float maxWidth, float maxVisibleHeight);
protected void updateSizeAndPosition() { protected void updateSizeAndPosition() {
if (menuTab == null) { return; } if (menuTab == null) {
return;
}
Rectangle boundary = Forge.getCurrentScreen().getDropDownBoundary(); Rectangle boundary = Forge.getCurrentScreen().getDropDownBoundary();
@@ -145,8 +158,7 @@ public abstract class FDropDown extends FScrollPane {
if (y < boundary.y + boundary.height / 2) { if (y < boundary.y + boundary.height / 2) {
showAbove = false; showAbove = false;
maxVisibleHeight = boundary.y + boundary.height - y; //prevent covering prompt maxVisibleHeight = boundary.y + boundary.height - y; //prevent covering prompt
} } else { //handle drop downs at near bottom of screen
else { //handle drop downs at near bottom of screen
showAbove = true; showAbove = true;
y = menuTab.screenPos.y; y = menuTab.screenPos.y;
maxVisibleHeight = y - boundary.y; maxVisibleHeight = y - boundary.y;
@@ -191,6 +203,31 @@ public abstract class FDropDown extends FScrollPane {
float w = getWidth(); float w = getWidth();
float h = getHeight(); float h = getHeight();
g.drawRect(2, getBorderColor(), 0, 0, w, h); //ensure border shows up on all sides g.drawRect(2, getBorderColor(), 0, 0, w, h); //ensure border shows up on all sides
if (getDropDownOwner() instanceof FMenuTab) {
try {
if (getScrollLeft() > 0) {
float x = getIndicatorMargin();
float y = getHeight() / 2;
g.fillTriangle(getIndicatorColor(), x, y, x + getIndicatorSize(), y - getIndicatorSize(), x + getIndicatorSize(), y + getIndicatorSize());
}
if (getScrollLeft() < getMaxScrollLeft()) {
float x = getWidth() - getIndicatorMargin();
float y = getHeight() / 2;
g.fillTriangle(getIndicatorColor(), x, y, x - getIndicatorSize(), y - getIndicatorSize(), x - getIndicatorSize(), y + getIndicatorSize());
}
if (getScrollTop() > 0) {
float x = getWidth() / 2;
float y = getIndicatorMargin();
g.fillTriangle(getIndicatorColor(), x, y, x - getIndicatorSize(), y + getIndicatorSize(), x + getIndicatorSize(), y + getIndicatorSize());
}
if (getScrollTop() < getMaxScrollTop()) {
float x = getWidth() / 2;
float y = getHeight() - getIndicatorSize();
g.fillTriangle(getIndicatorColor(), x, y, x - getIndicatorSize(), y - getIndicatorSize(), x + getIndicatorSize(), y - getIndicatorSize());
}
} catch (Exception e) {
}
}
} }
protected FDisplayObject getDropDownOwner() { protected FDisplayObject getDropDownOwner() {
@@ -201,6 +238,7 @@ public abstract class FDropDown extends FScrollPane {
FDisplayObject owner = getDropDownOwner(); FDisplayObject owner = getDropDownOwner();
return owner == null || !owner.screenPos.contains(x, y); //auto-hide when backdrop pressed unless over owner return owner == null || !owner.screenPos.contains(x, y); //auto-hide when backdrop pressed unless over owner
} }
public void tapChild() { public void tapChild() {
if (selectedChild != null) { if (selectedChild != null) {
selectedChild.tap(0, 0, 1); selectedChild.tap(0, 0, 1);
@@ -210,18 +248,20 @@ public abstract class FDropDown extends FScrollPane {
hide(); hide();
} }
} }
public void cancel() { public void cancel() {
if (getMenuTab() != null) if (getMenuTab() != null)
getMenuTab().clearSelected(); getMenuTab().clearSelected();
hide(); hide();
} }
public void scrollToHoveredChild(boolean down) { public void scrollToHoveredChild(boolean down) {
selectedChild = null; selectedChild = null;
for (FDisplayObject fDisplayObject : getChildren()) { for (FDisplayObject fDisplayObject : getChildren()) {
if (fDisplayObject.isHovered()) { if (fDisplayObject.isHovered()) {
//System.out.println(fDisplayObject.screenPos.x+"|"+fDisplayObject.screenPos.y); //System.out.println(fDisplayObject.screenPos.x+"|"+fDisplayObject.screenPos.y);
float mod = down ? 0 : -fDisplayObject.screenPos.height; float mod = down ? 0 : -fDisplayObject.screenPos.height;
float y = fDisplayObject.screenPos.y+mod; float y = fDisplayObject.screenPos.y + mod;
scrollIntoView(fDisplayObject.screenPos.x, y, fDisplayObject.screenPos.width, fDisplayObject.screenPos.height, 0); scrollIntoView(fDisplayObject.screenPos.x, y, fDisplayObject.screenPos.width, fDisplayObject.screenPos.height, 0);
selectedChild = fDisplayObject; selectedChild = fDisplayObject;
break; break;
@@ -235,7 +275,7 @@ public abstract class FDropDown extends FScrollPane {
if (owner instanceof FSubMenu) { if (owner instanceof FSubMenu) {
return owner.contains(owner.getLeft() + owner.screenToLocalX(x), owner.getTop() + owner.screenToLocalY(y)); return owner.contains(owner.getLeft() + owner.screenToLocalX(x), owner.getTop() + owner.screenToLocalY(y));
} }
return true; return true;
} }
private class Backdrop extends FDisplayObject { private class Backdrop extends FDisplayObject {
@@ -252,7 +292,9 @@ public abstract class FDropDown extends FScrollPane {
@Override @Override
public boolean tap(float x, float y, int count) { public boolean tap(float x, float y, int count) {
if (!isVisible()) { return false; } if (!isVisible()) {
return false;
}
hide(); //always hide if tapped hide(); //always hide if tapped
return preventOwnerHandlingBackupTap(x, y, count); return preventOwnerHandlingBackupTap(x, y, count);
@@ -260,21 +302,21 @@ public abstract class FDropDown extends FScrollPane {
@Override @Override
public boolean pan(float x, float y, float deltaX, float deltaY, boolean moreVertical) { public boolean pan(float x, float y, float deltaX, float deltaY, boolean moreVertical) {
if (!GuiBase.isAndroid()) if (!isMatchHeader())
hide(); //always hide if backdrop panned hide(); //always hide if backdrop panned
return false; //allow pan to pass through to object behind backdrop return false; //allow pan to pass through to object behind backdrop
} }
@Override @Override
public boolean fling(float velocityX, float velocityY) { public boolean fling(float velocityX, float velocityY) {
if (!GuiBase.isAndroid()) if (!isMatchHeader())
hide(); //always hide if backdrop flung hide(); //always hide if backdrop flung
return false; //allow fling to pass through to object behind backdrop return false; //allow fling to pass through to object behind backdrop
} }
@Override @Override
public boolean zoom(float x, float y, float amount) { public boolean zoom(float x, float y, float amount) {
if (!GuiBase.isAndroid()) if (!isMatchHeader())
hide(); //always hide if backdrop zoomed hide(); //always hide if backdrop zoomed
return false; //allow zoom to pass through to object behind backdrop return false; //allow zoom to pass through to object behind backdrop
} }
@@ -284,4 +326,20 @@ public abstract class FDropDown extends FScrollPane {
//draw nothing for backdrop //draw nothing for backdrop
} }
} }
private boolean isMatchHeader() {
if (this instanceof VGameMenu)
return true;
if (this instanceof VPlayers)
return true;
if (this instanceof VReveal)
return true;
if (this instanceof VLog)
return true;
if (this instanceof VDevMenu)
return true;
if (this instanceof VStack)
return true;
return false;
}
} }

View File

@@ -4,15 +4,21 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import com.badlogic.gdx.Input; import com.badlogic.gdx.Input;
import forge.Forge;
import forge.Graphics; import forge.Graphics;
import forge.screens.FScreen.Header; import forge.screens.FScreen.Header;
import forge.screens.match.MatchController;
public class FMenuBar extends Header { public class FMenuBar extends Header {
private final List<FMenuTab> tabs = new ArrayList<>(); private final List<FMenuTab> tabs = new ArrayList<>();
private int selected = -1; private int selected = -1;
public void addTab(String text0, FDropDown dropDown0) { public void addTab(String text0, FDropDown dropDown0) {
FMenuTab tab = new FMenuTab(text0, this, dropDown0, tabs.size()); addTab(text0, dropDown0, false);
}
public void addTab(String text0, FDropDown dropDown0, boolean iconOnly) {
FMenuTab tab = new FMenuTab(text0, this, dropDown0, tabs.size(), iconOnly);
dropDown0.setMenuTab(tab); dropDown0.setMenuTab(tab);
tabs.add(add(tab)); tabs.add(add(tab));
} }
@@ -29,10 +35,22 @@ public class FMenuBar extends Header {
protected void doLayout(float width, float height) { protected void doLayout(float width, float height) {
int visibleTabCount = 0; int visibleTabCount = 0;
float minWidth = 0; float minWidth = 0;
int iconOnlyTabCount = 0;
float iconMinWidth = 0;
for (FMenuTab tab : tabs) { for (FMenuTab tab : tabs) {
if (tab.isVisible()) { if (tab.isVisible()) {
minWidth += tab.getMinWidth(); if (Forge.isLandscapeMode()) {
visibleTabCount++; if (!tab.iconOnly) {
minWidth += tab.getMinWidth();
visibleTabCount++;
} else {
iconMinWidth += tab.getMinWidth();
iconOnlyTabCount++;
}
} else {
minWidth += tab.getMinWidth();
visibleTabCount++;
}
} }
} }
int tabWidth; int tabWidth;
@@ -40,12 +58,15 @@ public class FMenuBar extends Header {
float dx = (width - minWidth) / visibleTabCount; float dx = (width - minWidth) / visibleTabCount;
for (FMenuTab tab : tabs) { for (FMenuTab tab : tabs) {
if (tab.isVisible()) { if (tab.isVisible()) {
if (tab.iconOnly) {
tab.setActiveIcon(MatchController.instance.getGameView().getRevealedCollection() != null);
}
tabWidth = Math.round(tab.getMinWidth() + dx); tabWidth = Math.round(tab.getMinWidth() + dx);
if (x + tabWidth > width) { if (x + tabWidth > width) {
tabWidth = Math.round(width - x); //prevent final tab extending off screen tabWidth = Math.round(width - x); //prevent final tab extending off screen
} }
tab.setBounds(x, 0, tabWidth, height); tab.setBounds(tab.iconOnly ? 0 : x, 0, tab.iconOnly ? tab.getMinWidth() + FMenuTab.PADDING * 2 : tabWidth, height);
x += tabWidth; x += tab.iconOnly ? tab.getMinWidth() + FMenuTab.PADDING * 2 : tabWidth;
} }
} }
} }
@@ -61,6 +82,7 @@ public class FMenuBar extends Header {
public float doLandscapeLayout(float screenWidth, float screenHeight) { public float doLandscapeLayout(float screenWidth, float screenHeight) {
return 0; return 0;
} }
public void setNextSelected() { public void setNextSelected() {
selected++; selected++;
closeAll(); closeAll();
@@ -68,13 +90,15 @@ public class FMenuBar extends Header {
selected = 0; selected = 0;
try { try {
tabs.get(selected).showDropDown(); tabs.get(selected).showDropDown();
} catch (Exception e) {} } catch (Exception e) {
}
if (selected > tabs.size()) { if (selected > tabs.size()) {
closeAll(); closeAll();
selected = tabs.size(); selected = tabs.size();
return; return;
} }
} }
public void setPreviousSelected() { public void setPreviousSelected() {
selected--; selected--;
closeAll(); closeAll();
@@ -82,21 +106,25 @@ public class FMenuBar extends Header {
selected = tabs.size(); selected = tabs.size();
try { try {
tabs.get(selected).showDropDown(); tabs.get(selected).showDropDown();
} catch (Exception e) {} } catch (Exception e) {
}
if (selected < 0) { if (selected < 0) {
closeAll(); closeAll();
selected = -1; selected = -1;
return; return;
} }
} }
public void closeAll() { public void closeAll() {
for (FMenuTab fMenuTab : tabs) { for (FMenuTab fMenuTab : tabs) {
fMenuTab.hideDropDown(); fMenuTab.hideDropDown();
} }
} }
public boolean isShowingMenu(boolean anyDropdown) { public boolean isShowingMenu(boolean anyDropdown) {
return tabs.stream().anyMatch(tab -> tab.isShowingDropdownMenu(anyDropdown)); return tabs.stream().anyMatch(tab -> tab.isShowingDropdownMenu(anyDropdown));
} }
public void clearSelected() { public void clearSelected() {
selected--; selected--;
if (selected < -1) if (selected < -1)

View File

@@ -5,14 +5,18 @@ import com.badlogic.gdx.utils.Align;
import forge.Forge; import forge.Forge;
import forge.Graphics; import forge.Graphics;
import forge.assets.FImage;
import forge.assets.FSkinColor; import forge.assets.FSkinColor;
import forge.assets.FSkinColor.Colors; import forge.assets.FSkinColor.Colors;
import forge.assets.FSkinFont; import forge.assets.FSkinFont;
import forge.assets.FSkinImage;
import forge.toolbox.FDisplayObject; import forge.toolbox.FDisplayObject;
import forge.util.Utils; import forge.util.Utils;
public class FMenuTab extends FDisplayObject { public class FMenuTab extends FDisplayObject {
public static final FSkinFont FONT = FSkinFont.get(12); public static final FSkinFont FONT = FSkinFont.get(12);
boolean iconOnly = false;
boolean active = false;
private static FSkinColor getSelBackColor() { private static FSkinColor getSelBackColor() {
if (Forge.isMobileAdventureMode) if (Forge.isMobileAdventureMode)
return FSkinColor.get(Colors.ADV_CLR_ACTIVE); return FSkinColor.get(Colors.ADV_CLR_ACTIVE);
@@ -42,10 +46,11 @@ public class FMenuTab extends FDisplayObject {
private float minWidth; private float minWidth;
private int index; private int index;
public FMenuTab(String text0, FMenuBar menuBar0, FDropDown dropDown0, int index0) { public FMenuTab(String text0, FMenuBar menuBar0, FDropDown dropDown0, int index0, boolean iconOnly0) {
menuBar = menuBar0; menuBar = menuBar0;
dropDown = dropDown0; dropDown = dropDown0;
index = index0; index = index0;
iconOnly = iconOnly0;
setText(text0); setText(text0);
} }
@@ -89,6 +94,10 @@ public class FMenuTab extends FDisplayObject {
menuBar.revalidate(); menuBar.revalidate();
} }
public void setActiveIcon(boolean value) {
active = value;
}
@Override @Override
public void setVisible(boolean visible0) { public void setVisible(boolean visible0) {
if (isVisible() == visible0) { return; } if (isVisible() == visible0) { return; }
@@ -102,6 +111,10 @@ public class FMenuTab extends FDisplayObject {
} }
public float getMinWidth() { public float getMinWidth() {
if (iconOnly) {
float multiplier = Forge.isLandscapeMode() ? 2.5f : 1.8f;
return FONT.getLineHeight() * multiplier;
}
return minWidth; return minWidth;
} }
@@ -140,7 +153,14 @@ public class FMenuTab extends FDisplayObject {
h = getHeight() - 2 * PADDING; h = getHeight() - 2 * PADDING;
if (isHovered()) if (isHovered())
g.fillRect(getSelBackColor().brighter(), x, y, w, h); g.fillRect(getSelBackColor().brighter(), x, y, w, h);
g.drawText(text, FONT, foreColor, x, y, w, h, false, Align.center, true); if (iconOnly) {
float mod = w * 0.75f;
FImage icon = active ? FSkinImage.SEE : FSkinImage.UNSEE;
float scaleW = icon.getWidth() * 0.8f;
float scaleH = icon.getHeight() * 0.8f;
g.drawImage(icon, x + w/2 - scaleW/2, y + h/2 - scaleH/2, scaleW, scaleH);
} else
g.drawText(text, FONT, foreColor, x, y, w, h, false, Align.center, true);
} }
public boolean isShowingDropdownMenu(boolean any) { public boolean isShowingDropdownMenu(boolean any) {
if (dropDown == null) if (dropDown == null)

View File

@@ -123,9 +123,7 @@ public class LoadingOverlay extends FOverlay {
float y = (getHeight() - panelHeight) / 2; float y = (getHeight() - panelHeight) / 2;
float oldAlpha = g.getfloatAlphaComposite(); float oldAlpha = g.getfloatAlphaComposite();
//dark translucent back.. //dark translucent back..
g.setAlphaComposite(0.6f); g.fillRect(FSkinColor.getStandardColor(Color.BLACK).alphaColor(0.6f), 0, 0, getWidth(), getHeight());
g.fillRect(Color.BLACK, 0, 0, getWidth(), getHeight());
g.setAlphaComposite(oldAlpha);
//overlay //overlay
g.fillRect(getOverlayColor(), x, y, panelWidth, panelHeight); g.fillRect(getOverlayColor(), x, y, panelWidth, panelHeight);
g.drawRect(Utils.scale(2), getForeColor(), x, y, panelWidth, panelHeight); g.drawRect(Utils.scale(2), getForeColor(), x, y, panelWidth, panelHeight);

View File

@@ -13,6 +13,7 @@ import forge.card.CardZoom;
import forge.game.spellability.StackItemView; import forge.game.spellability.StackItemView;
import forge.gui.interfaces.IGuiGame; import forge.gui.interfaces.IGuiGame;
import forge.screens.match.views.VField; import forge.screens.match.views.VField;
import forge.screens.match.views.VReveal;
import forge.toolbox.FDisplayObject; import forge.toolbox.FDisplayObject;
import forge.util.Utils; import forge.util.Utils;
import forge.util.collect.FCollectionView; import forge.util.collect.FCollectionView;
@@ -77,6 +78,7 @@ public class MatchScreen extends FScreen {
private List<VPlayerPanel> playerPanelsList; private List<VPlayerPanel> playerPanelsList;
private final VGameMenu gameMenu; private final VGameMenu gameMenu;
private final VPlayers players; private final VPlayers players;
private final VReveal revealed;
private final VLog log; private final VLog log;
private final VStack stack; private final VStack stack;
private final VDevMenu devMenu; private final VDevMenu devMenu;
@@ -101,7 +103,7 @@ public class MatchScreen extends FScreen {
for (VPlayerPanel playerPanel : playerPanels0) { for (VPlayerPanel playerPanel : playerPanels0) {
playerPanels.put(playerPanel.getPlayer(), scroller.add(playerPanel)); playerPanels.put(playerPanel.getPlayer(), scroller.add(playerPanel));
playerPanel.setFlipped(true); playerPanel.setFlipped(true);
if(!playerPanel.getPlayer().isAI()) if (!playerPanel.getPlayer().isAI())
humanCount++; humanCount++;
} }
bottomPlayerPanel = playerPanels0.get(0); bottomPlayerPanel = playerPanels0.get(0);
@@ -111,7 +113,7 @@ public class MatchScreen extends FScreen {
//reorder list so bottom player is at the end of the list ensuring top to bottom turn order //reorder list so bottom player is at the end of the list ensuring top to bottom turn order
playerPanelsList.remove(bottomPlayerPanel); playerPanelsList.remove(bottomPlayerPanel);
playerPanelsList.add(bottomPlayerPanel); playerPanelsList.add(bottomPlayerPanel);
selectedPlayer = playerPanelsList.size()-1; selectedPlayer = playerPanelsList.size() - 1;
bottomPlayerPrompt = add(new VPrompt("", "", bottomPlayerPrompt = add(new VPrompt("", "",
e -> getGameController().selectButtonOk(), e -> getGameController().selectButtonOk(),
@@ -133,6 +135,8 @@ public class MatchScreen extends FScreen {
gameMenu.setDropDownContainer(this); gameMenu.setDropDownContainer(this);
players = new VPlayers(); players = new VPlayers();
players.setDropDownContainer(this); players.setDropDownContainer(this);
revealed = new VReveal();
revealed.setDropDownContainer(this);
log = new VLog(); log = new VLog();
log.setDropDownContainer(this); log.setDropDownContainer(this);
devMenu = new VDevMenu(); devMenu = new VDevMenu();
@@ -140,15 +144,15 @@ public class MatchScreen extends FScreen {
stack = new VStack(); stack = new VStack();
stack.setDropDownContainer(this); stack.setDropDownContainer(this);
FMenuBar menuBar = (FMenuBar)getHeader(); FMenuBar menuBar = (FMenuBar) getHeader();
if (topPlayerPrompt == null) { if (topPlayerPrompt == null) {
menuBar.addTab("", revealed, true);
menuBar.addTab(Forge.getLocalizer().getMessage("lblGame"), gameMenu); menuBar.addTab(Forge.getLocalizer().getMessage("lblGame"), gameMenu);
menuBar.addTab(Forge.getLocalizer().getMessage("lblPlayers") + " (" + playerPanels.size() + ")", players); menuBar.addTab(Forge.getLocalizer().getMessage("lblPlayers") + " (" + playerPanels.size() + ")", players);
menuBar.addTab(Forge.getLocalizer().getMessage("lblLog"), log); menuBar.addTab(Forge.getLocalizer().getMessage("lblLog"), log);
menuBar.addTab(Forge.getLocalizer().getMessage("lblDev"), devMenu); menuBar.addTab(Forge.getLocalizer().getMessage("lblDev"), devMenu);
menuBar.addTab( Forge.getLocalizer().getMessage("lblStack") + " (0)", stack); menuBar.addTab(Forge.getLocalizer().getMessage("lblStack") + " (0)", stack);
} } else {
else {
menuBar.addTab("\u2022 \u2022 \u2022", new PlayerSpecificMenu(true)); menuBar.addTab("\u2022 \u2022 \u2022", new PlayerSpecificMenu(true));
stack.setRotate90(true); stack.setRotate90(true);
menuBar.addTab(Forge.getLocalizer().getMessage("lblStack") + " (0)", stack); menuBar.addTab(Forge.getLocalizer().getMessage("lblStack") + " (0)", stack);
@@ -162,11 +166,11 @@ public class MatchScreen extends FScreen {
} }
} }
private boolean is4Player(){ private boolean is4Player() {
return playerPanels.keySet().size() == 4; return playerPanels.keySet().size() == 4;
} }
private boolean is3Player(){ private boolean is3Player() {
return playerPanels.keySet().size() == 3; return playerPanels.keySet().size() == 3;
} }
@@ -176,9 +180,10 @@ public class MatchScreen extends FScreen {
private class HiddenMenuTab extends FMenuTab { private class HiddenMenuTab extends FMenuTab {
private HiddenMenuTab(FDropDown dropDown0) { private HiddenMenuTab(FDropDown dropDown0) {
super(null, null, dropDown0, -1); super(null, null, dropDown0, -1, false);
setVisible(false); setVisible(false);
} }
@Override @Override
public void setText(String text0) { public void setText(String text0) {
//avoid trying to set text for this tab //avoid trying to set text for this tab
@@ -214,8 +219,7 @@ public class MatchScreen extends FScreen {
Rectangle menuScreenPos = PlayerSpecificMenu.this.screenPos; Rectangle menuScreenPos = PlayerSpecificMenu.this.screenPos;
if (dropDown.getRotate180()) { if (dropDown.getRotate180()) {
dropDown.getMenuTab().screenPos.setPosition(menuScreenPos.x + menuScreenPos.width, menuScreenPos.y); dropDown.getMenuTab().screenPos.setPosition(menuScreenPos.x + menuScreenPos.width, menuScreenPos.y);
} } else {
else {
dropDown.getMenuTab().screenPos.setPosition(menuScreenPos.x + menuScreenPos.width, menuScreenPos.y + menuScreenPos.height); dropDown.getMenuTab().screenPos.setPosition(menuScreenPos.x + menuScreenPos.width, menuScreenPos.y + menuScreenPos.height);
} }
dropDown.show(); dropDown.show();
@@ -233,8 +237,7 @@ public class MatchScreen extends FScreen {
if (ForgePreferences.DEV_MODE) { if (ForgePreferences.DEV_MODE) {
addItem(new MenuItem(Forge.getLocalizer().getMessage("lblDev"), devMenu)); addItem(new MenuItem(Forge.getLocalizer().getMessage("lblDev"), devMenu));
} }
} } else { //TODO: Support using menu when player doesn't have priority
else { //TODO: Support using menu when player doesn't have priority
FMenuItem item = new FMenuItem(Forge.getLocalizer().getMessage("lblMustWaitPriority"), null); FMenuItem item = new FMenuItem(Forge.getLocalizer().getMessage("lblMustWaitPriority"), null);
item.setEnabled(false); item.setEnabled(false);
addItem(item); addItem(item);
@@ -280,7 +283,7 @@ public class MatchScreen extends FScreen {
return topPlayerPanel; return topPlayerPanel;
} }
public void setViewWinLose( ViewWinLose viewWinLose ){ public void setViewWinLose(ViewWinLose viewWinLose) {
this.viewWinLose = viewWinLose; this.viewWinLose = viewWinLose;
} }
@@ -338,29 +341,31 @@ public class MatchScreen extends FScreen {
@Override @Override
protected void drawOverlay(Graphics g) { protected void drawOverlay(Graphics g) {
final GameView game = MatchController.instance.getGameView(); final GameView game = MatchController.instance.getGameView();
if (game == null) { return; } if (game == null) {
return;
if (gameMenu!=null) {
if (gameMenu.getChildCount()>1){
if (viewWinLose == null) {
gameMenu.getChildAt(0).setEnabled(!game.isMulligan());
gameMenu.getChildAt(1).setEnabled(!game.isMulligan());
if (!Forge.isMobileAdventureMode) {
gameMenu.getChildAt(2).setEnabled(!game.isMulligan());
gameMenu.getChildAt(3).setEnabled(false);
}
} else {
gameMenu.getChildAt(0).setEnabled(false);
gameMenu.getChildAt(1).setEnabled(false);
if (!Forge.isMobileAdventureMode) {
gameMenu.getChildAt(2).setEnabled(false);
gameMenu.getChildAt(3).setEnabled(true);
}
}
}
} }
if (devMenu!=null) {
if (devMenu.isVisible()){ if (gameMenu != null) {
if (gameMenu.getChildCount() > 1) {
if (viewWinLose == null) {
gameMenu.getChildAt(0).setEnabled(!game.isMulligan());
gameMenu.getChildAt(1).setEnabled(!game.isMulligan());
if (!Forge.isMobileAdventureMode) {
gameMenu.getChildAt(2).setEnabled(!game.isMulligan());
gameMenu.getChildAt(3).setEnabled(false);
}
} else {
gameMenu.getChildAt(0).setEnabled(false);
gameMenu.getChildAt(1).setEnabled(false);
if (!Forge.isMobileAdventureMode) {
gameMenu.getChildAt(2).setEnabled(false);
gameMenu.getChildAt(3).setEnabled(true);
}
}
}
}
if (devMenu != null) {
if (devMenu.isVisible()) {
try { try {
//rollbackphase enable -- todo limit by gametype? //rollbackphase enable -- todo limit by gametype?
devMenu.getChildAt(2).setEnabled(game.getPlayers().size() == 2 && game.getStack().size() == 0 && !GuiBase.isNetworkplay() && game.getPhase().isMain() && !game.getPlayerTurn().isAI()); devMenu.getChildAt(2).setEnabled(game.getPlayers().size() == 2 && game.getStack().size() == 0 && !GuiBase.isNetworkplay() && game.getPhase().isMain() && !game.getPlayerTurn().isAI());
@@ -384,7 +389,7 @@ public class MatchScreen extends FScreen {
} }
drawArcs(g); drawArcs(g);
if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ENABLE_MAGNIFIER) && Forge.magnify && Forge.magnifyToggle) { if (FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ENABLE_MAGNIFIER) && Forge.magnify && Forge.magnifyToggle) {
if (Forge.isLandscapeMode() && (!GuiBase.isAndroid()||Forge.hasGamepad()) && !CardZoom.isOpen() && potentialListener != null) { if (Forge.isLandscapeMode() && (!GuiBase.isAndroid() || Forge.hasGamepad()) && !CardZoom.isOpen() && potentialListener != null) {
for (FDisplayObject object : potentialListener) { for (FDisplayObject object : potentialListener) {
if (object != null) { if (object != null) {
if (object instanceof FCardPanel) { if (object instanceof FCardPanel) {
@@ -398,24 +403,23 @@ public class MatchScreen extends FScreen {
float cardW = getHeight() * 0.45f; float cardW = getHeight() * 0.45f;
float cardH = FCardPanel.ASPECT_RATIO * cardW; float cardH = FCardPanel.ASPECT_RATIO * cardW;
float cardX = !ZoneType.Battlefield.equals(cardPanel.getCard().getZone()) float cardX = !ZoneType.Battlefield.equals(cardPanel.getCard().getZone())
? cardPanel.screenPos.x-cardW : cardPanel.screenPos.x+(cardPanel.isTapped() ? cardPanel.screenPos.x - cardW : cardPanel.screenPos.x + (cardPanel.isTapped()
? cardPanel.getWidth() : cardPanel.getWidth()/1.4f); ? cardPanel.getWidth() : cardPanel.getWidth() / 1.4f);
if (vPlayerPanel.getSelectedTab() != null && vPlayerPanel.getSelectedTab().isVisible() if (vPlayerPanel.getSelectedTab() != null && vPlayerPanel.getSelectedTab().isVisible()
&& cardX > vPlayerPanel.getSelectedTab().getDisplayArea().getLeft()) { && cardX > vPlayerPanel.getSelectedTab().getDisplayArea().getLeft()) {
cardX = cardPanel.screenPos.x-cardW; cardX = cardPanel.screenPos.x - cardW;
} }
if ((cardX+cardW) > scroller.getWidth()+scroller.getLeft()) if ((cardX + cardW) > scroller.getWidth() + scroller.getLeft())
cardX = cardPanel.screenPos.x-cardW; cardX = cardPanel.screenPos.x - cardW;
if (vPlayerPanel.getCommandZone() != null if (vPlayerPanel.getCommandZone() != null
&& vPlayerPanel.getCommandZone().isVisible() && cardX > vPlayerPanel.getCommandZone().screenPos.x) && vPlayerPanel.getCommandZone().isVisible() && cardX > vPlayerPanel.getCommandZone().screenPos.x)
cardX = cardPanel.screenPos.x-cardW; cardX = cardPanel.screenPos.x - cardW;
float cardY = (cardPanel.screenPos.y-cardH)+cardPanel.getHeight(); float cardY = (cardPanel.screenPos.y - cardH) + cardPanel.getHeight();
if (vPlayerPanel.getPlayer() == bottomPlayerPanel.getPlayer()) { if (vPlayerPanel.getPlayer() == bottomPlayerPanel.getPlayer()) {
cardY = bottomPlayerPrompt.screenPos.y - cardH; cardY = bottomPlayerPrompt.screenPos.y - cardH;
} } else if (cardY < vPlayerPanel.getField().screenPos.y && vPlayerPanel.getPlayer() != bottomPlayerPanel.getPlayer()) {
else if (cardY < vPlayerPanel.getField().screenPos.y && vPlayerPanel.getPlayer() != bottomPlayerPanel.getPlayer()) {
cardY = vPlayerPanel.getField().screenPos.y; cardY = vPlayerPanel.getField().screenPos.y;
if ((cardY+cardH) > bottomPlayerPrompt.screenPos.y) if ((cardY + cardH) > bottomPlayerPrompt.screenPos.y)
cardY = bottomPlayerPrompt.screenPos.y - cardH; cardY = bottomPlayerPrompt.screenPos.y - cardH;
} }
if (Forge.magnifyShowDetails) if (Forge.magnifyShowDetails)
@@ -433,11 +437,11 @@ public class MatchScreen extends FScreen {
if (object.isHovered() && cardView != null && getStack().isVisible()) { if (object.isHovered() && cardView != null && getStack().isVisible()) {
float cardW = getHeight() * 0.45f; float cardW = getHeight() * 0.45f;
float cardH = FCardPanel.ASPECT_RATIO * cardW; float cardH = FCardPanel.ASPECT_RATIO * cardW;
float cardX = object.screenPos.x-cardW-Utils.scale(4); float cardX = object.screenPos.x - cardW - Utils.scale(4);
float cardY = object.screenPos.y-Utils.scale(2); float cardY = object.screenPos.y - Utils.scale(2);
if (cardY < topPlayerPanel.getField().screenPos.y) if (cardY < topPlayerPanel.getField().screenPos.y)
cardY = topPlayerPanel.getField().screenPos.y; cardY = topPlayerPanel.getField().screenPos.y;
if ((cardY+cardH) > bottomPlayerPrompt.screenPos.y) if ((cardY + cardH) > bottomPlayerPrompt.screenPos.y)
cardY = bottomPlayerPrompt.screenPos.y - cardH; cardY = bottomPlayerPrompt.screenPos.y - cardH;
if (Forge.magnifyShowDetails) if (Forge.magnifyShowDetails)
CardImageRenderer.drawDetails(g, cardView, MatchController.instance.getGameView(), false, cardX, cardY, cardW, cardH); CardImageRenderer.drawDetails(g, cardView, MatchController.instance.getGameView(), false, cardX, cardY, cardW, cardH);
@@ -453,6 +457,7 @@ public class MatchScreen extends FScreen {
} }
} }
} }
void drawArcs(Graphics g) { void drawArcs(Graphics g) {
//get all card targeting arrow origins on the battlefield //get all card targeting arrow origins on the battlefield
final Map<Integer, Vector2> endpoints = new HashMap<>(); final Map<Integer, Vector2> endpoints = new HashMap<>();
@@ -483,11 +488,11 @@ public class MatchScreen extends FScreen {
@Override @Override
public boolean keyDown(int keyCode) { public boolean keyDown(int keyCode) {
// TODO: make the keyboard shortcuts configurable on Mobile // TODO: make the keyboard shortcuts configurable on Mobile
if (Forge.hasGamepad() && ((FMenuBar)getHeader()).isShowingMenu(false) && (keyCode == Keys.ESCAPE || keyCode == Keys.ENTER)) if (Forge.hasGamepad() && ((FMenuBar) getHeader()).isShowingMenu(false) && (keyCode == Keys.ESCAPE || keyCode == Keys.ENTER))
return false; return false;
switch (keyCode) { switch (keyCode) {
case Keys.DPAD_DOWN: case Keys.DPAD_DOWN:
if (!((FMenuBar)getHeader()).isShowingMenu(true)) { if (!((FMenuBar) getHeader()).isShowingMenu(true)) {
try { try {
InfoTab selected = selectedPlayerPanel().getSelectedTab(); InfoTab selected = selectedPlayerPanel().getSelectedTab();
if (selected != null && selected.getDisplayArea().isVisible()) { if (selected != null && selected.getDisplayArea().isVisible()) {
@@ -506,11 +511,12 @@ public class MatchScreen extends FScreen {
} }
} }
revalidate(true); revalidate(true);
} catch (Exception e) {} } catch (Exception e) {
}
} }
break; break;
case Keys.DPAD_RIGHT: case Keys.DPAD_RIGHT:
if (!((FMenuBar)getHeader()).isShowingMenu(true)) { if (!((FMenuBar) getHeader()).isShowingMenu(true)) {
try { try {
InfoTab selected = selectedPlayerPanel().getSelectedTab(); InfoTab selected = selectedPlayerPanel().getSelectedTab();
if (selected != null && selected.getDisplayArea().isVisible()) { if (selected != null && selected.getDisplayArea().isVisible()) {
@@ -519,11 +525,12 @@ public class MatchScreen extends FScreen {
selectedPlayerPanel().getSelectedRow().setNextSelected(1); selectedPlayerPanel().getSelectedRow().setNextSelected(1);
} }
revalidate(true); revalidate(true);
} catch (Exception e) {} } catch (Exception e) {
}
} }
break; break;
case Keys.DPAD_UP: case Keys.DPAD_UP:
if (!((FMenuBar)getHeader()).isShowingMenu(true)) { if (!((FMenuBar) getHeader()).isShowingMenu(true)) {
try { try {
InfoTab selected = selectedPlayerPanel().getSelectedTab(); InfoTab selected = selectedPlayerPanel().getSelectedTab();
if (selected != null && selected.getDisplayArea().isVisible()) { if (selected != null && selected.getDisplayArea().isVisible()) {
@@ -542,11 +549,12 @@ public class MatchScreen extends FScreen {
} }
} }
revalidate(true); revalidate(true);
} catch (Exception e) {} } catch (Exception e) {
}
} }
break; break;
case Keys.DPAD_LEFT: case Keys.DPAD_LEFT:
if (!((FMenuBar)getHeader()).isShowingMenu(true)) { if (!((FMenuBar) getHeader()).isShowingMenu(true)) {
try { try {
InfoTab selected = selectedPlayerPanel().getSelectedTab(); InfoTab selected = selectedPlayerPanel().getSelectedTab();
if (selected != null && selected.getDisplayArea().isVisible()) { if (selected != null && selected.getDisplayArea().isVisible()) {
@@ -555,11 +563,12 @@ public class MatchScreen extends FScreen {
selectedPlayerPanel().getSelectedRow().setPreviousSelected(1); selectedPlayerPanel().getSelectedRow().setPreviousSelected(1);
} }
revalidate(true); revalidate(true);
} catch (Exception e) {} } catch (Exception e) {
}
} }
break; break;
case Keys.BUTTON_Y: case Keys.BUTTON_Y:
if (!((FMenuBar)getHeader()).isShowingMenu(true)) { if (!((FMenuBar) getHeader()).isShowingMenu(true)) {
try { try {
InfoTab selected = selectedPlayerPanel().getSelectedTab(); InfoTab selected = selectedPlayerPanel().getSelectedTab();
if (selected != null && selected.getDisplayArea().isVisible()) { if (selected != null && selected.getDisplayArea().isVisible()) {
@@ -567,11 +576,12 @@ public class MatchScreen extends FScreen {
} else { } else {
selectedPlayerPanel().getSelectedRow().showZoom(); selectedPlayerPanel().getSelectedRow().showZoom();
} }
} catch (Exception e) {} } catch (Exception e) {
}
} }
break; break;
case Keys.BUTTON_A: case Keys.BUTTON_A:
if (!((FMenuBar)getHeader()).isShowingMenu(true)) { if (!((FMenuBar) getHeader()).isShowingMenu(true)) {
try { try {
InfoTab selected = selectedPlayerPanel().getSelectedTab(); InfoTab selected = selectedPlayerPanel().getSelectedTab();
if (selected != null && selected.getDisplayArea().isVisible()) { if (selected != null && selected.getDisplayArea().isVisible()) {
@@ -581,7 +591,8 @@ public class MatchScreen extends FScreen {
//nullPotentialListener(); //nullPotentialListener();
selectedPlayerPanel().getSelectedRow().tapChild(); selectedPlayerPanel().getSelectedRow().tapChild();
} }
} catch (Exception e) {} } catch (Exception e) {
}
} }
break; break;
case Keys.BUTTON_L1: //switch selected panels case Keys.BUTTON_L1: //switch selected panels
@@ -590,7 +601,7 @@ public class MatchScreen extends FScreen {
selectedPlayerPanel().hideSelectedTab(); selectedPlayerPanel().hideSelectedTab();
selectedPlayer--; selectedPlayer--;
if (selectedPlayer < 0) if (selectedPlayer < 0)
selectedPlayer=playerPanelsList.size()-1; selectedPlayer = playerPanelsList.size() - 1;
selectedPlayerPanel().closeSelectedTab(); selectedPlayerPanel().closeSelectedTab();
selectedPlayerPanel().getSelectedRow().unselectCurrent(); selectedPlayerPanel().getSelectedRow().unselectCurrent();
//selectedPlayerPanel().setNextSelectedTab(true); //selectedPlayerPanel().setNextSelectedTab(true);
@@ -652,8 +663,7 @@ public class MatchScreen extends FScreen {
if (gui.shouldAlwaysAcceptTrigger(triggerID)) { if (gui.shouldAlwaysAcceptTrigger(triggerID)) {
gui.setShouldAlwaysAskTrigger(triggerID); gui.setShouldAlwaysAskTrigger(triggerID);
} } else {
else {
gui.setShouldAlwaysAcceptTrigger(triggerID); gui.setShouldAlwaysAcceptTrigger(triggerID);
if (stackInstance.equals(gameView.peekStack())) { if (stackInstance.equals(gameView.peekStack())) {
//auto-yes if ability is on top of stack //auto-yes if ability is on top of stack
@@ -686,8 +696,7 @@ public class MatchScreen extends FScreen {
if (gui.shouldAlwaysDeclineTrigger(triggerID)) { if (gui.shouldAlwaysDeclineTrigger(triggerID)) {
gui.setShouldAlwaysAskTrigger(triggerID); gui.setShouldAlwaysAskTrigger(triggerID);
} } else {
else {
gui.setShouldAlwaysDeclineTrigger(triggerID); gui.setShouldAlwaysDeclineTrigger(triggerID);
if (stackInstance.equals(gameView.peekStack())) { if (stackInstance.equals(gameView.peekStack())) {
//auto-no if ability is on top of stack //auto-no if ability is on top of stack
@@ -749,7 +758,7 @@ public class MatchScreen extends FScreen {
public void resetFields() { public void resetFields() {
CardAreaPanel.resetForNewGame(); CardAreaPanel.resetForNewGame();
for (VPlayerPanel playerPanel : getPlayerPanels().values()) { for (VPlayerPanel playerPanel : getPlayerPanels().values()) {
for (CardAreaPanel p : playerPanel.getField().getCardPanels()){ for (CardAreaPanel p : playerPanel.getField().getCardPanels()) {
p.reset(); p.reset();
} }
playerPanel.getZoneTab(ZoneType.Hand).getDisplayArea().clear(); playerPanel.getZoneTab(ZoneType.Hand).getDisplayArea().clear();
@@ -778,22 +787,23 @@ public class MatchScreen extends FScreen {
} }
public Iterable<PlayerZoneUpdate> tempShowZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> zonesToUpdate) { public Iterable<PlayerZoneUpdate> tempShowZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> zonesToUpdate) {
// pfps needs to actually do something // pfps needs to actually do something
return zonesToUpdate; // pfps should return only those zones newly shown return zonesToUpdate; // pfps should return only those zones newly shown
} }
public void hideZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> zonesToUpdate) { public void hideZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> zonesToUpdate) {
// pfps needs to actually do something // pfps needs to actually do something
} }
public void updateSingleCard(final CardView card) { public void updateSingleCard(final CardView card) {
final CardAreaPanel pnl = CardAreaPanel.get(card); final CardAreaPanel pnl = CardAreaPanel.get(card);
if (pnl == null) { return; } if (pnl == null) {
return;
}
final ZoneType zone = card.getZone(); final ZoneType zone = card.getZone();
if (zone != null && zone == ZoneType.Battlefield) { if (zone != null && zone == ZoneType.Battlefield) {
pnl.updateCard(card); pnl.updateCard(card);
} } else { //ensure card not on battlefield is reset such that it no longer thinks it's on the battlefield
else { //ensure card not on battlefield is reset such that it no longer thinks it's on the battlefield
pnl.setTapped(false); pnl.setTapped(false);
pnl.getAttachedPanels().clear(); pnl.getAttachedPanels().clear();
pnl.setAttachedToPanel(null); pnl.setAttachedToPanel(null);
@@ -801,12 +811,14 @@ public class MatchScreen extends FScreen {
pnl.setNextPanelInStack(null); pnl.setNextPanelInStack(null);
} }
} }
private String daytime = null; private String daytime = null;
private Float time = null; private Float time = null;
FSkinTexture currentBG = getBG(); FSkinTexture currentBG = getBG();
FSkinTexture getBG() { FSkinTexture getBG() {
if (Forge.isMobileAdventureMode) { if (Forge.isMobileAdventureMode) {
switch(GameScene.instance().getAdventurePlayerLocation(false)) { switch (GameScene.instance().getAdventurePlayerLocation(false)) {
case "green": case "green":
return FSkinTexture.ADV_BG_FOREST; return FSkinTexture.ADV_BG_FOREST;
case "black": case "black":
@@ -831,6 +843,7 @@ public class MatchScreen extends FScreen {
} }
return FSkinTexture.BG_MATCH; return FSkinTexture.BG_MATCH;
} }
private class BGAnimation extends ForgeAnimation { private class BGAnimation extends ForgeAnimation {
private static final float DURATION = 1.4f; private static final float DURATION = 1.4f;
private float progress = 0; private float progress = 0;
@@ -845,7 +858,7 @@ public class MatchScreen extends FScreen {
percentage = 1; percentage = 1;
} }
if (MatchController.instance.getGameView().isMatchOver()) if (MatchController.instance.getGameView().isMatchOver())
percentage=1; percentage = 1;
if (Forge.isMobileAdventureMode) { if (Forge.isMobileAdventureMode) {
if (percentage < 1) if (percentage < 1)
g.drawNightDay(image, x, y, w, h, time, false, 0); g.drawNightDay(image, x, y, w, h, time, false, 0);
@@ -870,14 +883,14 @@ public class MatchScreen extends FScreen {
if (hasActivePlane()) { if (hasActivePlane()) {
String dt = MatchController.instance.getDayTime() == null ? "" : MatchController.instance.getDayTime(); String dt = MatchController.instance.getDayTime() == null ? "" : MatchController.instance.getDayTime();
if (percentage < 1) if (percentage < 1)
g.drawRipple(image, x, y, w, h, 1-percentage); g.drawRipple(image, x, y, w, h, 1 - percentage);
if ("Day".equalsIgnoreCase(dt)) { if ("Day".equalsIgnoreCase(dt)) {
g.setAlphaComposite(percentage); g.setAlphaComposite(percentage);
g.drawNightDay(image, x, y, w, h, 100f, true, 1-percentage); g.drawNightDay(image, x, y, w, h, 100f, true, 1 - percentage);
g.setAlphaComposite(oldAlpha); g.setAlphaComposite(oldAlpha);
} else if ("Night".equalsIgnoreCase(dt)) { } else if ("Night".equalsIgnoreCase(dt)) {
g.setAlphaComposite(percentage); g.setAlphaComposite(percentage);
g.drawNightDay(image, x, y, w, h, -100f, true, 1-percentage); g.drawNightDay(image, x, y, w, h, -100f, true, 1 - percentage);
g.setAlphaComposite(oldAlpha); g.setAlphaComposite(oldAlpha);
} }
} else { } else {
@@ -925,6 +938,7 @@ public class MatchScreen extends FScreen {
} }
} }
private class FieldScroller extends FScrollPane { private class FieldScroller extends FScrollPane {
private float extraHeight = 0; private float extraHeight = 0;
private String plane = ""; private String plane = "";
@@ -935,12 +949,12 @@ public class MatchScreen extends FScreen {
super.drawBackground(g); super.drawBackground(g);
if (!FModel.getPreferences().getPrefBoolean(FPref.UI_MATCH_IMAGE_VISIBLE)) { if (!FModel.getPreferences().getPrefBoolean(FPref.UI_MATCH_IMAGE_VISIBLE)) {
if (!Forge.isMobileAdventureMode) if (!Forge.isMobileAdventureMode)
if(!hasActivePlane()) if (!hasActivePlane())
return; return;
} }
boolean isGameFast = MatchController.instance.isGameFast(); boolean isGameFast = MatchController.instance.isGameFast();
float midField = topPlayerPanel.getBottom(); float midField = topPlayerPanel.getBottom();
float promptHeight = !Forge.isLandscapeMode() || bottomPlayerPrompt == null ? 0f : bottomPlayerPrompt.getHeight()/1.3f; float promptHeight = !Forge.isLandscapeMode() || bottomPlayerPrompt == null ? 0f : bottomPlayerPrompt.getHeight() / 1.3f;
float x = topPlayerPanel.getField().getLeft(); float x = topPlayerPanel.getField().getLeft();
float y = midField - topPlayerPanel.getField().getHeight() - promptHeight; float y = midField - topPlayerPanel.getField().getHeight() - promptHeight;
float w = getWidth() - x; float w = getWidth() - x;
@@ -998,8 +1012,10 @@ public class MatchScreen extends FScreen {
} }
} }
} }
//auto adjust zoom for local multiplayer landscape mode //auto adjust zoom for local multiplayer landscape mode
List<VPlayerPanel> losers = new ArrayList<>(); List<VPlayerPanel> losers = new ArrayList<>();
@Override @Override
public void drawOverlay(Graphics g) { public void drawOverlay(Graphics g) {
if (Forge.isLandscapeMode()) { if (Forge.isLandscapeMode()) {
@@ -1017,20 +1033,20 @@ public class MatchScreen extends FScreen {
height = p.getAvatar().getHeight(); height = p.getAvatar().getHeight();
p.setVisible(false); p.setVisible(false);
playerPanelsList.remove(p); playerPanelsList.remove(p);
System.out.println("Removed panel: "+p.getPlayer().toString()); System.out.println("Removed panel: " + p.getPlayer().toString());
} }
} }
losers.clear(); losers.clear();
if (playerPanelsList.size() == 2) { if (playerPanelsList.size() == 2) {
//reset avatar size //reset avatar size
for (VPlayerPanel playerPanel : playerPanelsList) { for (VPlayerPanel playerPanel : playerPanelsList) {
float size = playerPanel.getAvatar().getWidth()*2; float size = playerPanel.getAvatar().getWidth() * 2;
playerPanel.getAvatar().setSize(size, size); playerPanel.getAvatar().setSize(size, size);
playerPanel.revalidate(true); playerPanel.revalidate(true);
System.out.println("Panel Resized: "+playerPanel.getPlayer().toString()); System.out.println("Panel Resized: " + playerPanel.getPlayer().toString());
} }
} }
zoom(0,0, height); zoom(0, 0, height);
} }
} }
@@ -1041,7 +1057,7 @@ public class MatchScreen extends FScreen {
//field separator lines //field separator lines
if (!Forge.isLandscapeMode()) { if (!Forge.isLandscapeMode()) {
for (VPlayerPanel playerPanel: playerPanelsList){ for (VPlayerPanel playerPanel : playerPanelsList) {
midField = playerPanel.getTop(); midField = playerPanel.getTop();
y = midField - playerPanel.getField().getHeight(); y = midField - playerPanel.getField().getHeight();
if (playerPanel.getSelectedTab() == null) { if (playerPanel.getSelectedTab() == null) {
@@ -1051,7 +1067,7 @@ public class MatchScreen extends FScreen {
} }
} }
for (VPlayerPanel playerPanel: playerPanelsList){ for (VPlayerPanel playerPanel : playerPanelsList) {
midField = playerPanel.getTop(); midField = playerPanel.getTop();
y = midField - 0.5f; y = midField - 0.5f;
g.drawLine(1, getBorderColor(), x, y, w, y); g.drawLine(1, getBorderColor(), x, y, w, y);
@@ -1066,7 +1082,7 @@ public class MatchScreen extends FScreen {
protected ScrollBounds layoutAndGetScrollBounds(float visibleWidth, float visibleHeight) { protected ScrollBounds layoutAndGetScrollBounds(float visibleWidth, float visibleHeight) {
float totalHeight = visibleHeight + extraHeight; float totalHeight = visibleHeight + extraHeight;
float avatarHeight = VAvatar.HEIGHT; float avatarHeight = VAvatar.HEIGHT;
if (is4Player() || is3Player()){ if (is4Player() || is3Player()) {
avatarHeight *= 0.5f; avatarHeight *= 0.5f;
} }
float playerCount = getPlayerPanels().keySet().size(); float playerCount = getPlayerPanels().keySet().size();
@@ -1154,14 +1170,19 @@ public class MatchScreen extends FScreen {
} }
backupHorzScrollPane(playerPanel.getCommandZone(), x, horzScrollPanes); backupHorzScrollPane(playerPanel.getCommandZone(), x, horzScrollPanes);
} }
private void backupHorzScrollPane(FScrollPane scrollPane, float x, Map<FScrollPane, Pair<Float, Float>> horzScrollPanes) { private void backupHorzScrollPane(FScrollPane scrollPane, float x, Map<FScrollPane, Pair<Float, Float>> horzScrollPanes) {
horzScrollPanes.put(scrollPane, Pair.of(scrollPane.getScrollLeft(), scrollPane.getScrollWidth())); horzScrollPanes.put(scrollPane, Pair.of(scrollPane.getScrollLeft(), scrollPane.getScrollWidth()));
} }
} }
private String getPlaneName(){ return MatchController.instance.getGameView().getPlanarPlayer().getCurrentPlaneName(); }
private boolean hasActivePlane(){ private String getPlaneName() {
if(MatchController.instance.getGameView() != null) return MatchController.instance.getGameView().getPlanarPlayer().getCurrentPlaneName();
if(MatchController.instance.getGameView().getPlanarPlayer() != null) { }
private boolean hasActivePlane() {
if (MatchController.instance.getGameView() != null)
if (MatchController.instance.getGameView().getPlanarPlayer() != null) {
return !MatchController.instance.getGameView().getPlanarPlayer().getCurrentPlaneName().equals(""); return !MatchController.instance.getGameView().getPlanarPlayer().getCurrentPlaneName().equals("");
} }
return false; return false;
@@ -1172,22 +1193,25 @@ public class MatchScreen extends FScreen {
setPotentialListener(listeners); setPotentialListener(listeners);
super.buildTouchListeners(screenX, screenY, listeners); super.buildTouchListeners(screenX, screenY, listeners);
} }
public VPlayerPanel selectedPlayerPanel() { public VPlayerPanel selectedPlayerPanel() {
if (selectedPlayer >= playerPanelsList.size()) if (selectedPlayer >= playerPanelsList.size())
selectedPlayer = playerPanelsList.size()-1; selectedPlayer = playerPanelsList.size() - 1;
if (playerPanelsList.isEmpty()) if (playerPanelsList.isEmpty())
return null; return null;
return playerPanelsList.get(selectedPlayer); return playerPanelsList.get(selectedPlayer);
} }
public static void setPotentialListener(List<FDisplayObject> listener) { public static void setPotentialListener(List<FDisplayObject> listener) {
if (potentialListener != null) if (potentialListener != null)
for (FDisplayObject f: potentialListener) for (FDisplayObject f : potentialListener)
f.setHovered(false); f.setHovered(false);
potentialListener = listener; potentialListener = listener;
} }
public static void nullPotentialListener() { public static void nullPotentialListener() {
if (potentialListener != null) if (potentialListener != null)
for (FDisplayObject f: potentialListener) for (FDisplayObject f : potentialListener)
f.setHovered(false); f.setHovered(false);
potentialListener = null; potentialListener = null;
} }

View File

@@ -11,6 +11,7 @@ import forge.Graphics;
import forge.animation.ForgeAnimation; import forge.animation.ForgeAnimation;
import forge.assets.FImage; import forge.assets.FImage;
import forge.assets.FSkin; import forge.assets.FSkin;
import forge.assets.FSkinColor;
import forge.assets.FSkinFont; import forge.assets.FSkinFont;
import forge.game.card.CounterEnumType; import forge.game.card.CounterEnumType;
import forge.game.player.PlayerView; import forge.game.player.PlayerView;
@@ -153,15 +154,11 @@ public class VAvatar extends FDisplayObject {
float alpha = displayPriority ? 1f : 0.8f; float alpha = displayPriority ? 1f : 0.8f;
if (alphaModifier < 1) if (alphaModifier < 1)
alpha = alphaModifier; alpha = alphaModifier;
g.setAlphaComposite(alpha); g.drawRect(w / 16f, FSkinColor.getStandardColor(Color.CYAN).alphaColor(alpha), 0, 0, w, h);
g.drawRect(w / 16f, Color.CYAN, 0, 0, w, h);
g.setAlphaComposite(oldAlpha);
} }
//priority indicator //priority indicator
if (displayPriority && player.getHasPriority() && alphaModifier == 1) { if (displayPriority && player.getHasPriority() && alphaModifier == 1) {
g.setAlphaComposite(0.6f); g.drawRect(w / 16f, FSkinColor.getStandardColor(Color.LIME).alphaColor(0.6f), 0, 0, w, h);
g.drawRect(w / 16f, Color.LIME, 0, 0, w, h);
g.setAlphaComposite(oldAlpha);
} }
//highlighted //highlighted
if (MatchController.instance.isHighlighted(player)) { if (MatchController.instance.isHighlighted(player)) {

View File

@@ -0,0 +1,159 @@
package forge.screens.match.views;
import com.badlogic.gdx.utils.Align;
import forge.Forge;
import forge.Graphics;
import forge.assets.FImage;
import forge.assets.FSkinColor;
import forge.assets.FSkinFont;
import forge.assets.TextRenderer;
import forge.card.CardRenderer;
import forge.card.CardZoom;
import forge.game.card.CardView;
import forge.gui.card.CardDetailUtil;
import forge.menu.FDropDown;
import forge.screens.match.MatchController;
import forge.toolbox.FDisplayObject;
import forge.toolbox.FLabel;
import forge.trackable.TrackableCollection;
import forge.util.CardTranslation;
import forge.util.Utils;
import java.util.ArrayList;
import java.util.List;
public class VReveal extends FDropDown {
public static final float MARGINS = Utils.scale(4);
private static final FSkinFont FONT = FSkinFont.get(11);
public static final float PADDING = Utils.scale(3);
private TrackableCollection<CardView> revealed;
private static FSkinColor getAltRowColor() {
if (Forge.isMobileAdventureMode)
return FSkinColor.get(FSkinColor.Colors.ADV_CLR_ZEBRA);
return FSkinColor.get(FSkinColor.Colors.CLR_ZEBRA);
}
private static FSkinColor getRowColor() {
return getAltRowColor().darker();
}
private static FSkinColor getForeColor() {
if (Forge.isMobileAdventureMode)
return FSkinColor.get(FSkinColor.Colors.ADV_CLR_TEXT);
return FSkinColor.get(FSkinColor.Colors.CLR_TEXT);
}
private final TextRenderer renderer = new TextRenderer(false);
@Override
protected boolean autoHide() {
return true;
}
@Override
protected void drawBackground(Graphics g) {
float w = getWidth();
float h = getHeight();
g.fillRect(getRowColor(), 0, 0, w, h); //can fill background with main row color since drop down will never be taller than number of rows
}
@Override
protected ScrollBounds updateAndGetPaneSize(float maxWidth, float maxVisibleHeight) {
float x = MARGINS;
float y = MARGINS;
float totalWidth = Forge.getScreenWidth();
float width = totalWidth - 2 * MARGINS;
float entryHeight;
float entryWidth = totalWidth;
float minWidth = 4 * Utils.AVG_FINGER_WIDTH;
if (entryWidth < minWidth) {
entryWidth = minWidth;
}
revealed = MatchController.instance.getGameView().getRevealedCollection();
if (revealed == null || revealed.isEmpty()) {
FLabel label = add(new FLabel.Builder().text("[" + Forge.getLocalizer().getMessage("lblEmpty") + "]").font(FSkinFont.get(11)).align(Align.center).build());
float height = Math.round(label.getAutoSizeBounds().height) + 2 * PADDING;
label.setBounds(x, y, width, height);
return new ScrollBounds(totalWidth, y + height + MARGINS);
} else {
clear();
boolean isAltRow = false;
RevealEntryDisplay revealEntryDisplay;
x = getMenuTab().screenPos.x;
y = 1;
for (CardView c : revealed) {
revealEntryDisplay = add(new RevealEntryDisplay(c, isAltRow));
isAltRow = !isAltRow;
entryHeight = revealEntryDisplay.getMinHeight(entryWidth) + MARGINS;
revealEntryDisplay.setBounds(0, y, entryWidth, entryHeight);
y += entryHeight;
}
}
return new ScrollBounds(totalWidth, y + MARGINS);
}
private class RevealEntryDisplay extends FDisplayObject {
CardView card;
boolean altRow;
String text;
FImage cardArt;
private RevealEntryDisplay(CardView cardView, boolean isAltRow) {
card = cardView;
altRow = isAltRow;
text = CardTranslation.getTranslatedName(card.getCurrentState().getName()) + "\n" + formatType();
cardArt = CardRenderer.getCardArt(cardView);
}
private float getMinHeight(float width) {
width -= 2 * PADDING; //account for left and right insets
float height = renderer.getWrappedBounds("\n", FONT, width).height;
height += 2 * PADDING;
return Math.round(height);
}
@Override
public boolean tap(float x, float y, int count) {
try {
List<CardView> cardViewList = new ArrayList<>(revealed);
int index = cardViewList.indexOf(card);
CardZoom.show(cardViewList, index, null);
} catch (Exception e) {
e.printStackTrace();
}
return true;
}
@Override
public void draw(Graphics g) {
float w = getWidth();
float h = getHeight();
float cardArtWidth = h * 1.302f;
if (altRow) {
g.fillRect(getAltRowColor(), 0, 0, w, h);
}
if (isHovered()) {
g.fillRect(getForeColor().brighter().alphaColor(0.3f), 0, 0, w, h);
}
g.drawImage(cardArt, 0, 0, cardArtWidth, h);
//use full height without padding so text not scaled down
renderer.drawText(g, text, FONT, getForeColor(), cardArtWidth + PADDING, PADDING, w - (2 * PADDING + cardArtWidth), h, 0, h, false, Align.left, false);
}
private String formatType() {
String type = CardDetailUtil.formatCardType(card.getCurrentState(), true);
if (card.getCurrentState().isCreature()) { //include P/T or Loyalty at end of type
type += " (" + card.getCurrentState().getPower() + " / " + card.getCurrentState().getToughness() + ")";
} else if (card.getCurrentState().isPlaneswalker()) {
type += " (" + card.getCurrentState().getLoyalty() + ")";
} else if (card.getCurrentState().getType().hasSubtype("Vehicle")) {
type += String.format(" [%s / %s]", card.getCurrentState().getPower(), card.getCurrentState().getToughness());
}
return type;
}
}
}

View File

@@ -427,9 +427,7 @@ public class FLabel extends FDisplayObject implements IButton {
else if (!text.isEmpty()) { else if (!text.isEmpty()) {
float oldAlpha = g.getfloatAlphaComposite(); float oldAlpha = g.getfloatAlphaComposite();
if (isHovered() && selectable) { if (isHovered() && selectable) {
g.setAlphaComposite(0.4f); g.fillRect(FSkinColor.getStandardColor(Color.GRAY).alphaColor(0.4f), x, y, w, h);
g.fillRect(Color.GRAY, x, y, w, h);
g.setAlphaComposite(oldAlpha);
} }
drawText(g, x, y, w, h, alignment); drawText(g, x, y, w, h, alignment);
} }

View File

@@ -15,7 +15,7 @@ import forge.util.Utils;
public abstract class FScrollPane extends FContainer { public abstract class FScrollPane extends FContainer {
private static final float FLING_DECEL = 750f; private static final float FLING_DECEL = 750f;
private static FSkinColor getIndicatorColor() { public static FSkinColor getIndicatorColor() {
if (Forge.isMobileAdventureMode) if (Forge.isMobileAdventureMode)
return FSkinColor.get(FSkinColor.Colors.ADV_CLR_TEXT).alphaColor(0.7f); return FSkinColor.get(FSkinColor.Colors.ADV_CLR_TEXT).alphaColor(0.7f);
return FSkinColor.get(FSkinColor.Colors.CLR_TEXT).alphaColor(0.7f); return FSkinColor.get(FSkinColor.Colors.CLR_TEXT).alphaColor(0.7f);
@@ -30,6 +30,14 @@ public abstract class FScrollPane extends FContainer {
scrollBounds = new ScrollBounds(); scrollBounds = new ScrollBounds();
} }
public float getIndicatorMargin() {
return INDICATOR_MARGIN;
}
public float getIndicatorSize() {
return INDICATOR_SIZE;
}
public float getScrollLeft() { public float getScrollLeft() {
return scrollLeft; return scrollLeft;
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -9,6 +9,7 @@ import java.util.Set;
import java.util.Timer; import java.util.Timer;
import java.util.TimerTask; import java.util.TimerTask;
import forge.trackable.TrackableCollection;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@@ -50,12 +51,15 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
public final boolean hasLocalPlayers() { public final boolean hasLocalPlayers() {
return !gameControllers.isEmpty(); return !gameControllers.isEmpty();
} }
public final Set<PlayerView> getLocalPlayers() { public final Set<PlayerView> getLocalPlayers() {
return gameControllers.keySet(); return gameControllers.keySet();
} }
public final int getLocalPlayerCount() { public final int getLocalPlayerCount() {
return gameControllers.size(); return gameControllers.size();
} }
public final boolean isLocalPlayer(final PlayerView player) { public final boolean isLocalPlayer(final PlayerView player) {
return gameControllers.containsKey(player); return gameControllers.containsKey(player);
} }
@@ -94,12 +98,15 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
currentPlayer = player; currentPlayer = player;
updateCurrentPlayer(player); updateCurrentPlayer(player);
} }
protected abstract void updateCurrentPlayer(PlayerView player); protected abstract void updateCurrentPlayer(PlayerView player);
private GameView gameView = null; private GameView gameView = null;
public final GameView getGameView() { public final GameView getGameView() {
return gameView; return gameView;
} }
@Override @Override
public void setGameView(final GameView gameView0) { public void setGameView(final GameView gameView0) {
if (gameView == null || gameView0 == null) { if (gameView == null || gameView0 == null) {
@@ -118,6 +125,7 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
public final IGameController getGameController() { public final IGameController getGameController() {
return getGameController(getCurrentPlayer()); return getGameController(getCurrentPlayer());
} }
public final IGameController getGameController(final PlayerView player) { public final IGameController getGameController(final PlayerView player) {
if (player == null) { if (player == null) {
return spectator; return spectator;
@@ -180,6 +188,16 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
updateCards(Collections.singleton(card)); updateCards(Collections.singleton(card));
} }
@Override
public void updateRevealedCards(TrackableCollection<CardView> collection) {
if (gameView != null) {
TrackableCollection<CardView> existing = gameView.getRevealedCollection();
if (existing != null)
collection.addAll(existing);
gameView.updateRevealedCards(collection);
}
}
@Override @Override
public void refreshCardDetails(final Iterable<CardView> cards) { public void refreshCardDetails(final Iterable<CardView> cards) {
//not needed for base game implementation //not needed for base game implementation
@@ -199,7 +217,7 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
if (gameView != null && gameView.isGameOver()) { if (gameView != null && gameView.isGameOver()) {
return true; return true;
} }
if (spectator!=null) { //workaround fix!! this is needed on above code or it will if (spectator != null) { //workaround fix!! this is needed on above code or it will
for (Map.Entry<PlayerView, IGameController> e : gameControllers.entrySet()) { for (Map.Entry<PlayerView, IGameController> e : gameControllers.entrySet()) {
if (e.getValue().equals(spectator)) { if (e.getValue().equals(spectator)) {
gameControllers.remove(e.getKey()); gameControllers.remove(e.getKey());
@@ -212,7 +230,7 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
if (getGameController().mayLookAtAllCards()) { // when it bugged here, the game thinks the spectator (null) if (getGameController().mayLookAtAllCards()) { // when it bugged here, the game thinks the spectator (null)
return true; // is the humancontroller here (maybe because there is an existing game thread???) return true; // is the humancontroller here (maybe because there is an existing game thread???)
} }
} catch (NullPointerException e){ } catch (NullPointerException e) {
return true; // return true so it will work as normal return true; // return true so it will work as normal
} }
} else { } else {
@@ -225,10 +243,14 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
@Override @Override
public boolean mayFlip(final CardView cv) { public boolean mayFlip(final CardView cv) {
if (cv == null) { return false; } if (cv == null) {
return false;
}
final CardStateView altState = cv.getAlternateState(); final CardStateView altState = cv.getAlternateState();
if (altState == null) { return false; } if (altState == null) {
return false;
}
switch (altState.getState()) { switch (altState.getState()) {
case Original: case Original:
@@ -252,6 +274,7 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
} }
private final Set<PlayerView> highlightedPlayers = Sets.newHashSet(); private final Set<PlayerView> highlightedPlayers = Sets.newHashSet();
@Override @Override
public void setHighlighted(final PlayerView pv, final boolean b) { public void setHighlighted(final PlayerView pv, final boolean b) {
final boolean hasChanged = b ? highlightedPlayers.add(pv) : highlightedPlayers.remove(pv); final boolean hasChanged = b ? highlightedPlayers.add(pv) : highlightedPlayers.remove(pv);
@@ -265,6 +288,7 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
} }
private final Set<CardView> highlightedCards = Sets.newHashSet(); private final Set<CardView> highlightedCards = Sets.newHashSet();
// used to highlight cards in UI // used to highlight cards in UI
@Override @Override
public void setUsedToPay(final CardView card, final boolean value) { public void setUsedToPay(final CardView card, final boolean value) {
@@ -279,34 +303,56 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
} }
private final Set<CardView> selectableCards = Sets.newHashSet(); private final Set<CardView> selectableCards = Sets.newHashSet();
public void setSelectables(final Iterable<CardView> cards) { public void setSelectables(final Iterable<CardView> cards) {
for (CardView cv : cards) { selectableCards.add(cv); } for (CardView cv : cards) {
selectableCards.add(cv);
}
} }
public void clearSelectables() { public void clearSelectables() {
selectableCards.clear(); selectableCards.clear();
} }
public boolean isSelectable(final CardView card) { public boolean isSelectable(final CardView card) {
return selectableCards.contains(card); return selectableCards.contains(card);
} }
public boolean isSelecting() { public boolean isSelecting() {
return !selectableCards.isEmpty(); return !selectableCards.isEmpty();
} }
public boolean isGamePaused() { return gamePause; }
public boolean isGameFast() { return gameSpeed; } public boolean isGamePaused() {
public void setgamePause(boolean pause) { gamePause = pause; } return gamePause;
public void setGameSpeed(boolean isFast) { gameSpeed = isFast; } }
public boolean isGameFast() {
return gameSpeed;
}
public void setgamePause(boolean pause) {
gamePause = pause;
}
public void setGameSpeed(boolean isFast) {
gameSpeed = isFast;
}
public void pauseMatch() { public void pauseMatch() {
IGameController controller = spectator; IGameController controller = spectator;
if (controller != null && !isGamePaused()) if (controller != null && !isGamePaused())
controller.selectButtonOk(); controller.selectButtonOk();
} }
public void resumeMatch() { public void resumeMatch() {
IGameController controller = spectator; IGameController controller = spectator;
if (controller != null && isGamePaused()) if (controller != null && isGamePaused())
controller.selectButtonOk(); controller.selectButtonOk();
} }
/** Concede game, bring up WinLose UI. */ /**
* Concede game, bring up WinLose UI.
*/
public boolean concede() { public boolean concede() {
if (gameView.isGameOver()) { if (gameView.isGameOver()) {
return true; return true;
@@ -346,11 +392,9 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
} }
ignoreConcedeChain = false; ignoreConcedeChain = false;
return false; return false;
} } else if (spectator == null) {
else if (spectator == null) {
return true; //if no local players or spectator, just quit return true; //if no local players or spectator, just quit
} } else {
else {
if (showConfirmDialog(Localizer.getInstance().getMessage("lblCloseGameSpectator"), Localizer.getInstance().getMessage("lblCloseGame"), Localizer.getInstance().getMessage("lblClose"), Localizer.getInstance().getMessage("lblCancel"))) { if (showConfirmDialog(Localizer.getInstance().getMessage("lblCloseGameSpectator"), Localizer.getInstance().getMessage("lblCloseGame"), Localizer.getInstance().getMessage("lblClose"), Localizer.getInstance().getMessage("lblCancel"))) {
IGameController controller = spectator; IGameController controller = spectator;
spectator = null; //ensure we don't prompt again, including when calling nextGameDecision below spectator = null; //ensure we don't prompt again, including when calling nextGameDecision below
@@ -421,14 +465,11 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
awaitNextInputTask = new TimerTask() { awaitNextInputTask = new TimerTask() {
@Override @Override
public void run() { public void run() {
FThreads.invokeInEdtLater(new Runnable() { FThreads.invokeInEdtLater(() -> {
@Override synchronized (awaitNextInputTimer) {
public void run() { if (awaitNextInputTask != null) {
synchronized (awaitNextInputTimer) { updatePromptForAwait(getCurrentPlayer());
if (awaitNextInputTask != null) { awaitNextInputTask = null;
updatePromptForAwait(getCurrentPlayer());
awaitNextInputTask = null;
}
} }
} }
}); });
@@ -451,7 +492,8 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
if (awaitNextInputTask != null) { if (awaitNextInputTask != null) {
try { try {
awaitNextInputTask.cancel(); //cancel timer once next input shown if needed awaitNextInputTask.cancel(); //cancel timer once next input shown if needed
} catch (final Exception ex) {} //suppress any exception thrown by cancel() } catch (final Exception ex) {
} //suppress any exception thrown by cancel()
awaitNextInputTask = null; awaitNextInputTask = null;
} }
} }
@@ -470,9 +512,11 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
// Abilities to auto-yield to // Abilities to auto-yield to
private final Set<String> autoYields = Sets.newHashSet(); private final Set<String> autoYields = Sets.newHashSet();
public final Iterable<String> getAutoYields() { public final Iterable<String> getAutoYields() {
return autoYields; return autoYields;
} }
@Override @Override
public final boolean shouldAutoYield(final String key) { public final boolean shouldAutoYield(final String key) {
String abilityKey = key.indexOf("): ") != -1 ? key.substring(key.indexOf("): ") + 3) : key; String abilityKey = key.indexOf("): ") != -1 ? key.substring(key.indexOf("): ") + 3) : key;
@@ -480,6 +524,7 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
return !getDisableAutoYields() && autoYields.contains(yieldPerAbility ? abilityKey : key); return !getDisableAutoYields() && autoYields.contains(yieldPerAbility ? abilityKey : key);
} }
@Override @Override
public final void setShouldAutoYield(final String key, final boolean autoYield) { public final void setShouldAutoYield(final String key, final boolean autoYield) {
String abilityKey = key.indexOf("): ") != -1 ? key.substring(key.indexOf("): ") + 3) : key; String abilityKey = key.indexOf("): ") != -1 ? key.substring(key.indexOf("): ") + 3) : key;
@@ -487,16 +532,17 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
if (autoYield) { if (autoYield) {
autoYields.add(yieldPerAbility ? abilityKey : key); autoYields.add(yieldPerAbility ? abilityKey : key);
} } else {
else {
autoYields.remove(yieldPerAbility ? abilityKey : key); autoYields.remove(yieldPerAbility ? abilityKey : key);
} }
} }
private boolean disableAutoYields; private boolean disableAutoYields;
public final boolean getDisableAutoYields() { public final boolean getDisableAutoYields() {
return disableAutoYields; return disableAutoYields;
} }
public final void setDisableAutoYields(final boolean b0) { public final void setDisableAutoYields(final boolean b0) {
disableAutoYields = b0; disableAutoYields = b0;
} }
@@ -511,16 +557,29 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
private final Map<Integer, Boolean> triggersAlwaysAccept = Maps.newTreeMap(); private final Map<Integer, Boolean> triggersAlwaysAccept = Maps.newTreeMap();
@Override @Override
public final boolean shouldAlwaysAcceptTrigger(final int trigger) { return Boolean.TRUE.equals(triggersAlwaysAccept.get(Integer.valueOf(trigger))); } public final boolean shouldAlwaysAcceptTrigger(final int trigger) {
@Override return Boolean.TRUE.equals(triggersAlwaysAccept.get(Integer.valueOf(trigger)));
public final boolean shouldAlwaysDeclineTrigger(final int trigger) { return Boolean.FALSE.equals(triggersAlwaysAccept.get(Integer.valueOf(trigger))); } }
@Override @Override
public final void setShouldAlwaysAcceptTrigger(final int trigger) { triggersAlwaysAccept.put(Integer.valueOf(trigger), Boolean.TRUE); } public final boolean shouldAlwaysDeclineTrigger(final int trigger) {
return Boolean.FALSE.equals(triggersAlwaysAccept.get(Integer.valueOf(trigger)));
}
@Override @Override
public final void setShouldAlwaysDeclineTrigger(final int trigger) { triggersAlwaysAccept.put(Integer.valueOf(trigger), Boolean.FALSE); } public final void setShouldAlwaysAcceptTrigger(final int trigger) {
triggersAlwaysAccept.put(Integer.valueOf(trigger), Boolean.TRUE);
}
@Override @Override
public final void setShouldAlwaysAskTrigger(final int trigger) { triggersAlwaysAccept.remove(Integer.valueOf(trigger)); } public final void setShouldAlwaysDeclineTrigger(final int trigger) {
triggersAlwaysAccept.put(Integer.valueOf(trigger), Boolean.FALSE);
}
@Override
public final void setShouldAlwaysAskTrigger(final int trigger) {
triggersAlwaysAccept.remove(Integer.valueOf(trigger));
}
// End of Triggers preliminary choice // End of Triggers preliminary choice
@@ -529,15 +588,12 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
/** /**
* Convenience for getChoices(message, 0, 1, choices). * Convenience for getChoices(message, 0, 1, choices).
* *
* @param <T> * @param <T> is automatically inferred.
* is automatically inferred. * @param message a {@link java.lang.String} object.
* @param message * @param choices a T object.
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return null if choices is missing, empty, or if the users' choices are * @return null if choices is missing, empty, or if the users' choices are
* empty; otherwise, returns the first item in the List returned by * empty; otherwise, returns the first item in the List returned by
* getChoices. * getChoices.
* @see #getChoices(String, int, int, List) * @see #getChoices(String, int, int, List)
*/ */
@Override @Override
@@ -550,17 +606,15 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
} }
// returned Object will never be null // returned Object will never be null
/** /**
* <p> * <p>
* getChoice. * getChoice.
* </p> * </p>
* *
* @param <T> * @param <T> a T object.
* a T object. * @param message a {@link java.lang.String} object.
* @param message * @param choices a T object.
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return a T object. * @return a T object.
*/ */
@Override @Override
@@ -588,13 +642,17 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
public Integer getInteger(final String message, final int min) { public Integer getInteger(final String message, final int min) {
return getInteger(message, min, Integer.MAX_VALUE, false); return getInteger(message, min, Integer.MAX_VALUE, false);
} }
@Override @Override
public Integer getInteger(final String message, final int min, final int max) { public Integer getInteger(final String message, final int min, final int max) {
return getInteger(message, min, max, false); return getInteger(message, min, max, false);
} }
@Override @Override
public Integer getInteger(final String message, final int min, final int max, final boolean sortDesc) { public Integer getInteger(final String message, final int min, final int max, final boolean sortDesc) {
if (max <= min) { return min; } //just return min if max <= min if (max <= min) {
return min;
} //just return min if max <= min
//force cutting off after 100 numbers at most //force cutting off after 100 numbers at most
if (max == Integer.MAX_VALUE) { if (max == Integer.MAX_VALUE) {
@@ -654,7 +712,9 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
while (true) { while (true) {
final String str = showInputDialog(prompt, message); final String str = showInputDialog(prompt, message);
if (str == null) { return null; } // that is 'cancel' if (str == null) {
return null;
} // that is 'cancel'
if (StringUtils.isNumeric(str)) { if (StringUtils.isNumeric(str)) {
final Integer val = Integer.valueOf(str); final Integer val = Integer.valueOf(str);
@@ -696,8 +756,8 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
* current implementation requires the user to cancel in order to get the * current implementation requires the user to cancel in order to get the
* new item to be the first item in the resulting list. * new item to be the first item in the resulting list.
* *
* @param title the dialog title. * @param title the dialog title.
* @param newItem the object to insert. * @param newItem the object to insert.
* @param oldItems the list of objects. * @param oldItems the list of objects.
* @return A shallow copy of the list of objects, with newItem inserted. * @return A shallow copy of the list of objects, with newItem inserted.
*/ */
@@ -753,24 +813,24 @@ public abstract class AbstractGuiGame implements IGuiGame, IMayViewCards {
@Override @Override
public boolean showConfirmDialog(final String message, final String title, public boolean showConfirmDialog(final String message, final String title,
final boolean defaultYes) { final boolean defaultYes) {
return showConfirmDialog(message, title, Localizer.getInstance().getMessage("lblYes"), Localizer.getInstance().getMessage("lblNo")); return showConfirmDialog(message, title, Localizer.getInstance().getMessage("lblYes"), Localizer.getInstance().getMessage("lblNo"));
} }
@Override @Override
public boolean showConfirmDialog(final String message, final String title, public boolean showConfirmDialog(final String message, final String title,
final String yesButtonText, final String noButtonText) { final String yesButtonText, final String noButtonText) {
return showConfirmDialog(message, title, yesButtonText, noButtonText, true); return showConfirmDialog(message, title, yesButtonText, noButtonText, true);
} }
@Override @Override
public void notifyStackAddition(GameEventSpellAbilityCast event) { public void notifyStackAddition(GameEventSpellAbilityCast event) {
} }
@Override @Override
public void notifyStackRemoval(GameEventSpellRemovedFromStack event) { public void notifyStackRemoval(GameEventSpellRemovedFromStack event) {
} }
@Override @Override
public void handleLandPlayed(Card land) { public void handleLandPlayed(Card land) {
} }

View File

@@ -31,90 +31,142 @@ import forge.util.ITriggerEvent;
public interface IGuiGame { public interface IGuiGame {
void setGameView(GameView gameView); void setGameView(GameView gameView);
GameView getGameView(); GameView getGameView();
void setOriginalGameController(PlayerView view, IGameController gameController); void setOriginalGameController(PlayerView view, IGameController gameController);
void setGameController(PlayerView player, IGameController gameController); void setGameController(PlayerView player, IGameController gameController);
void setSpectator(IGameController spectator); void setSpectator(IGameController spectator);
void openView(TrackableCollection<PlayerView> myPlayers); void openView(TrackableCollection<PlayerView> myPlayers);
void afterGameEnd(); void afterGameEnd();
void showCombat(); void showCombat();
void showPromptMessage(PlayerView playerView, String message); void showPromptMessage(PlayerView playerView, String message);
void showCardPromptMessage(PlayerView playerView, String message, CardView card); void showCardPromptMessage(PlayerView playerView, String message, CardView card);
void updateButtons(PlayerView owner, boolean okEnabled, boolean cancelEnabled, boolean focusOk); void updateButtons(PlayerView owner, boolean okEnabled, boolean cancelEnabled, boolean focusOk);
void updateButtons(PlayerView owner, String label1, String label2, boolean enable1, boolean enable2, boolean focus1); void updateButtons(PlayerView owner, String label1, String label2, boolean enable1, boolean enable2, boolean focus1);
void flashIncorrectAction(); void flashIncorrectAction();
void alertUser(); void alertUser();
void updatePhase(boolean saveState); void updatePhase(boolean saveState);
void updateTurn(PlayerView player); void updateTurn(PlayerView player);
void updatePlayerControl(); void updatePlayerControl();
void enableOverlay(); void enableOverlay();
void disableOverlay(); void disableOverlay();
void finishGame(); void finishGame();
void showManaPool(PlayerView player); void showManaPool(PlayerView player);
void hideManaPool(PlayerView player); void hideManaPool(PlayerView player);
void updateStack(); void updateStack();
void notifyStackAddition(final GameEventSpellAbilityCast event); void notifyStackAddition(final GameEventSpellAbilityCast event);
void notifyStackRemoval(final GameEventSpellRemovedFromStack event); void notifyStackRemoval(final GameEventSpellRemovedFromStack event);
void handleLandPlayed(Card land); void handleLandPlayed(Card land);
Iterable<PlayerZoneUpdate> tempShowZones(PlayerView controller, Iterable<PlayerZoneUpdate> zonesToUpdate); Iterable<PlayerZoneUpdate> tempShowZones(PlayerView controller, Iterable<PlayerZoneUpdate> zonesToUpdate);
void hideZones(PlayerView controller, Iterable<PlayerZoneUpdate> zonesToUpdate); void hideZones(PlayerView controller, Iterable<PlayerZoneUpdate> zonesToUpdate);
void updateZones(Iterable<PlayerZoneUpdate> zonesToUpdate); void updateZones(Iterable<PlayerZoneUpdate> zonesToUpdate);
void updateSingleCard(CardView card); void updateSingleCard(CardView card);
void updateCards(Iterable<CardView> cards); void updateCards(Iterable<CardView> cards);
void updateRevealedCards(TrackableCollection<CardView> collection);
void refreshCardDetails(Iterable<CardView> cards); void refreshCardDetails(Iterable<CardView> cards);
void refreshField(); void refreshField();
GameState getGamestate(); GameState getGamestate();
void updateManaPool(Iterable<PlayerView> manaPoolUpdate); void updateManaPool(Iterable<PlayerView> manaPoolUpdate);
void updateLives(Iterable<PlayerView> livesUpdate); void updateLives(Iterable<PlayerView> livesUpdate);
void setPanelSelection(CardView hostCard); void setPanelSelection(CardView hostCard);
SpellAbilityView getAbilityToPlay(CardView hostCard, List<SpellAbilityView> abilities, ITriggerEvent triggerEvent); SpellAbilityView getAbilityToPlay(CardView hostCard, List<SpellAbilityView> abilities, ITriggerEvent triggerEvent);
Map<CardView, Integer> assignCombatDamage(CardView attacker, List<CardView> blockers, int damage, GameEntityView defender, boolean overrideOrder, boolean maySkip); Map<CardView, Integer> assignCombatDamage(CardView attacker, List<CardView> blockers, int damage, GameEntityView defender, boolean overrideOrder, boolean maySkip);
// The Object passed should be GameEntityView for most case. Can be Byte for "generate mana of any combination" effect // The Object passed should be GameEntityView for most case. Can be Byte for "generate mana of any combination" effect
Map<Object, Integer> assignGenericAmount(CardView effectSource, Map<Object, Integer> target, int amount, final boolean atLeastOne, final String amountLabel); Map<Object, Integer> assignGenericAmount(CardView effectSource, Map<Object, Integer> target, int amount, final boolean atLeastOne, final String amountLabel);
void message(String message); void message(String message);
void message(String message, String title); void message(String message, String title);
void showErrorDialog(String message); void showErrorDialog(String message);
void showErrorDialog(String message, String title); void showErrorDialog(String message, String title);
boolean showConfirmDialog(String message, String title); boolean showConfirmDialog(String message, String title);
boolean showConfirmDialog(String message, String title, boolean defaultYes); boolean showConfirmDialog(String message, String title, boolean defaultYes);
boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText); boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText);
boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText, boolean defaultYes); boolean showConfirmDialog(String message, String title, String yesButtonText, String noButtonText, boolean defaultYes);
int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption); int showOptionDialog(String message, String title, FSkinProp icon, List<String> options, int defaultOption);
String showInputDialog(String message, String title); String showInputDialog(String message, String title);
String showInputDialog(String message, String title, FSkinProp icon); String showInputDialog(String message, String title, FSkinProp icon);
String showInputDialog(String message, String title, FSkinProp icon, String initialInput); String showInputDialog(String message, String title, FSkinProp icon, String initialInput);
String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions); String showInputDialog(String message, String title, FSkinProp icon, String initialInput, List<String> inputOptions);
boolean confirm(CardView c, String question); boolean confirm(CardView c, String question);
boolean confirm(CardView c, String question, List<String> options); boolean confirm(CardView c, String question, List<String> options);
boolean confirm(CardView c, String question, boolean defaultIsYes, List<String> options); boolean confirm(CardView c, String question, boolean defaultIsYes, List<String> options);
<T> List<T> getChoices(String message, int min, int max, List<T> choices); <T> List<T> getChoices(String message, int min, int max, List<T> choices);
<T> List<T> getChoices(String message, int min, int max, List<T> choices, T selected, Function<T, String> display); <T> List<T> getChoices(String message, int min, int max, List<T> choices, T selected, Function<T, String> display);
// Get Integer in range // Get Integer in range
Integer getInteger(String message, int min); Integer getInteger(String message, int min);
Integer getInteger(String message, int min, int max); Integer getInteger(String message, int min, int max);
Integer getInteger(String message, int min, int max, boolean sortDesc); Integer getInteger(String message, int min, int max, boolean sortDesc);
Integer getInteger(String message, int min, int max, int cutoff); Integer getInteger(String message, int min, int max, int cutoff);
/** /**
* Convenience for getChoices(message, 0, 1, choices). * Convenience for getChoices(message, 0, 1, choices).
* *
* @param <T> * @param <T> is automatically inferred.
* is automatically inferred. * @param message a {@link java.lang.String} object.
* @param message * @param choices a T object.
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return null if choices is missing, empty, or if the users' choices are * @return null if choices is missing, empty, or if the users' choices are
* empty; otherwise, returns the first item in the List returned by * empty; otherwise, returns the first item in the List returned by
* getChoices. * getChoices.
*/ */
<T> T oneOrNone(String message, List<T> choices); <T> T oneOrNone(String message, List<T> choices);
@@ -123,12 +175,9 @@ public interface IGuiGame {
* getChoice. * getChoice.
* </p> * </p>
* *
* @param <T> * @param <T> a T object.
* a T object. * @param message a {@link java.lang.String} object.
* @param message * @param choices a T object.
* a {@link java.lang.String} object.
* @param choices
* a T object.
* @return One of {@code choices}. Can only be {@code null} if {@code choices} is empty. * @return One of {@code choices}. Can only be {@code null} if {@code choices} is empty.
*/ */
<T> T one(String message, List<T> choices); <T> T one(String message, List<T> choices);
@@ -136,9 +185,11 @@ public interface IGuiGame {
<T> void reveal(String message, List<T> items); <T> void reveal(String message, List<T> items);
<T> List<T> many(String title, String topCaption, int cnt, List<T> sourceChoices, CardView c); <T> List<T> many(String title, String topCaption, int cnt, List<T> sourceChoices, CardView c);
<T> List<T> many(String title, String topCaption, int min, int max, List<T> sourceChoices, CardView c); <T> List<T> many(String title, String topCaption, int min, int max, List<T> sourceChoices, CardView c);
<T> List<T> order(String title, String top, List<T> sourceChoices, CardView c); <T> List<T> order(String title, String top, List<T> sourceChoices, CardView c);
<T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices, CardView referenceCard, boolean sideboardingMode); <T> List<T> order(String title, String top, int remainingObjectsMin, int remainingObjectsMax, List<T> sourceChoices, List<T> destChoices, CardView referenceCard, boolean sideboardingMode);
/** /**
@@ -146,53 +197,78 @@ public interface IGuiGame {
* current implementation requires the user to cancel in order to get the * current implementation requires the user to cancel in order to get the
* new item to be the first item in the resulting list. * new item to be the first item in the resulting list.
* *
* @param title * @param title the dialog title.
* the dialog title. * @param newItem the object to insert.
* @param newItem * @param oldItems the list of objects.
* the object to insert.
* @param oldItems
* the list of objects.
* @return A shallow copy of the list of objects, with newItem inserted. * @return A shallow copy of the list of objects, with newItem inserted.
*/ */
<T> List<T> insertInList(String title, T newItem, List<T> oldItems); <T> List<T> insertInList(String title, T newItem, List<T> oldItems);
List<PaperCard> sideboard(CardPool sideboard, CardPool main, String message); List<PaperCard> sideboard(CardPool sideboard, CardPool main, String message);
GameEntityView chooseSingleEntityForEffect(String title, List<? extends GameEntityView> optionList, DelayedReveal delayedReveal, boolean isOptional); GameEntityView chooseSingleEntityForEffect(String title, List<? extends GameEntityView> optionList, DelayedReveal delayedReveal, boolean isOptional);
List<GameEntityView> chooseEntitiesForEffect(String title, List<? extends GameEntityView> optionList, int min, int max, DelayedReveal delayedReveal); List<GameEntityView> chooseEntitiesForEffect(String title, List<? extends GameEntityView> optionList, int min, int max, DelayedReveal delayedReveal);
// show a list of cards and allow some of them to be moved around and return new list // show a list of cards and allow some of them to be moved around and return new list
List<CardView> manipulateCardList(String title, final Iterable<CardView> cards, final Iterable<CardView> manipulable, boolean toTop, boolean toBottom, boolean toAnywhere); List<CardView> manipulateCardList(String title, final Iterable<CardView> cards, final Iterable<CardView> manipulable, boolean toTop, boolean toBottom, boolean toAnywhere);
void setCard(CardView card); void setCard(CardView card);
void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi); void setPlayerAvatar(LobbyPlayer player, IHasIcon ihi);
PlayerZoneUpdates openZones(PlayerView controller, Collection<ZoneType> zones, Map<PlayerView, Object> players, boolean backupLastZones); PlayerZoneUpdates openZones(PlayerView controller, Collection<ZoneType> zones, Map<PlayerView, Object> players, boolean backupLastZones);
void restoreOldZones(PlayerView playerView, PlayerZoneUpdates playerZoneUpdates); void restoreOldZones(PlayerView playerView, PlayerZoneUpdates playerZoneUpdates);
void setHighlighted(PlayerView pv, boolean b); void setHighlighted(PlayerView pv, boolean b);
void setUsedToPay(CardView card, boolean value); void setUsedToPay(CardView card, boolean value);
void setSelectables(final Iterable<CardView> cards); void setSelectables(final Iterable<CardView> cards);
void clearSelectables(); void clearSelectables();
boolean isSelecting(); boolean isSelecting();
boolean isGamePaused(); boolean isGamePaused();
void setgamePause(boolean pause); void setgamePause(boolean pause);
void setGameSpeed(boolean gameSpeed); void setGameSpeed(boolean gameSpeed);
String getDayTime(); String getDayTime();
void updateDayTime(String daytime); void updateDayTime(String daytime);
void awaitNextInput(); void awaitNextInput();
void cancelAwaitNextInput(); void cancelAwaitNextInput();
boolean isUiSetToSkipPhase(PlayerView playerTurn, PhaseType phase); boolean isUiSetToSkipPhase(PlayerView playerTurn, PhaseType phase);
void autoPassUntilEndOfTurn(PlayerView player); void autoPassUntilEndOfTurn(PlayerView player);
boolean mayAutoPass(PlayerView player); boolean mayAutoPass(PlayerView player);
void autoPassCancel(PlayerView player); void autoPassCancel(PlayerView player);
void updateAutoPassPrompt(); void updateAutoPassPrompt();
boolean shouldAutoYield(String key); boolean shouldAutoYield(String key);
void setShouldAutoYield(String key, boolean autoYield); void setShouldAutoYield(String key, boolean autoYield);
boolean shouldAlwaysAcceptTrigger(int trigger); boolean shouldAlwaysAcceptTrigger(int trigger);
boolean shouldAlwaysDeclineTrigger(int trigger); boolean shouldAlwaysDeclineTrigger(int trigger);
void setShouldAlwaysAcceptTrigger(int trigger); void setShouldAlwaysAcceptTrigger(int trigger);
void setShouldAlwaysDeclineTrigger(int trigger); void setShouldAlwaysDeclineTrigger(int trigger);
void setShouldAlwaysAskTrigger(int trigger); void setShouldAlwaysAskTrigger(int trigger);
void clearAutoYields(); void clearAutoYields();
void setCurrentPlayer(PlayerView player); void setCurrentPlayer(PlayerView player);

View File

@@ -328,6 +328,9 @@ public enum FSkinProp {
ICO_FAVICON (new int[] {0, 640, 80, 80}, PropType.ICON), ICO_FAVICON (new int[] {0, 640, 80, 80}, PropType.ICON),
ICO_LOCK (new int[] {620, 800, 48, 48}, PropType.ICON), ICO_LOCK (new int[] {620, 800, 48, 48}, PropType.ICON),
//reveal icons
ICO_SEE (new int[] {568, 1520, 60, 40}, PropType.ICON),
ICO_UNSEE (new int[] {568, 1560, 60, 40}, PropType.ICON),
//layout images //layout images
IMG_HANDLE (new int[] {320, 450, 80, 20}, PropType.IMAGE), IMG_HANDLE (new int[] {320, 450, 80, 20}, PropType.IMAGE),

View File

@@ -19,6 +19,7 @@ import java.util.Map.Entry;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.TreeSet; import java.util.TreeSet;
import forge.trackable.TrackableCollection;
import forge.util.ImageUtil; import forge.util.ImageUtil;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.Range; import org.apache.commons.lang3.Range;
@@ -148,7 +149,7 @@ import io.sentry.Sentry;
/** /**
* A prototype for player controller class * A prototype for player controller class
* * <p>
* Handles phase skips for now. * Handles phase skips for now.
*/ */
public class PlayerControllerHuman extends PlayerController implements IGameController { public class PlayerControllerHuman extends PlayerController implements IGameController {
@@ -258,8 +259,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
* Set this to {@code true} to enable this player to see all cards any other * Set this to {@code true} to enable this player to see all cards any other
* player can see. * player can see.
* *
* @param mayLookAtAllCards * @param mayLookAtAllCards the mayLookAtAllCards to set
* the mayLookAtAllCards to set
*/ */
public void setMayLookAtAllCards(final boolean mayLookAtAllCards) { public void setMayLookAtAllCards(final boolean mayLookAtAllCards) {
this.mayLookAtAllCards = mayLookAtAllCards; this.mayLookAtAllCards = mayLookAtAllCards;
@@ -271,7 +271,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
*/ */
@Override @Override
public SpellAbility getAbilityToPlay(final Card hostCard, final List<SpellAbility> abilities, public SpellAbility getAbilityToPlay(final Card hostCard, final List<SpellAbility> abilities,
final ITriggerEvent triggerEvent) { final ITriggerEvent triggerEvent) {
// make sure another human player can't choose opponents cards just because he might see them // make sure another human player can't choose opponents cards just because he might see them
if (triggerEvent != null && !hostCard.isInPlay() && !hostCard.getOwner().equals(player) && if (triggerEvent != null && !hostCard.isInPlay() && !hostCard.getOwner().equals(player) &&
!hostCard.getController().equals(player) && !hostCard.getController().equals(player) &&
@@ -355,15 +355,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public Map<Card, Integer> assignCombatDamage(final Card attacker, final CardCollectionView blockers, final CardCollectionView remaining, public Map<Card, Integer> assignCombatDamage(final Card attacker, final CardCollectionView blockers, final CardCollectionView remaining,
final int damageDealt, final GameEntity defender, final boolean overrideOrder) { final int damageDealt, final GameEntity defender, final boolean overrideOrder) {
// Attacker is a poor name here, since the creature assigning damage // Attacker is a poor name here, since the creature assigning damage
// could just as easily be the blocker. // could just as easily be the blocker.
final Map<Card, Integer> map = Maps.newHashMap(); final Map<Card, Integer> map = Maps.newHashMap();
if ((attacker.hasKeyword(Keyword.TRAMPLE) && defender != null) || (blockers.size() > 1) if ((attacker.hasKeyword(Keyword.TRAMPLE) && defender != null) || (blockers.size() > 1)
|| ((attacker.hasKeyword("You may assign CARDNAME's combat damage divided as you choose among " + || ((attacker.hasKeyword("You may assign CARDNAME's combat damage divided as you choose among " +
"defending player and/or any number of creatures they control.")) && overrideOrder && "defending player and/or any number of creatures they control.")) && overrideOrder &&
blockers.size() > 0) || (attacker.hasKeyword("Trample:Planeswalker") && defender instanceof Card)) { blockers.size() > 0) || (attacker.hasKeyword("Trample:Planeswalker") && defender instanceof Card)) {
GameEntityViewMap<Card, CardView> gameCacheBlockers = GameEntityView.getMap(blockers); GameEntityViewMap<Card, CardView> gameCacheBlockers = GameEntityView.getMap(blockers);
final CardView vAttacker = CardView.get(attacker); final CardView vAttacker = CardView.get(attacker);
final GameEntityView vDefender = GameEntityView.get(defender); final GameEntityView vDefender = GameEntityView.get(defender);
@@ -398,7 +398,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
vAffected.put(GameEntityView.get(e.getKey()), e.getValue()); vAffected.put(GameEntityView.get(e.getKey()), e.getValue());
} }
final Map<Object, Integer> vResult = getGui().assignGenericAmount(vSource, vAffected, shieldAmount, false, final Map<Object, Integer> vResult = getGui().assignGenericAmount(vSource, vAffected, shieldAmount, false,
localizer.getMessage("lblShield")); localizer.getMessage("lblShield"));
Map<GameEntity, Integer> result = new HashMap<>(); Map<GameEntity, Integer> result = new HashMap<>();
if (vResult != null) { //fix for netplay if (vResult != null) { //fix for netplay
for (Map.Entry<GameEntity, Integer> e : affected.entrySet()) { for (Map.Entry<GameEntity, Integer> e : affected.entrySet()) {
@@ -420,7 +420,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
vAffected.put(it.next(), maxAmount); vAffected.put(it.next(), maxAmount);
} }
final Map<Object, Integer> vResult = getGui().assignGenericAmount(vSource, vAffected, manaAmount, false, final Map<Object, Integer> vResult = getGui().assignGenericAmount(vSource, vAffected, manaAmount, false,
localizer.getMessage("lblMana").toLowerCase()); localizer.getMessage("lblMana").toLowerCase());
Map<Byte, Integer> result = new HashMap<>(); Map<Byte, Integer> result = new HashMap<>();
if (vResult != null) { //fix for netplay if (vResult != null) { //fix for netplay
it = colorSet.iterator(); it = colorSet.iterator();
@@ -471,7 +471,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
ability.getParamOrDefault("AnnounceTitle", announce); ability.getParamOrDefault("AnnounceTitle", announce);
if (cost.isMandatory()) { if (cost.isMandatory()) {
return chooseNumber(ability, localizer.getMessage("lblChooseAnnounceForCard", announceTitle, return chooseNumber(ability, localizer.getMessage("lblChooseAnnounceForCard", announceTitle,
CardTranslation.getTranslatedName(ability.getHostCard().getName())) , min, max); CardTranslation.getTranslatedName(ability.getHostCard().getName())), min, max);
} }
if ("NumTimes".equals(announce)) { if ("NumTimes".equals(announce)) {
return getGui().getInteger(localizer.getMessage("lblHowManyTimesToPay", ability.getPayCosts().getTotalMana(), return getGui().getInteger(localizer.getMessage("lblHowManyTimesToPay", ability.getPayCosts().getTotalMana(),
@@ -483,18 +483,18 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public CardCollectionView choosePermanentsToSacrifice(final SpellAbility sa, final int min, final int max, public CardCollectionView choosePermanentsToSacrifice(final SpellAbility sa, final int min, final int max,
final CardCollectionView valid, final String message) { final CardCollectionView valid, final String message) {
return choosePermanentsTo(min, max, valid, message, localizer.getMessage("lblSacrifice").toLowerCase(), sa); return choosePermanentsTo(min, max, valid, message, localizer.getMessage("lblSacrifice").toLowerCase(), sa);
} }
@Override @Override
public CardCollectionView choosePermanentsToDestroy(final SpellAbility sa, final int min, final int max, public CardCollectionView choosePermanentsToDestroy(final SpellAbility sa, final int min, final int max,
final CardCollectionView valid, final String message) { final CardCollectionView valid, final String message) {
return choosePermanentsTo(min, max, valid, message, localizer.getMessage("lblDestroy"), sa); return choosePermanentsTo(min, max, valid, message, localizer.getMessage("lblDestroy"), sa);
} }
private CardCollectionView choosePermanentsTo(final int min, int max, final CardCollectionView valid, private CardCollectionView choosePermanentsTo(final int min, int max, final CardCollectionView valid,
final String message, final String action, final SpellAbility sa) { final String message, final String action, final SpellAbility sa) {
max = Math.min(max, valid.size()); max = Math.min(max, valid.size());
if (max <= 0) { if (max <= 0) {
return CardCollection.EMPTY; return CardCollection.EMPTY;
@@ -516,7 +516,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
private boolean useSelectCardsInput(final FCollectionView<? extends GameEntity> sourceList) { private boolean useSelectCardsInput(final FCollectionView<? extends GameEntity> sourceList) {
// can't use InputSelect from GUI thread (e.g., DevMode Tutor) // can't use InputSelect from GUI thread (e.g., DevMode Tutor)
if (FThreads.isGuiThread()) { return false; } if (FThreads.isGuiThread()) {
return false;
}
// if UI_SELECT_FROM_CARD_DISPLAYS not set use InputSelect only for battlefield and player hand // if UI_SELECT_FROM_CARD_DISPLAYS not set use InputSelect only for battlefield and player hand
// if UI_SELECT_FROM_CARD_DISPLAYS set and using desktop GUI use InputSelect for any zone that can be shown // if UI_SELECT_FROM_CARD_DISPLAYS set and using desktop GUI use InputSelect for any zone that can be shown
@@ -535,11 +537,11 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
} }
final boolean useUiPointAtCard = final boolean useUiPointAtCard =
(FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) && (!GuiBase.getInterface().isLibgdxPort())) ? (FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) && (!GuiBase.getInterface().isLibgdxPort())) ?
(cz.is(ZoneType.Battlefield) || cz.is(ZoneType.Hand) || cz.is(ZoneType.Library) || (cz.is(ZoneType.Battlefield) || cz.is(ZoneType.Hand) || cz.is(ZoneType.Library) ||
cz.is(ZoneType.Graveyard) || cz.is(ZoneType.Exile) || cz.is(ZoneType.Flashback) || cz.is(ZoneType.Graveyard) || cz.is(ZoneType.Exile) || cz.is(ZoneType.Flashback) ||
cz.is(ZoneType.Command) || cz.is(ZoneType.Sideboard)) : cz.is(ZoneType.Command) || cz.is(ZoneType.Sideboard)) :
(cz.is(ZoneType.Hand, player) || cz.is(ZoneType.Battlefield)); (cz.is(ZoneType.Hand, player) || cz.is(ZoneType.Battlefield));
if (!useUiPointAtCard) { if (!useUiPointAtCard) {
return false; return false;
} }
@@ -549,7 +551,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public CardCollectionView chooseCardsForEffect(final CardCollectionView sourceList, final SpellAbility sa, public CardCollectionView chooseCardsForEffect(final CardCollectionView sourceList, final SpellAbility sa,
final String title, final int min, final int max, final boolean isOptional, Map<String, Object> params) { final String title, final int min, final int max, final boolean isOptional, Map<String, Object> params) {
// If only one card to choose, use a dialog box. // If only one card to choose, use a dialog box.
// Otherwise, use the order dialog to be able to grab multiple cards in one shot // Otherwise, use the order dialog to be able to grab multiple cards in one shot
@@ -586,8 +588,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public <T extends GameEntity> T chooseSingleEntityForEffect(final FCollectionView<T> optionList, public <T extends GameEntity> T chooseSingleEntityForEffect(final FCollectionView<T> optionList,
final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final boolean isOptional, final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final boolean isOptional,
final Player targetedPlayer, Map<String, Object> params) { final Player targetedPlayer, Map<String, Object> params) {
// Human is supposed to read the message and understand from it what to choose // Human is supposed to read the message and understand from it what to choose
if (optionList.isEmpty()) { if (optionList.isEmpty()) {
if (delayedReveal != null) { if (delayedReveal != null) {
@@ -632,7 +634,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public <T extends GameEntity> List<T> chooseEntitiesForEffect(final FCollectionView<T> optionList, final int min, final int max, public <T extends GameEntity> List<T> chooseEntitiesForEffect(final FCollectionView<T> optionList, final int min, final int max,
final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final Player targetedPlayer, Map<String, Object> params) { final DelayedReveal delayedReveal, final SpellAbility sa, final String title, final Player targetedPlayer, Map<String, Object> params) {
// useful details for debugging problems with the mass select logic // useful details for debugging problems with the mass select logic
Sentry.setExtra("Card", sa.getCardView().toString()); Sentry.setExtra("Card", sa.getCardView().toString());
Sentry.setExtra("SpellAbility", sa.toString()); Sentry.setExtra("SpellAbility", sa.toString());
@@ -688,13 +690,13 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public int chooseNumber(final SpellAbility sa, final String title, final List<Integer> choices, public int chooseNumber(final SpellAbility sa, final String title, final List<Integer> choices,
final Player relatedPlayer) { final Player relatedPlayer) {
return getGui().one(title, choices).intValue(); return getGui().one(title, choices).intValue();
} }
@Override @Override
public SpellAbility chooseSingleSpellForEffect(final List<SpellAbility> spells, final SpellAbility sa, public SpellAbility chooseSingleSpellForEffect(final List<SpellAbility> spells, final SpellAbility sa,
final String title, Map<String, Object> params) { final String title, Map<String, Object> params) {
if (spells.size() < 2) { if (spells.size() < 2) {
return Iterables.getFirst(spells, null); return Iterables.getFirst(spells, null);
} }
@@ -719,7 +721,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
//override generic //override generic
List<SpellAbilityView> chosen = getGui().getChoices(title, num, num, Lists.newArrayList(spellViewCache.keySet())); List<SpellAbilityView> chosen = getGui().getChoices(title, num, num, Lists.newArrayList(spellViewCache.keySet()));
for(SpellAbilityView view : chosen) { for (SpellAbilityView view : chosen) {
if (spellViewCache.containsKey(view)) { if (spellViewCache.containsKey(view)) {
result.add(spellViewCache.get(view)); result.add(spellViewCache.get(view));
} }
@@ -744,13 +746,13 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
case "FirstRemembered": case "FirstRemembered":
o = sa.getHostCard().getFirstRemembered(); o = sa.getHostCard().getFirstRemembered();
if (o instanceof Card) { if (o instanceof Card) {
show = (Card)o; show = (Card) o;
} }
break; break;
case "LastRemembered": case "LastRemembered":
o = sa.getHostCard().getFirstRemembered(); o = sa.getHostCard().getFirstRemembered();
if (o instanceof Card) { if (o instanceof Card) {
show = (Card)o; show = (Card) o;
} }
break; break;
} }
@@ -766,13 +768,13 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public boolean confirmBidAction(final SpellAbility sa, final PlayerActionConfirmMode bidlife, final String string, public boolean confirmBidAction(final SpellAbility sa, final PlayerActionConfirmMode bidlife, final String string,
final int bid, final Player winner) { final int bid, final Player winner) {
return InputConfirm.confirm(this, sa, string + " " + localizer.getMessage("lblHighestBidder") + " " + winner); return InputConfirm.confirm(this, sa, string + " " + localizer.getMessage("lblHighestBidder") + " " + winner);
} }
@Override @Override
public boolean confirmStaticApplication(final Card hostCard, final GameEntity affected, final String logic, public boolean confirmStaticApplication(final Card hostCard, final GameEntity affected, final String logic,
final String message) { final String message) {
return InputConfirm.confirm(this, CardView.get(hostCard), message); return InputConfirm.confirm(this, CardView.get(hostCard), message);
} }
@@ -919,7 +921,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
final String fm = MessageUtil.formatMessage(message, getLocalPlayerView(), owner); final String fm = MessageUtil.formatMessage(message, getLocalPlayerView(), owner);
if (!cards.isEmpty()) { if (!cards.isEmpty()) {
tempShowCards(cards); tempShowCards(cards);
getGui().reveal(fm, CardView.getCollection(cards)); TrackableCollection<CardView> collection = CardView.getCollection(cards);
getGui().reveal(fm, collection);
getGui().updateRevealedCards(collection);
endTempShowCards(); endTempShowCards();
} else { } else {
getGui().message(MessageUtil.formatMessage(localizer.getMessage("lblThereNoCardInPlayerZone", "{player's}", zone.getTranslatedName().toLowerCase()), getGui().message(MessageUtil.formatMessage(localizer.getMessage("lblThereNoCardInPlayerZone", "{player's}", zone.getTranslatedName().toLowerCase()),
@@ -935,14 +939,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
} }
public ImmutablePair<CardCollection, CardCollection> arrangeForMove(final String title, final FCollectionView<Card> cards, final List<Card> manipulable, final boolean topOK, final boolean bottomOK) { public ImmutablePair<CardCollection, CardCollection> arrangeForMove(final String title, final FCollectionView<Card> cards, final List<Card> manipulable, final boolean topOK, final boolean bottomOK) {
List<Card> result = manipulateCardList(title, cards, manipulable, topOK, bottomOK, false); List<Card> result = manipulateCardList(title, cards, manipulable, topOK, bottomOK, false);
CardCollection toBottom = new CardCollection(); CardCollection toBottom = new CardCollection();
CardCollection toTop = new CardCollection(); CardCollection toTop = new CardCollection();
for (int i = 0; i<cards.size() && manipulable.contains(result.get(i)) ; i++ ) { for (int i = 0; i < cards.size() && manipulable.contains(result.get(i)); i++) {
toTop.add(result.get(i)); toTop.add(result.get(i));
} }
if (toTop.size() < cards.size()) { // the top isn't everything if (toTop.size() < cards.size()) { // the top isn't everything
for (int i = result.size()-1; i>=0 && manipulable.contains(result.get(i)); i-- ) { for (int i = result.size() - 1; i >= 0 && manipulable.contains(result.get(i)); i--) {
toBottom.add(result.get(i)); toBottom.add(result.get(i));
} }
} }
@@ -956,10 +960,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
tempShowCards(topN); tempShowCards(topN);
if (FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) && if (FModel.getPreferences().getPrefBoolean(FPref.UI_SELECT_FROM_CARD_DISPLAYS) &&
(!GuiBase.getInterface().isLibgdxPort()) && (!GuiBase.isNetworkplay())) { //prevent crash for desktop vs mobile port it will crash the netplay since mobile doesnt have manipulatecardlist, send the alternate below (!GuiBase.getInterface().isLibgdxPort()) && (!GuiBase.isNetworkplay())) { //prevent crash for desktop vs mobile port it will crash the netplay since mobile doesnt have manipulatecardlist, send the alternate below
CardCollectionView cardList = player.getCardsIn(ZoneType.Library); CardCollectionView cardList = player.getCardsIn(ZoneType.Library);
ImmutablePair<CardCollection, CardCollection> result = ImmutablePair<CardCollection, CardCollection> result =
arrangeForMove(localizer.getMessage("lblMoveCardstoToporBbottomofLibrary"), cardList, topN, true, true); arrangeForMove(localizer.getMessage("lblMoveCardstoToporBbottomofLibrary"), cardList, topN, true, true);
toTop = result.getLeft(); toTop = result.getLeft();
toBottom = result.getRight(); toBottom = result.getRight();
} else { } else {
@@ -974,7 +978,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
toBottom = new CardCollection(); toBottom = new CardCollection();
List<CardView> views = getGui().many(localizer.getMessage("lblSelectCardsToBeOutOnTheBottomOfYourLibrary"), List<CardView> views = getGui().many(localizer.getMessage("lblSelectCardsToBeOutOnTheBottomOfYourLibrary"),
localizer.getMessage("lblCardsToPutOnTheBottom"), -1, cardCacheScry.getTrackableKeys(), null); localizer.getMessage("lblCardsToPutOnTheBottom"), -1, cardCacheScry.getTrackableKeys(), null);
cardCacheScry.addToList(views, toBottom); cardCacheScry.addToList(views, toBottom);
topN.removeAll(toBottom); topN.removeAll(toBottom);
@@ -986,7 +990,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
GameEntityViewMap<Card, CardView> cardCacheOrder = GameEntityView.getMap(topN); GameEntityViewMap<Card, CardView> cardCacheOrder = GameEntityView.getMap(topN);
toTop = new CardCollection(); toTop = new CardCollection();
views = getGui().order(localizer.getMessage("lblArrangeCardsToBePutOnTopOfYourLibrary"), views = getGui().order(localizer.getMessage("lblArrangeCardsToBePutOnTopOfYourLibrary"),
localizer.getMessage("lblTopOfLibrary"), cardCacheOrder.getTrackableKeys(), null); localizer.getMessage("lblTopOfLibrary"), cardCacheOrder.getTrackableKeys(), null);
cardCacheOrder.addToList(views, toTop); cardCacheOrder.addToList(views, toTop);
} }
} }
@@ -1088,34 +1092,34 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
List<CardView> choices = gameCacheMove.getTrackableKeys(); List<CardView> choices = gameCacheMove.getTrackableKeys();
switch (destinationZone) { switch (destinationZone) {
case Library: case Library:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoLibrary"), localizer.getMessage(bottomOfLibrary ? "lblClosestToBottom" : "lblClosestToTop"), choices, null); choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoLibrary"), localizer.getMessage(bottomOfLibrary ? "lblClosestToBottom" : "lblClosestToTop"), choices, null);
break; break;
case Battlefield: case Battlefield:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutOntoBattlefield"), localizer.getMessage("lblPutFirst"), choices, null); choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutOntoBattlefield"), localizer.getMessage("lblPutFirst"), choices, null);
break; break;
case Graveyard: case Graveyard:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoGraveyard"), localizer.getMessage("lblClosestToBottom"), choices, null); choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoGraveyard"), localizer.getMessage("lblClosestToBottom"), choices, null);
break; break;
case Exile: case Exile:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoExile"), localizer.getMessage("lblPutFirst"), choices, null); choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoExile"), localizer.getMessage("lblPutFirst"), choices, null);
break; break;
case PlanarDeck: case PlanarDeck:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoPlanarDeck"), localizer.getMessage("lblClosestToTop"), choices, null); choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoPlanarDeck"), localizer.getMessage("lblClosestToTop"), choices, null);
break; break;
case SchemeDeck: case SchemeDeck:
choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoSchemeDeck"), localizer.getMessage("lblClosestToTop"), choices, null); choices = getGui().order(localizer.getMessage("lblChooseOrderCardsPutIntoSchemeDeck"), localizer.getMessage("lblClosestToTop"), choices, null);
break; break;
case Stack: case Stack:
choices = getGui().order(localizer.getMessage("lblChooseOrderCopiesCast"), localizer.getMessage("lblPutFirst"), choices, null); choices = getGui().order(localizer.getMessage("lblChooseOrderCopiesCast"), localizer.getMessage("lblPutFirst"), choices, null);
break; break;
case None: //for when we want to order but don't really want to move the cards case None: //for when we want to order but don't really want to move the cards
choices = getGui().order(localizer.getMessage("lblChooseOrderCards"), localizer.getMessage("lblPutFirst"), choices, null); choices = getGui().order(localizer.getMessage("lblChooseOrderCards"), localizer.getMessage("lblPutFirst"), choices, null);
break; break;
default: default:
System.out.println("ZoneType " + destinationZone + " - Not Ordered"); System.out.println("ZoneType " + destinationZone + " - Not Ordered");
endTempShowCards(); endTempShowCards();
return cards; return cards;
} }
endTempShowCards(); endTempShowCards();
CardCollection result = new CardCollection(); CardCollection result = new CardCollection();
@@ -1125,7 +1129,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public CardCollectionView chooseCardsToDiscardFrom(final Player p, final SpellAbility sa, public CardCollectionView chooseCardsToDiscardFrom(final Player p, final SpellAbility sa,
final CardCollection valid, final int min, final int max) { final CardCollection valid, final int min, final int max) {
boolean optional = min == 0; boolean optional = min == 0;
if (p != player) { if (p != player) {
@@ -1184,8 +1188,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
*/ */
@Override @Override
public CardCollectionView chooseCardsToDiscardUnlessType(final int num, final CardCollectionView hand, public CardCollectionView chooseCardsToDiscardUnlessType(final int num, final CardCollectionView hand,
final String uType, final SpellAbility sa) { final String uType, final SpellAbility sa) {
String [] splitUTypes = uType.split(","); String[] splitUTypes = uType.split(",");
final InputSelectEntitiesFromList<Card> target = new InputSelectEntitiesFromList<Card>(this, num, num, hand, final InputSelectEntitiesFromList<Card> target = new InputSelectEntitiesFromList<Card>(this, num, num, hand,
sa) { sa) {
private static final long serialVersionUID = -5774108410928795591L; private static final long serialVersionUID = -5774108410928795591L;
@@ -1206,10 +1210,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
return super.hasAllTargets(); return super.hasAllTargets();
} }
}; };
int n=1; int n = 1;
StringBuilder promptType = new StringBuilder(); StringBuilder promptType = new StringBuilder();
for (String part : splitUTypes) { for (String part : splitUTypes) {
if (n==1) { if (n == 1) {
promptType.append(part.toLowerCase()); promptType.append(part.toLowerCase());
} else { } else {
promptType.append(" or ").append(part.toLowerCase()); promptType.append(" or ").append(part.toLowerCase());
@@ -1247,7 +1251,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
*/ */
@Override @Override
public String chooseSomeType(final String kindOfType, final SpellAbility sa, final Collection<String> validTypes, public String chooseSomeType(final String kindOfType, final SpellAbility sa, final Collection<String> validTypes,
final List<String> invalidTypes, final boolean isOptional) { final List<String> invalidTypes, final boolean isOptional) {
final List<String> types = Lists.newArrayList(validTypes); final List<String> types = Lists.newArrayList(validTypes);
if (invalidTypes != null && !invalidTypes.isEmpty()) { if (invalidTypes != null && !invalidTypes.isEmpty()) {
Iterables.removeAll(types, invalidTypes); Iterables.removeAll(types, invalidTypes);
@@ -1378,7 +1382,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public Object vote(final SpellAbility sa, final String prompt, final List<Object> options, public Object vote(final SpellAbility sa, final String prompt, final List<Object> options,
final ListMultimap<Object, Player> votes, Player forPlayer) { final ListMultimap<Object, Player> votes, Player forPlayer) {
return getGui().one(prompt, options); return getGui().one(prompt, options);
} }
@@ -1392,7 +1396,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
*/ */
@Override @Override
public boolean confirmReplacementEffect(final ReplacementEffect replacementEffect, final SpellAbility effectSA, public boolean confirmReplacementEffect(final ReplacementEffect replacementEffect, final SpellAbility effectSA,
GameEntity affected, final String question) { GameEntity affected, final String question) {
if (GuiBase.getInterface().isLibgdxPort()) { if (GuiBase.getInterface().isLibgdxPort()) {
return this.getGui().confirm(effectSA.getView().getHostCard(), question.replaceAll("\n", " ")); return this.getGui().confirm(effectSA.getView().getHostCard(), question.replaceAll("\n", " "));
} else { } else {
@@ -1430,7 +1434,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
if (mayAutoPass()) { if (mayAutoPass()) {
if (CombatUtil.validateAttackers(combat)) { if (CombatUtil.validateAttackers(combat)) {
return; // don't prompt to declare attackers if user chose to return; // don't prompt to declare attackers if user chose to
// end the turn and not attacking is legal // end the turn and not attacking is legal
} }
// otherwise: cancel auto pass because of this unexpected attack // otherwise: cancel auto pass because of this unexpected attack
autoPassCancel(); autoPassCancel();
@@ -1482,7 +1486,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
if (getGui().isUiSetToSkipPhase(getGame().getPhaseHandler().getPlayerTurn().getView(), if (getGui().isUiSetToSkipPhase(getGame().getPhaseHandler().getPlayerTurn().getView(),
getGame().getPhaseHandler().getPhase())) { getGame().getPhaseHandler().getPhase())) {
return null; // avoid prompt for input if stack is empty and return null; // avoid prompt for input if stack is empty and
// player is set to skip the current phase // player is set to skip the current phase
} }
} else { } else {
final SpellAbility ability = stack.peekAbility(); final SpellAbility ability = stack.peekAbility();
@@ -1522,13 +1526,12 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
return choices; return choices;
} }
@SuppressWarnings("serial") @SuppressWarnings("serial") final InputSelectCardsFromList inp = new InputSelectCardsFromList(this, nDiscard, nDiscard,
final InputSelectCardsFromList inp = new InputSelectCardsFromList(this, nDiscard, nDiscard,
player.getZone(ZoneType.Hand).getCards()) { player.getZone(ZoneType.Hand).getCards()) {
@Override @Override
protected final boolean allowAwaitNextInput() { protected final boolean allowAwaitNextInput() {
return true; // prevent Cleanup message getting stuck during return true; // prevent Cleanup message getting stuck during
// opponent's next turn // opponent's next turn
} }
}; };
final String message = localizer.getMessage("lblCleanupPhase") + "\n" final String message = localizer.getMessage("lblCleanupPhase") + "\n"
@@ -1551,7 +1554,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public boolean payManaOptional(final Card c, final Cost cost, final SpellAbility sa, final String prompt, public boolean payManaOptional(final Card c, final Cost cost, final SpellAbility sa, final String prompt,
final ManaPaymentPurpose purpose) { final ManaPaymentPurpose purpose) {
if (sa == null && cost.isOnlyManaCost() && cost.getTotalMana().isZero() if (sa == null && cost.isOnlyManaCost() && cost.getTotalMana().isZero()
&& !FModel.getPreferences().getPrefBoolean(FPref.MATCHPREF_PROMPT_FREE_BLOCKS)) { && !FModel.getPreferences().getPrefBoolean(FPref.MATCHPREF_PROMPT_FREE_BLOCKS)) {
return true; return true;
@@ -1590,36 +1593,36 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public boolean chooseBinary(final SpellAbility sa, final String question, final BinaryChoiceType kindOfChoice, public boolean chooseBinary(final SpellAbility sa, final String question, final BinaryChoiceType kindOfChoice,
final Boolean defaultVal) { final Boolean defaultVal) {
final List<String> labels; final List<String> labels;
switch (kindOfChoice) { switch (kindOfChoice) {
case HeadsOrTails: case HeadsOrTails:
labels = ImmutableList.of(localizer.getMessage("lblHeads"), localizer.getMessage("lblTails")); labels = ImmutableList.of(localizer.getMessage("lblHeads"), localizer.getMessage("lblTails"));
break; break;
case TapOrUntap: case TapOrUntap:
labels = ImmutableList.of(StringUtils.capitalize(localizer.getMessage("lblTap")), labels = ImmutableList.of(StringUtils.capitalize(localizer.getMessage("lblTap")),
localizer.getMessage("lblUntap")); localizer.getMessage("lblUntap"));
break; break;
case OddsOrEvens: case OddsOrEvens:
labels = ImmutableList.of(localizer.getMessage("lblOdds"), localizer.getMessage("lblEvens")); labels = ImmutableList.of(localizer.getMessage("lblOdds"), localizer.getMessage("lblEvens"));
break; break;
case UntapOrLeaveTapped: case UntapOrLeaveTapped:
labels = ImmutableList.of(localizer.getMessage("lblUntap"), localizer.getMessage("lblLeaveTapped")); labels = ImmutableList.of(localizer.getMessage("lblUntap"), localizer.getMessage("lblLeaveTapped"));
break; break;
case UntapTimeVault: case UntapTimeVault:
labels = ImmutableList.of(localizer.getMessage("lblUntapAndSkipThisTurn"), localizer.getMessage("lblLeaveTapped")); labels = ImmutableList.of(localizer.getMessage("lblUntapAndSkipThisTurn"), localizer.getMessage("lblLeaveTapped"));
break; break;
case PlayOrDraw: case PlayOrDraw:
labels = ImmutableList.of(localizer.getMessage("lblPlay"), localizer.getMessage("lblDraw")); labels = ImmutableList.of(localizer.getMessage("lblPlay"), localizer.getMessage("lblDraw"));
break; break;
case LeftOrRight: case LeftOrRight:
labels = ImmutableList.of(localizer.getMessage("lblLeft"), localizer.getMessage("lblRight")); labels = ImmutableList.of(localizer.getMessage("lblLeft"), localizer.getMessage("lblRight"));
break; break;
case AddOrRemove: case AddOrRemove:
labels = ImmutableList.of(localizer.getMessage("lblAddCounter"), localizer.getMessage("lblRemoveCounter")); labels = ImmutableList.of(localizer.getMessage("lblAddCounter"), localizer.getMessage("lblRemoveCounter"));
break; break;
default: default:
labels = ImmutableList.copyOf(kindOfChoice.toString().split("Or")); labels = ImmutableList.copyOf(kindOfChoice.toString().split("Or"));
} }
return InputConfirm.confirm(this, sa, question, defaultVal == null || defaultVal.booleanValue(), labels); return InputConfirm.confirm(this, sa, question, defaultVal == null || defaultVal.booleanValue(), labels);
@@ -1627,9 +1630,9 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public boolean chooseFlipResult(final SpellAbility sa, final Player flipper, final boolean[] results, public boolean chooseFlipResult(final SpellAbility sa, final Player flipper, final boolean[] results,
final boolean call) { final boolean call) {
final String[] labelsSrc = call ? new String[] { localizer.getMessage("lblHeads"), localizer.getMessage("lblTails") } final String[] labelsSrc = call ? new String[]{localizer.getMessage("lblHeads"), localizer.getMessage("lblTails")}
: new String[] { localizer.getMessage("lblWinTheFlip"), localizer.getMessage("lblLoseTheFlip") }; : new String[]{localizer.getMessage("lblWinTheFlip"), localizer.getMessage("lblLoseTheFlip")};
final List<String> sortedResults = new ArrayList<String>(); final List<String> sortedResults = new ArrayList<String>();
for (boolean result : results) { for (boolean result : results) {
sortedResults.add(labelsSrc[result ? 0 : 1]); sortedResults.add(labelsSrc[result ? 0 : 1]);
@@ -1644,14 +1647,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public Card chooseProtectionShield(final GameEntity entityBeingDamaged, final List<String> options, public Card chooseProtectionShield(final GameEntity entityBeingDamaged, final List<String> options,
final Map<String, Card> choiceMap) { final Map<String, Card> choiceMap) {
final String title = entityBeingDamaged + " - " + localizer.getMessage("lblSelectPreventionShieldToUse"); final String title = entityBeingDamaged + " - " + localizer.getMessage("lblSelectPreventionShieldToUse");
return choiceMap.get(getGui().one(title, options)); return choiceMap.get(getGui().one(title, options));
} }
@Override @Override
public Pair<SpellAbilityStackInstance, GameObject> chooseTarget(final SpellAbility saSpellskite, public Pair<SpellAbilityStackInstance, GameObject> chooseTarget(final SpellAbility saSpellskite,
final List<Pair<SpellAbilityStackInstance, GameObject>> allTargets) { final List<Pair<SpellAbilityStackInstance, GameObject>> allTargets) {
if (allTargets.size() < 2) { if (allTargets.size() < 2) {
return Iterables.getFirst(allTargets, null); return Iterables.getFirst(allTargets, null);
} }
@@ -1692,7 +1695,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
*/ */
@Override @Override
public List<AbilitySub> chooseModeForAbility(final SpellAbility sa, List<AbilitySub> possible, final int min, final int num, public List<AbilitySub> chooseModeForAbility(final SpellAbility sa, List<AbilitySub> possible, final int min, final int num,
boolean allowRepeat) { boolean allowRepeat) {
boolean trackerFrozen = getGame().getTracker().isFrozen(); boolean trackerFrozen = getGame().getTracker().isFrozen();
if (trackerFrozen) { if (trackerFrozen) {
// The view tracker needs to be unfrozen to update the SpellAbilityViews at this point, or it may crash // The view tracker needs to be unfrozen to update the SpellAbilityViews at this point, or it may crash
@@ -1726,7 +1729,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public List<String> chooseColors(final String message, final SpellAbility sa, final int min, final int max, public List<String> chooseColors(final String message, final SpellAbility sa, final int min, final int max,
List<String> options) { List<String> options) {
options = options.stream().map(DeckRecognizer::getLocalisedMagicColorName).collect(Collectors.toList()); options = options.stream().map(DeckRecognizer::getLocalisedMagicColorName).collect(Collectors.toList());
List<String> choices = getGui().getChoices(message, min, max, options); List<String> choices = getGui().getChoices(message, min, max, options);
return choices.stream().map(DeckRecognizer::getColorNameByLocalisedName).collect(Collectors.toList()); return choices.stream().map(DeckRecognizer::getColorNameByLocalisedName).collect(Collectors.toList());
@@ -1736,12 +1739,12 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
public byte chooseColor(final String message, final SpellAbility sa, final ColorSet colors) { public byte chooseColor(final String message, final SpellAbility sa, final ColorSet colors) {
final int cntColors = colors.countColors(); final int cntColors = colors.countColors();
switch (cntColors) { switch (cntColors) {
case 0: case 0:
return 0; return 0;
case 1: case 1:
return colors.getColor(); return colors.getColor();
default: default:
return chooseColorCommon(message, sa == null ? null : sa.getHostCard(), colors, false); return chooseColorCommon(message, sa == null ? null : sa.getHostCard(), colors, false);
} }
} }
@@ -1749,15 +1752,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
public byte chooseColorAllowColorless(final String message, final Card c, final ColorSet colors) { public byte chooseColorAllowColorless(final String message, final Card c, final ColorSet colors) {
final int cntColors = 1 + colors.countColors(); final int cntColors = 1 + colors.countColors();
switch (cntColors) { switch (cntColors) {
case 1: case 1:
return 0; return 0;
default: default:
return chooseColorCommon(message, c, colors, true); return chooseColorCommon(message, c, colors, true);
} }
} }
private byte chooseColorCommon(final String message, final Card c, final ColorSet colors, private byte chooseColorCommon(final String message, final Card c, final ColorSet colors,
final boolean withColorless) { final boolean withColorless) {
final ImmutableList.Builder<String> colorNamesBuilder = ImmutableList.builder(); final ImmutableList.Builder<String> colorNamesBuilder = ImmutableList.builder();
if (withColorless) { if (withColorless) {
colorNamesBuilder.add(MagicColor.toLongString(MagicColor.COLORLESS)); colorNamesBuilder.add(MagicColor.toLongString(MagicColor.COLORLESS));
@@ -1778,7 +1781,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public ICardFace chooseSingleCardFace(final SpellAbility sa, final String message, final Predicate<ICardFace> cpp, public ICardFace chooseSingleCardFace(final SpellAbility sa, final String message, final Predicate<ICardFace> cpp,
final String name) { final String name) {
final Iterable<ICardFace> cardsFromDb = FModel.getMagicDb().getCommonCards().getAllFaces(); final Iterable<ICardFace> cardsFromDb = FModel.getMagicDb().getCommonCards().getAllFaces();
final List<ICardFace> cards = Lists.newArrayList(Iterables.filter(cardsFromDb, cpp)); final List<ICardFace> cards = Lists.newArrayList(Iterables.filter(cardsFromDb, cpp));
CardFaceView cardFaceView; CardFaceView cardFaceView;
@@ -1794,7 +1797,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public CounterType chooseCounterType(final List<CounterType> options, final SpellAbility sa, final String prompt, public CounterType chooseCounterType(final List<CounterType> options, final SpellAbility sa, final String prompt,
Map<String, Object> params) { Map<String, Object> params) {
if (options.size() <= 1) { if (options.size() <= 1) {
return Iterables.getFirst(options, null); return Iterables.getFirst(options, null);
} }
@@ -1830,7 +1833,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public ReplacementEffect chooseSingleReplacementEffect(final String prompt, public ReplacementEffect chooseSingleReplacementEffect(final String prompt,
final List<ReplacementEffect> possibleReplacers) { final List<ReplacementEffect> possibleReplacers) {
final ReplacementEffect first = possibleReplacers.get(0); final ReplacementEffect first = possibleReplacers.get(0);
if (possibleReplacers.size() == 1) { if (possibleReplacers.size() == 1) {
return first; return first;
@@ -1853,7 +1856,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public boolean payCostToPreventEffect(final Cost cost, final SpellAbility sa, final boolean alreadyPaid, public boolean payCostToPreventEffect(final Cost cost, final SpellAbility sa, final boolean alreadyPaid,
final FCollectionView<Player> allPayers) { final FCollectionView<Player> allPayers) {
// if it's paid by the AI already the human can pay, but it won't change anything // if it's paid by the AI already the human can pay, but it won't change anything
return HumanPlay.payCostDuringAbilityResolve(this, player, sa.getHostCard(), cost, sa, null); return HumanPlay.payCostDuringAbilityResolve(this, player, sa.getHostCard(), cost, sa, null);
} }
@@ -1883,7 +1886,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
} }
if (!needPrompt && !saStr.equals(firstStr) && !currentSa.hasParam("OrderDuplicates")) { if (!needPrompt && !saStr.equals(firstStr) && !currentSa.hasParam("OrderDuplicates")) {
needPrompt = true; // prompt by default unless all abilities needPrompt = true; // prompt by default unless all abilities
// are the same // are the same
} }
saLookupKey.append(delim).append(saStr); saLookupKey.append(delim).append(saStr);
@@ -2065,7 +2068,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public boolean chooseCardsPile(final SpellAbility sa, final CardCollectionView pile1, public boolean chooseCardsPile(final SpellAbility sa, final CardCollectionView pile1,
final CardCollectionView pile2, final String faceUp) { final CardCollectionView pile2, final String faceUp) {
final String p1Str = TextUtil.concatNoSpace("-- Pile 1 (", String.valueOf(pile1.size()), " cards) --"); final String p1Str = TextUtil.concatNoSpace("-- Pile 1 (", String.valueOf(pile1.size()), " cards) --");
final String p2Str = TextUtil.concatNoSpace("-- Pile 2 (", String.valueOf(pile2.size()), " cards) --"); final String p2Str = TextUtil.concatNoSpace("-- Pile 2 (", String.valueOf(pile2.size()), " cards) --");
@@ -2125,23 +2128,23 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
for (Player p : unplayable.keySet()) { for (Player p : unplayable.keySet()) {
final Map<DeckSection, List<? extends PaperCard>> removedUnplayableCards = unplayable.get(p); final Map<DeckSection, List<? extends PaperCard>> removedUnplayableCards = unplayable.get(p);
final List<PaperCard> labels = new ArrayList<>(); final List<PaperCard> labels = new ArrayList<>();
for (final DeckSection s: new TreeSet<>(removedUnplayableCards.keySet())) { for (final DeckSection s : new TreeSet<>(removedUnplayableCards.keySet())) {
if (DeckSection.Sideboard.equals(s)) if (DeckSection.Sideboard.equals(s))
continue; continue;
for (PaperCard c: removedUnplayableCards.get(s)) { for (PaperCard c : removedUnplayableCards.get(s)) {
labels.add(c); labels.add(c);
} }
} }
if (!labels.isEmpty()) if (!labels.isEmpty())
getGui().reveal(localizer.getMessage("lblActionFromPlayerDeck", message, Lang.getInstance().getPossessedObject(MessageUtil.mayBeYou(player, p), "")), getGui().reveal(localizer.getMessage("lblActionFromPlayerDeck", message, Lang.getInstance().getPossessedObject(MessageUtil.mayBeYou(player, p), "")),
ImmutableList.copyOf(labels)); ImmutableList.copyOf(labels));
} }
return; return;
} }
for (Player p : unplayable.keySet()) { for (Player p : unplayable.keySet()) {
final Map<DeckSection, List<? extends PaperCard>> removedUnplayableCards = unplayable.get(p); final Map<DeckSection, List<? extends PaperCard>> removedUnplayableCards = unplayable.get(p);
final List<Object> labels = new ArrayList<>(); final List<Object> labels = new ArrayList<>();
for (final DeckSection s: new TreeSet<>(removedUnplayableCards.keySet())) { for (final DeckSection s : new TreeSet<>(removedUnplayableCards.keySet())) {
labels.add("=== " + DeckAIUtils.getLocalizedDeckSection(localizer, s) + " ==="); labels.add("=== " + DeckAIUtils.getLocalizedDeckSection(localizer, s) + " ===");
labels.addAll(removedUnplayableCards.get(s)); labels.addAll(removedUnplayableCards.get(s));
} }
@@ -2163,7 +2166,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public Map<Card, ManaCostShard> chooseCardsForConvokeOrImprovise(final SpellAbility sa, final ManaCost manaCost, public Map<Card, ManaCostShard> chooseCardsForConvokeOrImprovise(final SpellAbility sa, final ManaCost manaCost,
final CardCollectionView untappedCards, boolean improvise) { final CardCollectionView untappedCards, boolean improvise) {
final InputSelectCardsForConvokeOrImprovise inp = new InputSelectCardsForConvokeOrImprovise(this, player, final InputSelectCardsForConvokeOrImprovise inp = new InputSelectCardsForConvokeOrImprovise(this, player,
manaCost, untappedCards, improvise, sa); manaCost, untappedCards, improvise, sa);
inp.showAndWait(); inp.showAndWait();
@@ -2172,7 +2175,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public String chooseCardName(final SpellAbility sa, final Predicate<ICardFace> cpp, final String valid, public String chooseCardName(final SpellAbility sa, final Predicate<ICardFace> cpp, final String valid,
final String message) { final String message) {
while (true) { while (true) {
final ICardFace cardFace = chooseSingleCardFace(sa, message, cpp, sa.getHostCard().getName()); final ICardFace cardFace = chooseSingleCardFace(sa, message, cpp, sa.getHostCard().getName());
final PaperCard cp = FModel.getMagicDb().getCommonCards().getCard(cardFace.getName()); final PaperCard cp = FModel.getMagicDb().getCommonCards().getCard(cardFace.getName());
@@ -2188,14 +2191,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public Card chooseSingleCardForZoneChange(final ZoneType destination, final List<ZoneType> origin, public Card chooseSingleCardForZoneChange(final ZoneType destination, final List<ZoneType> origin,
final SpellAbility sa, final CardCollection fetchList, final DelayedReveal delayedReveal, final SpellAbility sa, final CardCollection fetchList, final DelayedReveal delayedReveal,
final String selectPrompt, final boolean isOptional, final Player decider) { final String selectPrompt, final boolean isOptional, final Player decider) {
return chooseSingleEntityForEffect(fetchList, delayedReveal, sa, selectPrompt, isOptional, decider, null); return chooseSingleEntityForEffect(fetchList, delayedReveal, sa, selectPrompt, isOptional, decider, null);
} }
public List<Card> chooseCardsForZoneChange(final ZoneType destination, final List<ZoneType> origin, public List<Card> chooseCardsForZoneChange(final ZoneType destination, final List<ZoneType> origin,
final SpellAbility sa, final CardCollection fetchList, final int min, final int max, final DelayedReveal delayedReveal, final SpellAbility sa, final CardCollection fetchList, final int min, final int max, final DelayedReveal delayedReveal,
final String selectPrompt, final Player decider) { final String selectPrompt, final Player decider) {
return chooseEntitiesForEffect(fetchList, min, max, delayedReveal, sa, selectPrompt, decider, null); return chooseEntitiesForEffect(fetchList, min, max, delayedReveal, sa, selectPrompt, decider, null);
} }
@@ -2292,7 +2295,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
@Override @Override
public boolean selectCard(final CardView cardView, final List<CardView> otherCardViewsToSelect, public boolean selectCard(final CardView cardView, final List<CardView> otherCardViewsToSelect,
final ITriggerEvent triggerEvent) { final ITriggerEvent triggerEvent) {
return inputProxy.selectCard(cardView, otherCardViewsToSelect, triggerEvent); return inputProxy.selectCard(cardView, otherCardViewsToSelect, triggerEvent);
} }
@@ -2539,7 +2542,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
final Card card = gameCacheCounters.get(cv); final Card card = gameCacheCounters.get(cv);
final ImmutableList<CounterType> counters = subtract ? ImmutableList.copyOf(card.getCounters().keySet()) final ImmutableList<CounterType> counters = subtract ? ImmutableList.copyOf(card.getCounters().keySet())
: ImmutableList.copyOf(Collections2.transform(CounterEnumType.values, input -> CounterType.get(input))); : ImmutableList.copyOf(Collections2.transform(CounterEnumType.values, input -> CounterType.get(input)));
final CounterType counter = getGui().oneOrNone(localizer.getMessage("lblWhichTypeofCounter"), counters); final CounterType counter = getGui().oneOrNone(localizer.getMessage("lblWhichTypeofCounter"), counters);
if (counter == null) { if (counter == null) {
@@ -2706,8 +2709,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see forge.player.IDevModeCheats#addCardToExile() * @see forge.player.IDevModeCheats#addCardToExile()
*/ */
@Override @Override
public void castASpell() { public void castASpell() {
addCardToZone(ZoneType.Battlefield, false, false); addCardToZone(ZoneType.Battlefield, false, false);
@@ -2847,7 +2850,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
} else if (targetZone == ZoneType.Library) { } else if (targetZone == ZoneType.Library) {
if (!repeatLast) { if (!repeatLast) {
lastTopOfTheLibrary = getGui().confirm(forgeCard.getView(), localizer.getMessage("lblCardShouldBeAddedToLibraryTopOrBottom", CardTranslation.getTranslatedName(forgeCard.getName())), lastTopOfTheLibrary = getGui().confirm(forgeCard.getView(), localizer.getMessage("lblCardShouldBeAddedToLibraryTopOrBottom", CardTranslation.getTranslatedName(forgeCard.getName())),
true, Arrays.asList(localizer.getMessage("lblTop"), localizer.getMessage("lblBottom"))); true, Arrays.asList(localizer.getMessage("lblTop"), localizer.getMessage("lblBottom")));
} }
if (lastTopOfTheLibrary) { if (lastTopOfTheLibrary) {
getGame().getAction().moveToLibrary(forgeCard, null); getGame().getAction().moveToLibrary(forgeCard, null);
@@ -3148,8 +3151,8 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
} }
// Fetch cards and players specified by the user input // Fetch cards and players specified by the user input
final ZoneType[] zones = { ZoneType.Battlefield, ZoneType.Hand, ZoneType.Graveyard, ZoneType.Exile, final ZoneType[] zones = {ZoneType.Battlefield, ZoneType.Hand, ZoneType.Graveyard, ZoneType.Exile,
ZoneType.Command }; ZoneType.Command};
final CardCollectionView cards = getGame().getCardsIn(Arrays.asList(zones)); final CardCollectionView cards = getGame().getCardsIn(Arrays.asList(zones));
for (final Pair<Integer, Boolean> entity : entityInfo) { for (final Pair<Integer, Boolean> entity : entityInfo) {
boolean found = false; boolean found = false;
@@ -3306,14 +3309,14 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
*/ */
@Override @Override
public List<OptionalCostValue> chooseOptionalCosts(SpellAbility choosen, public List<OptionalCostValue> chooseOptionalCosts(SpellAbility choosen,
List<OptionalCostValue> optionalCost) { List<OptionalCostValue> optionalCost) {
return getGui().many(localizer.getMessage("lblChooseOptionalCosts"), localizer.getMessage("lblOptionalCosts"), 0, optionalCost.size(), return getGui().many(localizer.getMessage("lblChooseOptionalCosts"), localizer.getMessage("lblOptionalCosts"), 0, optionalCost.size(),
optionalCost, choosen.getHostCard().getView()); optionalCost, choosen.getHostCard().getView());
} }
@Override @Override
public boolean confirmMulliganScry(Player p) { public boolean confirmMulliganScry(Player p) {
return InputConfirm.confirm(this, (SpellAbility)null, localizer.getMessage("lblDoYouWanttoScry")); return InputConfirm.confirm(this, (SpellAbility) null, localizer.getMessage("lblDoYouWanttoScry"));
} }
@Override @Override
@@ -3344,7 +3347,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
public CardCollection getCardList(Iterable<CardView> cardViews) { public CardCollection getCardList(Iterable<CardView> cardViews) {
CardCollection result = new CardCollection(); CardCollection result = new CardCollection();
for(CardView cardView : cardViews){ for (CardView cardView : cardViews) {
final Card c = this.getCard(cardView); final Card c = this.getCard(cardView);
if (c != null) { if (c != null) {
result.add(c); result.add(c);