mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
Get mobile game working again by implementing IGuiBase interface
This commit is contained in:
32
.gitattributes
vendored
32
.gitattributes
vendored
@@ -1064,6 +1064,7 @@ forge-gui-mobile/libs/gdx-sources.jar -text
|
|||||||
forge-gui-mobile/libs/gdx.jar -text
|
forge-gui-mobile/libs/gdx.jar -text
|
||||||
forge-gui-mobile/pom.xml -text
|
forge-gui-mobile/pom.xml -text
|
||||||
forge-gui-mobile/src/forge/Forge.java -text
|
forge-gui-mobile/src/forge/Forge.java -text
|
||||||
|
forge-gui-mobile/src/forge/GuiMobile.java -text
|
||||||
forge-gui-mobile/src/forge/assets/CardFaceSymbols.java -text
|
forge-gui-mobile/src/forge/assets/CardFaceSymbols.java -text
|
||||||
forge-gui-mobile/src/forge/assets/FImage.java -text
|
forge-gui-mobile/src/forge/assets/FImage.java -text
|
||||||
forge-gui-mobile/src/forge/assets/FSkin.java -text
|
forge-gui-mobile/src/forge/assets/FSkin.java -text
|
||||||
@@ -1129,37 +1130,8 @@ forge-gui-mobile/src/forge/screens/draft/DraftScreen.java -text
|
|||||||
forge-gui-mobile/src/forge/screens/guantlet/GuantletScreen.java -text
|
forge-gui-mobile/src/forge/screens/guantlet/GuantletScreen.java -text
|
||||||
forge-gui-mobile/src/forge/screens/home/HomeScreen.java -text
|
forge-gui-mobile/src/forge/screens/home/HomeScreen.java -text
|
||||||
forge-gui-mobile/src/forge/screens/match/FControl.java -text
|
forge-gui-mobile/src/forge/screens/match/FControl.java -text
|
||||||
forge-gui-mobile/src/forge/screens/match/FControlGameEventHandler.java -text
|
forge-gui-mobile/src/forge/screens/match/InputSelectCard.java -text
|
||||||
forge-gui-mobile/src/forge/screens/match/FControlGamePlayback.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/MatchScreen.java -text
|
forge-gui-mobile/src/forge/screens/match/MatchScreen.java -text
|
||||||
forge-gui-mobile/src/forge/screens/match/events/IUiEventVisitor.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/events/UiEvent.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/events/UiEventAttackerDeclared.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/events/UiEventBlockerAssigned.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/ButtonUtil.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/Input.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputAttack.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputBase.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputBlock.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputConfirm.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputConfirmMulligan.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputLockUI.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputPassPriority.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputPayMana.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputPayManaOfCostPayment.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputPayManaSimple.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputPayManaX.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputPlaybackControl.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputProliferate.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputProxy.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputQueue.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputSelectCardsForConvoke.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputSelectCardsFromList.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputSelectEntitiesFromList.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputSelectManyBase.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputSelectTargets.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputSynchronized.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/input/InputSyncronizedBase.java -text
|
|
||||||
forge-gui-mobile/src/forge/screens/match/views/VAssignDamage.java -text
|
forge-gui-mobile/src/forge/screens/match/views/VAssignDamage.java -text
|
||||||
forge-gui-mobile/src/forge/screens/match/views/VAvatar.java -text
|
forge-gui-mobile/src/forge/screens/match/views/VAvatar.java -text
|
||||||
forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java -text
|
forge-gui-mobile/src/forge/screens/match/views/VCardDisplayArea.java -text
|
||||||
|
|||||||
@@ -20,13 +20,6 @@
|
|||||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
</natures>
|
</natures>
|
||||||
<linkedResources>
|
|
||||||
<link>
|
|
||||||
<name>assets</name>
|
|
||||||
<type>2</type>
|
|
||||||
<locationURI>copy_PARENT/forge-gui/res</locationURI>
|
|
||||||
</link>
|
|
||||||
</linkedResources>
|
|
||||||
<variableList>
|
<variableList>
|
||||||
<variable>
|
<variable>
|
||||||
<name>copy_PARENT</name>
|
<name>copy_PARENT</name>
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ public class Forge implements ApplicationListener {
|
|||||||
}
|
}
|
||||||
game = this;
|
game = this;
|
||||||
clipboard = clipboard0;
|
clipboard = clipboard0;
|
||||||
|
GuiBase.setInterface(new GuiMobile());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
311
forge-gui-mobile/src/forge/GuiMobile.java
Normal file
311
forge-gui-mobile/src/forge/GuiMobile.java
Normal file
@@ -0,0 +1,311 @@
|
|||||||
|
package forge;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
import forge.assets.FSkin;
|
||||||
|
import forge.assets.FSkinProp;
|
||||||
|
import forge.assets.FTextureImage;
|
||||||
|
import forge.assets.ISkinImage;
|
||||||
|
import forge.deck.Deck;
|
||||||
|
import forge.deck.FDeckViewer;
|
||||||
|
import forge.error.BugReporter;
|
||||||
|
import forge.events.UiEvent;
|
||||||
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntity;
|
||||||
|
import forge.game.GameType;
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.combat.Combat;
|
||||||
|
import forge.game.event.GameEventTurnBegan;
|
||||||
|
import forge.game.phase.PhaseHandler;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.LobbyPlayer;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.player.RegisteredPlayer;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.interfaces.IButton;
|
||||||
|
import forge.interfaces.IGuiBase;
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.match.input.InputQueue;
|
||||||
|
import forge.screens.match.FControl;
|
||||||
|
import forge.screens.match.views.VPhaseIndicator.PhaseLabel;
|
||||||
|
import forge.screens.match.winlose.ViewWinLose;
|
||||||
|
import forge.toolbox.FOptionPane;
|
||||||
|
import forge.toolbox.GuiChoose;
|
||||||
|
import forge.util.ThreadUtil;
|
||||||
|
|
||||||
|
public class GuiMobile implements IGuiBase {
|
||||||
|
@Override
|
||||||
|
public void invokeInEdtLater(Runnable proc) {
|
||||||
|
Gdx.app.postRunnable(proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invokeInEdtAndWait(final Runnable proc) {
|
||||||
|
if (isGuiThread()) {
|
||||||
|
// Just run in the current thread.
|
||||||
|
proc.run();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGuiThread() {
|
||||||
|
return !ThreadUtil.isGameThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getInstallRoot() {
|
||||||
|
switch (Gdx.app.getType()) {
|
||||||
|
case Desktop:
|
||||||
|
return "../forge-gui/";
|
||||||
|
case Android:
|
||||||
|
break;
|
||||||
|
case Applet:
|
||||||
|
break;
|
||||||
|
case WebGL:
|
||||||
|
break;
|
||||||
|
case iOS:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAssetsDir() {
|
||||||
|
return "res/";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mayShowCard(Card card) {
|
||||||
|
return FControl.mayShowCard(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reportBug(String details) {
|
||||||
|
BugReporter.reportBug(details);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reportException(Throwable ex) {
|
||||||
|
BugReporter.reportException(ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reportException(Throwable ex, String message) {
|
||||||
|
BugReporter.reportException(ex, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ISkinImage getUnskinnedIcon(String path) {
|
||||||
|
return new FTextureImage(new Texture(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int showOptionDialog(String message, String title, FSkinProp icon, String[] options, int defaultOption) {
|
||||||
|
return FOptionPane.showOptionDialog(message, title, icon == null ? null : FSkin.getImages().get(icon), options, defaultOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> T showInputDialog(String message, String title, FSkinProp icon, T initialInput, T[] inputOptions) {
|
||||||
|
return FOptionPane.showInputDialog(message, title, icon == null ? null : FSkin.getImages().get(icon), initialInput, inputOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> getChoices(final String message, final int min, final int max, final Collection<T> choices, final T selected, final Function<T, String> display) {
|
||||||
|
return GuiChoose.getChoices(message, min, max, choices, selected, display);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> List<T> order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax,
|
||||||
|
final List<T> sourceChoices, final List<T> destChoices, final Card referenceCard, final boolean sideboardingMode) {
|
||||||
|
return GuiChoose.order(title, top, remainingObjectsMin, remainingObjectsMax, sourceChoices, destChoices, referenceCard, sideboardingMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showCardList(final String title, final String message, final List<PaperCard> list) {
|
||||||
|
Deck deck = new Deck(title + " - " + message);
|
||||||
|
deck.getMain().addAllFlat(list);
|
||||||
|
FDeckViewer.show(deck);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IButton getBtnOK() {
|
||||||
|
return FControl.getView().getPrompt().getBtnOk();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IButton getBtnCancel() {
|
||||||
|
return FControl.getView().getPrompt().getBtnCancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void focusButton(final IButton button) {
|
||||||
|
//not needed for mobile game
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flashIncorrectAction() {
|
||||||
|
//SDisplayUtil.remind(VPrompt.SINGLETON_INSTANCE); //TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePhase() {
|
||||||
|
PhaseHandler pH = FControl.getGame().getPhaseHandler();
|
||||||
|
Player p = pH.getPlayerTurn();
|
||||||
|
PhaseType ph = pH.getPhase();
|
||||||
|
|
||||||
|
PhaseLabel lbl = FControl.getPlayerPanel(p).getPhaseIndicator().getLabel(ph);
|
||||||
|
|
||||||
|
FControl.resetAllPhaseButtons();
|
||||||
|
if (lbl != null) {
|
||||||
|
lbl.setActive(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateTurn(final GameEventTurnBegan event, final Game game) {
|
||||||
|
//VField nextField = FControl.getFieldViewFor(event.turnOwner);
|
||||||
|
//SDisplayUtil.showTab(nextField);
|
||||||
|
FControl.getView().getPrompt().updateText(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updatePlayerControl() {
|
||||||
|
//TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void finishGame() {
|
||||||
|
new ViewWinLose(FControl.getGame()).setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStack() {
|
||||||
|
FControl.getView().getStack().update();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void startMatch(GameType gameType, List<RegisteredPlayer> players) {
|
||||||
|
FControl.startMatch(gameType, players);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPanelSelection(Card c) {
|
||||||
|
//GuiUtils.setPanelSelection(c); //TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SpellAbility getAbilityToPlay(List<SpellAbility> abilities, Object triggerEvent) {
|
||||||
|
if (abilities.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (abilities.size() == 1) {
|
||||||
|
return abilities.get(0);
|
||||||
|
}
|
||||||
|
return GuiChoose.oneOrNone("Choose ability to play", abilities);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void hear(LobbyPlayer player, String message) {
|
||||||
|
//FNetOverlay.SINGLETON_INSTANCE.addMessage(player.getName(), message); //TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAvatarCount() {
|
||||||
|
if (FSkin.isLoaded()) {
|
||||||
|
return FSkin.getAvatars().size();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fireEvent(UiEvent e) {
|
||||||
|
FControl.fireEvent(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCard(Card card) {
|
||||||
|
FControl.setCard(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showCombat(Combat combat) {
|
||||||
|
FControl.showCombat(combat);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUsedToPay(Card card, boolean b) {
|
||||||
|
FControl.setUsedToPay(card, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHighlighted(Player player, boolean b) {
|
||||||
|
FControl.setHighlighted(player, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showPromptMessage(String message) {
|
||||||
|
FControl.showMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean stopAtPhase(Player playerTurn, PhaseType phase) {
|
||||||
|
return FControl.stopAtPhase(playerTurn, phase);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputQueue getInputQueue() {
|
||||||
|
return FControl.getInputQueue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Game getGame() {
|
||||||
|
return FControl.getGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateZones(List<Pair<Player, ZoneType>> zonesToUpdate) {
|
||||||
|
FControl.updateZones(zonesToUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateCards(Set<Card> cardsToUpdate) {
|
||||||
|
FControl.updateCards(cardsToUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateManaPool(List<Player> manaPoolUpdate) {
|
||||||
|
FControl.updateManaPool(manaPoolUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateLives(List<Player> livesUpdate) {
|
||||||
|
FControl.updateLives(livesUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void endCurrentGame() {
|
||||||
|
FControl.endCurrentGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<Card, Integer> getDamageToAssign(Card attacker, List<Card> blockers,
|
||||||
|
int damageDealt, GameEntity defender, boolean overrideOrder) {
|
||||||
|
return FControl.getDamageToAssign(attacker, blockers,
|
||||||
|
damageDealt, defender, overrideOrder);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package forge.assets;
|
|||||||
|
|
||||||
import forge.Forge.Graphics;
|
import forge.Forge.Graphics;
|
||||||
|
|
||||||
public interface FImage {
|
public interface FImage extends ISkinImage {
|
||||||
float getWidth();
|
float getWidth();
|
||||||
float getHeight();
|
float getHeight();
|
||||||
void draw(Graphics g, float x, float y, float w, float h);
|
void draw(Graphics g, float x, float y, float w, float h);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import java.util.Map;
|
|||||||
|
|
||||||
import org.apache.commons.lang3.text.WordUtils;
|
import org.apache.commons.lang3.text.WordUtils;
|
||||||
|
|
||||||
import com.badlogic.gdx.Application.ApplicationType;
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
@@ -17,17 +16,13 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
|||||||
|
|
||||||
import forge.assets.FSkinImage.SourceFile;
|
import forge.assets.FSkinImage.SourceFile;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
|
import forge.properties.ForgeConstants;
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.SplashScreen;
|
import forge.screens.SplashScreen;
|
||||||
import forge.toolbox.FProgressBar;
|
import forge.toolbox.FProgressBar;
|
||||||
|
|
||||||
public class FSkin {
|
public class FSkin {
|
||||||
private static final String
|
|
||||||
FILE_SKINS_DIR = "skins/",
|
|
||||||
FILE_AVATAR_SPRITE = "sprite_avatars.png",
|
|
||||||
DEFAULT_DIR = FILE_SKINS_DIR + "default/";
|
|
||||||
|
|
||||||
private static final Map<FSkinProp, FSkinImage> images = new HashMap<FSkinProp, FSkinImage>();
|
private static final Map<FSkinProp, FSkinImage> images = new HashMap<FSkinProp, FSkinImage>();
|
||||||
private static final Map<Integer, TextureRegion> avatars = new HashMap<Integer, TextureRegion>();
|
private static final Map<Integer, TextureRegion> avatars = new HashMap<Integer, TextureRegion>();
|
||||||
|
|
||||||
@@ -72,12 +67,12 @@ public class FSkin {
|
|||||||
|
|
||||||
// Non-default (preferred) skin name and dir.
|
// Non-default (preferred) skin name and dir.
|
||||||
preferredName = skinName.toLowerCase().replace(' ', '_');
|
preferredName = skinName.toLowerCase().replace(' ', '_');
|
||||||
preferredDir = FILE_SKINS_DIR + preferredName + "/";
|
preferredDir = ForgeConstants.SKINS_DIR + preferredName + "/";
|
||||||
|
|
||||||
FSkinTexture.BG_TEXTURE.load(preferredDir, DEFAULT_DIR); //load background texture early for splash screen
|
FSkinTexture.BG_TEXTURE.load(preferredDir, ForgeConstants.DEFAULT_SKINS_DIR); //load background texture early for splash screen
|
||||||
|
|
||||||
if (splashScreen != null) {
|
if (splashScreen != null) {
|
||||||
final FileHandle f = Gdx.files.internal(preferredDir + "bg_splash.png");
|
final FileHandle f = Gdx.files.local(preferredDir + "bg_splash.png");
|
||||||
if (!f.exists()) {
|
if (!f.exists()) {
|
||||||
if (!skinName.equals("default")) {
|
if (!skinName.equals("default")) {
|
||||||
FSkin.loadLight("default", splashScreen);
|
FSkin.loadLight("default", splashScreen);
|
||||||
@@ -138,12 +133,13 @@ public class FSkin {
|
|||||||
//FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("Processing image sprites: ", 5);
|
//FView.SINGLETON_INSTANCE.setSplashProgessBarMessage("Processing image sprites: ", 5);
|
||||||
|
|
||||||
// Grab and test various sprite files.
|
// Grab and test various sprite files.
|
||||||
final FileHandle f1 = Gdx.files.internal(DEFAULT_DIR + SourceFile.ICONS.getFilename());
|
String defaultDir = ForgeConstants.DEFAULT_SKINS_DIR;
|
||||||
final FileHandle f2 = Gdx.files.internal(preferredDir + SourceFile.ICONS.getFilename());
|
final FileHandle f1 = Gdx.files.local(defaultDir + SourceFile.ICONS.getFilename());
|
||||||
final FileHandle f3 = Gdx.files.internal(DEFAULT_DIR + SourceFile.FOILS.getFilename());
|
final FileHandle f2 = Gdx.files.local(preferredDir + SourceFile.ICONS.getFilename());
|
||||||
final FileHandle f4 = Gdx.files.internal(DEFAULT_DIR + FILE_AVATAR_SPRITE);
|
final FileHandle f3 = Gdx.files.local(defaultDir + SourceFile.FOILS.getFilename());
|
||||||
final FileHandle f5 = Gdx.files.internal(preferredDir + FILE_AVATAR_SPRITE);
|
final FileHandle f4 = Gdx.files.local(defaultDir + ForgeConstants.SPRITE_AVATARS_FILE);
|
||||||
final FileHandle f6 = Gdx.files.internal(DEFAULT_DIR + SourceFile.OLD_FOILS.getFilename());
|
final FileHandle f5 = Gdx.files.local(preferredDir + ForgeConstants.SPRITE_AVATARS_FILE);
|
||||||
|
final FileHandle f6 = Gdx.files.local(defaultDir + SourceFile.OLD_FOILS.getFilename());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
textures.put(f1.path(), new Texture(f1));
|
textures.put(f1.path(), new Texture(f1));
|
||||||
@@ -168,9 +164,9 @@ public class FSkin {
|
|||||||
|
|
||||||
//load images
|
//load images
|
||||||
for (FSkinImage image : FSkinImage.values()) {
|
for (FSkinImage image : FSkinImage.values()) {
|
||||||
image.load(preferredDir, DEFAULT_DIR, textures, preferredIcons);
|
image.load(preferredDir, ForgeConstants.DEFAULT_SKINS_DIR, textures, preferredIcons);
|
||||||
}
|
}
|
||||||
FSkinTexture.BG_MATCH.load(preferredDir, DEFAULT_DIR);
|
FSkinTexture.BG_MATCH.load(preferredDir, ForgeConstants.DEFAULT_SKINS_DIR);
|
||||||
|
|
||||||
//assemble avatar textures
|
//assemble avatar textures
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
@@ -302,13 +298,7 @@ public class FSkin {
|
|||||||
public static ArrayList<String> getSkinDirectoryNames() {
|
public static ArrayList<String> getSkinDirectoryNames() {
|
||||||
final ArrayList<String> mySkins = new ArrayList<String>();
|
final ArrayList<String> mySkins = new ArrayList<String>();
|
||||||
|
|
||||||
final FileHandle dir;
|
final FileHandle dir = Gdx.files.local(ForgeConstants.SKINS_DIR);
|
||||||
if (Gdx.app.getType() == ApplicationType.Desktop) {
|
|
||||||
dir = Gdx.files.internal("./bin/" + FILE_SKINS_DIR); //needed to iterate over directory for Desktop
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
dir = Gdx.files.internal(FILE_SKINS_DIR);
|
|
||||||
}
|
|
||||||
if (!dir.exists() || !dir.isDirectory()) {
|
if (!dir.exists() || !dir.isDirectory()) {
|
||||||
System.err.println("FSkin > can't find skins directory!");
|
System.err.println("FSkin > can't find skins directory!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,12 @@ import com.google.common.eventbus.Subscribe;
|
|||||||
import forge.FThreads;
|
import forge.FThreads;
|
||||||
import forge.Forge;
|
import forge.Forge;
|
||||||
import forge.card.CardCharacteristicName;
|
import forge.card.CardCharacteristicName;
|
||||||
|
import forge.control.FControlGameEventHandler;
|
||||||
|
import forge.control.FControlGamePlayback;
|
||||||
|
import forge.events.IUiEventVisitor;
|
||||||
|
import forge.events.UiEvent;
|
||||||
|
import forge.events.UiEventAttackerDeclared;
|
||||||
|
import forge.events.UiEventBlockerAssigned;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
import forge.game.GameEntity;
|
import forge.game.GameEntity;
|
||||||
import forge.game.GameRules;
|
import forge.game.GameRules;
|
||||||
@@ -41,16 +47,12 @@ import forge.game.player.RegisteredPlayer;
|
|||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.Zone;
|
import forge.game.zone.Zone;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.match.input.InputProxy;
|
||||||
|
import forge.match.input.InputQueue;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
import forge.net.FServer;
|
import forge.net.FServer;
|
||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.match.events.IUiEventVisitor;
|
|
||||||
import forge.screens.match.events.UiEvent;
|
|
||||||
import forge.screens.match.events.UiEventAttackerDeclared;
|
|
||||||
import forge.screens.match.events.UiEventBlockerAssigned;
|
|
||||||
import forge.screens.match.input.InputProxy;
|
|
||||||
import forge.screens.match.input.InputQueue;
|
|
||||||
import forge.screens.match.views.VAssignDamage;
|
import forge.screens.match.views.VAssignDamage;
|
||||||
import forge.screens.match.views.VCardDisplayArea.CardAreaPanel;
|
import forge.screens.match.views.VCardDisplayArea.CardAreaPanel;
|
||||||
import forge.screens.match.views.VPhaseIndicator;
|
import forge.screens.match.views.VPhaseIndicator;
|
||||||
|
|||||||
@@ -1,388 +0,0 @@
|
|||||||
package forge.screens.match;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
|
||||||
|
|
||||||
import forge.FThreads;
|
|
||||||
import forge.game.Game;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.event.*;
|
|
||||||
import forge.game.phase.PhaseHandler;
|
|
||||||
import forge.game.phase.PhaseType;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.zone.PlayerZone;
|
|
||||||
import forge.game.zone.Zone;
|
|
||||||
import forge.game.zone.ZoneType;
|
|
||||||
import forge.net.FServer;
|
|
||||||
import forge.screens.match.views.VPhaseIndicator.PhaseLabel;
|
|
||||||
import forge.screens.match.winlose.ViewWinLose;
|
|
||||||
import forge.toolbox.GuiChoose;
|
|
||||||
import forge.util.Lang;
|
|
||||||
import forge.util.maps.MapOfLists;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
public class FControlGameEventHandler extends IGameEventVisitor.Base<Void> {
|
|
||||||
public FControlGameEventHandler() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void receiveGameEvent(final GameEvent ev) {
|
|
||||||
ev.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final AtomicBoolean phaseUpdPlanned = new AtomicBoolean(false);
|
|
||||||
@Override
|
|
||||||
public Void visit(final GameEventTurnPhase ev) {
|
|
||||||
if (phaseUpdPlanned.getAndSet(true)) return null;
|
|
||||||
|
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() {
|
|
||||||
PhaseHandler pH = FControl.getGame().getPhaseHandler();
|
|
||||||
Player p = pH.getPlayerTurn();
|
|
||||||
PhaseType ph = pH.getPhase();
|
|
||||||
|
|
||||||
phaseUpdPlanned.set(false);
|
|
||||||
|
|
||||||
PhaseLabel lbl = FControl.getPlayerPanel(p).getPhaseIndicator().getLabel(ph);
|
|
||||||
|
|
||||||
FControl.resetAllPhaseButtons();
|
|
||||||
if (lbl != null) { lbl.setActive(true); }
|
|
||||||
} });
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventPlayerPriority)
|
|
||||||
*/
|
|
||||||
private final AtomicBoolean combatUpdPlanned = new AtomicBoolean(false);
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventPlayerPriority event) {
|
|
||||||
if (combatUpdPlanned.getAndSet(true)) { return null; }
|
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
combatUpdPlanned.set(false);
|
|
||||||
FControl.showCombat(FControl.getGame().getCombat());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final AtomicBoolean turnUpdPlanned = new AtomicBoolean(false);
|
|
||||||
@Override
|
|
||||||
public Void visit(final GameEventTurnBegan event) {
|
|
||||||
if (turnUpdPlanned.getAndSet(true)) { return null; }
|
|
||||||
|
|
||||||
final Game game = FControl.getGame(); // to make sure control gets a correct game instance
|
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
/*VField nextField = FControl.getFieldViewFor(event.turnOwner);
|
|
||||||
SDisplayUtil.showTab(nextField);*/
|
|
||||||
|
|
||||||
turnUpdPlanned.set(false);
|
|
||||||
FControl.getView().getPrompt().updateText(game);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventAnteCardsSelected ev) {
|
|
||||||
// Require EDT here?
|
|
||||||
List<Object> options = new ArrayList<Object>();
|
|
||||||
for (final Entry<Player, Card> kv : ((GameEventAnteCardsSelected) ev).cards.entries()) {
|
|
||||||
options.add(" -- From " + Lang.getPossesive(kv.getKey().getName()) + " deck --");
|
|
||||||
options.add(kv.getValue());
|
|
||||||
}
|
|
||||||
GuiChoose.one("These cards were chosen to ante", options);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventPlayerControl ev) {
|
|
||||||
if (FControl.getGame().isGameOver()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() {
|
|
||||||
/*FControl.initHandViews(FServer.getLobby().getGuiPlayer());
|
|
||||||
SLayoutIO.loadLayout(null);
|
|
||||||
VMatchUI.SINGLETON_INSTANCE.populate();
|
|
||||||
for (VHand h : VMatchUI.SINGLETON_INSTANCE.getHands()) {
|
|
||||||
h.getLayoutControl().updateHand();
|
|
||||||
}*/
|
|
||||||
} });
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Runnable unlockGameThreadOnGameOver = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
FControl.getInputQueue().onGameOver(true); // this will unlock any game threads waiting for inputs to complete
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventGameOutcome ev) {
|
|
||||||
FThreads.invokeInEdtNowOrLater(unlockGameThreadOnGameOver);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventGameFinished ev) {
|
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
new ViewWinLose(FControl.getGame()).setVisible(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final AtomicBoolean stackUpdPlanned = new AtomicBoolean(false);
|
|
||||||
private final Runnable updStack = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
stackUpdPlanned.set(false);
|
|
||||||
FControl.getView().getStack().update();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventSpellAbilityCast event) {
|
|
||||||
if (!stackUpdPlanned.getAndSet(true)) {
|
|
||||||
FThreads.invokeInEdtNowOrLater(updStack);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventSpellResolved event) {
|
|
||||||
if (!stackUpdPlanned.getAndSet(true)) {
|
|
||||||
FThreads.invokeInEdtNowOrLater(updStack);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventSpellRemovedFromStack event) {
|
|
||||||
if (!stackUpdPlanned.getAndSet(true)) {
|
|
||||||
FThreads.invokeInEdtNowOrLater(updStack);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final List<Pair<Player, ZoneType>> zonesToUpdate = new Vector<Pair<Player, ZoneType>>();
|
|
||||||
private final Runnable updZones = new Runnable() {
|
|
||||||
@Override public void run() {
|
|
||||||
synchronized (zonesToUpdate) {
|
|
||||||
FControl.updateZones(zonesToUpdate);
|
|
||||||
zonesToUpdate.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventZone event) {
|
|
||||||
if (event.player != null) {
|
|
||||||
// anything except stack will get here
|
|
||||||
updateZone(Pair.of(event.player, event.zoneType));
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventCardAttachment event) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
Game game = event.equipment.getGame();
|
|
||||||
PlayerZone zEq = (PlayerZone)game.getZoneOf(event.equipment);
|
|
||||||
if (event.oldEntiy instanceof Card) {
|
|
||||||
updateZone(game.getZoneOf((Card)event.oldEntiy));
|
|
||||||
}
|
|
||||||
if (event.newTarget instanceof Card) {
|
|
||||||
updateZone(game.getZoneOf((Card)event.newTarget));
|
|
||||||
}
|
|
||||||
return updateZone(zEq);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Void updateZone(Zone z) {
|
|
||||||
return updateZone(Pair.of(z.getPlayer(), z.getZoneType()));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Void updateZone(Pair<Player, ZoneType> kv) {
|
|
||||||
boolean needUpdate = false;
|
|
||||||
synchronized (zonesToUpdate) {
|
|
||||||
needUpdate = zonesToUpdate.isEmpty();
|
|
||||||
if (!zonesToUpdate.contains(kv)) {
|
|
||||||
zonesToUpdate.add(kv);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (needUpdate) {
|
|
||||||
FThreads.invokeInEdtNowOrLater(updZones);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final Set<Card> cardsToUpdate = new HashSet<Card>();
|
|
||||||
private final Runnable updCards = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
synchronized (cardsToUpdate) {
|
|
||||||
FControl.updateCards(cardsToUpdate);
|
|
||||||
cardsToUpdate.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventCardTapped event) {
|
|
||||||
return updateSingleCard(event.card);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventCardPhased event) {
|
|
||||||
return updateSingleCard(event.card);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventCardDamaged event) {
|
|
||||||
return updateSingleCard(event.card);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventCardCounters event) {
|
|
||||||
return updateSingleCard(event.card);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventBlockersDeclared event) { // This is to draw icons on blockers declared by AI
|
|
||||||
for (MapOfLists<Card, Card> kv : event.blockers.values()) {
|
|
||||||
for (Collection<Card> blockers : kv.values()) {
|
|
||||||
updateManyCards(blockers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.visit(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventAttackersDeclared event) {
|
|
||||||
// Skip redraw for GUI player?
|
|
||||||
if (event.player.getLobbyPlayer() == FServer.getLobby().getGuiPlayer()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update all attackers.
|
|
||||||
// Although they might have been updated when they were apped, there could be someone with vigilance, not redrawn yet.
|
|
||||||
updateManyCards(event.attackersMap.values());
|
|
||||||
|
|
||||||
return super.visit(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventCombatEnded event) {
|
|
||||||
// This should remove sword/shield icons from combatants by the time game moves to M2
|
|
||||||
updateManyCards(event.attackers);
|
|
||||||
updateManyCards(event.blockers);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Void updateSingleCard(Card c) {
|
|
||||||
boolean needUpdate = false;
|
|
||||||
synchronized (cardsToUpdate) {
|
|
||||||
needUpdate = cardsToUpdate.isEmpty();
|
|
||||||
if (!cardsToUpdate.contains(c)) {
|
|
||||||
cardsToUpdate.add(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (needUpdate) {
|
|
||||||
FThreads.invokeInEdtNowOrLater(updCards);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Void updateManyCards(Collection<Card> cc) {
|
|
||||||
boolean needUpdate = false;
|
|
||||||
synchronized (cardsToUpdate) {
|
|
||||||
needUpdate = cardsToUpdate.isEmpty();
|
|
||||||
cardsToUpdate.addAll(cc);
|
|
||||||
}
|
|
||||||
if (needUpdate) {
|
|
||||||
FThreads.invokeInEdtNowOrLater(updCards);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventCardStatsChanged)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventCardStatsChanged event) {
|
|
||||||
// TODO Smart partial updates
|
|
||||||
return updateManyCards(event.cards);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update manapool
|
|
||||||
private final List<Player> manaPoolUpdate = new Vector<Player>();
|
|
||||||
private final Runnable updManaPool = new Runnable() {
|
|
||||||
@Override public void run() {
|
|
||||||
synchronized (manaPoolUpdate) {
|
|
||||||
FControl.updateManaPool(manaPoolUpdate);
|
|
||||||
manaPoolUpdate.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventManaPool event) {
|
|
||||||
boolean invokeUpdate = false;
|
|
||||||
synchronized (manaPoolUpdate) {
|
|
||||||
if (!manaPoolUpdate.contains(event.player)) {
|
|
||||||
invokeUpdate = manaPoolUpdate.isEmpty();
|
|
||||||
manaPoolUpdate.add(event.player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (invokeUpdate)
|
|
||||||
FThreads.invokeInEdtNowOrLater(updManaPool);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update lives counters
|
|
||||||
private final List<Player> livesUpdate = new Vector<Player>();
|
|
||||||
private final Runnable updLives = new Runnable() {
|
|
||||||
@Override public void run() {
|
|
||||||
synchronized (livesUpdate) {
|
|
||||||
FControl.updateLives(livesUpdate);
|
|
||||||
livesUpdate.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventPlayerLivesChanged event) {
|
|
||||||
boolean invokeUpdate = false;
|
|
||||||
synchronized (livesUpdate) {
|
|
||||||
if (!livesUpdate.contains(event.player)) {
|
|
||||||
invokeUpdate = livesUpdate.isEmpty();
|
|
||||||
livesUpdate.add(event.player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (invokeUpdate)
|
|
||||||
FThreads.invokeInEdtNowOrLater(updLives);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventPlayerPoisoned event) {
|
|
||||||
boolean invokeUpdate = false;
|
|
||||||
synchronized (livesUpdate) {
|
|
||||||
if (!livesUpdate.contains(event.receiver)) {
|
|
||||||
invokeUpdate = livesUpdate.isEmpty();
|
|
||||||
livesUpdate.add(event.receiver);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (invokeUpdate)
|
|
||||||
FThreads.invokeInEdtNowOrLater(updLives);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
package forge.screens.match;
|
|
||||||
|
|
||||||
import com.google.common.eventbus.Subscribe;
|
|
||||||
|
|
||||||
import forge.FThreads;
|
|
||||||
import forge.game.event.*;
|
|
||||||
import forge.screens.match.input.InputPlaybackControl;
|
|
||||||
|
|
||||||
import java.util.concurrent.BrokenBarrierException;
|
|
||||||
import java.util.concurrent.CyclicBarrier;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
public class FControlGamePlayback extends IGameEventVisitor.Base<Void> {
|
|
||||||
private final InputPlaybackControl inputPlayback = new InputPlaybackControl(this);
|
|
||||||
private final AtomicBoolean paused = new AtomicBoolean(false);
|
|
||||||
|
|
||||||
private final CyclicBarrier gameThreadPauser = new CyclicBarrier(2);
|
|
||||||
|
|
||||||
public FControlGamePlayback() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Subscribe
|
|
||||||
public void receiveGameEvent(final GameEvent ev) { ev.visit(this); }
|
|
||||||
|
|
||||||
private int phasesDelay = 200;
|
|
||||||
private int combatDelay = 400;
|
|
||||||
private int castDelay = 400;
|
|
||||||
private int resolveDelay = 400;
|
|
||||||
|
|
||||||
private boolean fasterPlayback = false;
|
|
||||||
|
|
||||||
private void pauseForEvent(int delay) {
|
|
||||||
try {
|
|
||||||
Thread.sleep(fasterPlayback ? delay / 10 : delay);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventBlockersDeclared event) {
|
|
||||||
pauseForEvent(combatDelay);
|
|
||||||
return super.visit(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventTurnPhase)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventTurnPhase ev) {
|
|
||||||
boolean isUiToStop = FControl.stopAtPhase(ev.playerTurn, ev.phase);
|
|
||||||
|
|
||||||
switch(ev.phase) {
|
|
||||||
case COMBAT_END:
|
|
||||||
case COMBAT_DECLARE_ATTACKERS:
|
|
||||||
case COMBAT_DECLARE_BLOCKERS:
|
|
||||||
if (FControl.getGame().getPhaseHandler().inCombat()) {
|
|
||||||
pauseForEvent(combatDelay);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (isUiToStop) {
|
|
||||||
pauseForEvent(phasesDelay);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventDuelFinished)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventGameFinished event) {
|
|
||||||
FControl.getInputQueue().removeInput(inputPlayback);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventGameStarted event) {
|
|
||||||
FControl.getInputQueue().setInput(inputPlayback);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventLandPlayed event) {
|
|
||||||
pauseForEvent(resolveDelay);
|
|
||||||
return super.visit(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Void visit(final GameEventSpellResolved event) {
|
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { FControl.setCard(event.spell.getHostCard()); } });
|
|
||||||
pauseForEvent(resolveDelay);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventSpellAbilityCast)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Void visit(final GameEventSpellAbilityCast event) {
|
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() { @Override public void run() { FControl.setCard(event.sa.getHostCard()); } });
|
|
||||||
pauseForEvent(castDelay);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see forge.game.event.IGameEventVisitor.Base#visit(forge.game.event.GameEventPlayerPriority)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Void visit(GameEventPlayerPriority event) {
|
|
||||||
if (paused.get()) {
|
|
||||||
try {
|
|
||||||
inputPlayback.onGamePaused();
|
|
||||||
gameThreadPauser.await();
|
|
||||||
gameThreadPauser.reset();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (BrokenBarrierException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onGameStopRequested() {
|
|
||||||
paused.set(false);
|
|
||||||
if (gameThreadPauser.getNumberWaiting() != 0) {
|
|
||||||
releaseGameThread();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void releaseGameThread() {
|
|
||||||
// just need to run another thread through the barrier... not edt preferrably :)
|
|
||||||
|
|
||||||
FControl.getGame().getAction().invoke(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
gameThreadPauser.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
// TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (BrokenBarrierException e) {
|
|
||||||
// TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resume() {
|
|
||||||
paused.set(false);
|
|
||||||
releaseGameThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pause() {
|
|
||||||
paused.set(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void singleStep() {
|
|
||||||
releaseGameThread();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Write javadoc for this method.
|
|
||||||
* @param isFast
|
|
||||||
*/
|
|
||||||
public void setSpeed(boolean isFast) {
|
|
||||||
fasterPlayback = isFast;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package forge.screens.match;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import forge.game.card.Card;
|
||||||
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.match.input.Input;
|
||||||
|
import forge.match.input.InputPassPriority;
|
||||||
|
import forge.toolbox.FCardZoom;
|
||||||
|
import forge.toolbox.FCardZoom.ZoomController;
|
||||||
|
|
||||||
|
public class InputSelectCard {
|
||||||
|
private InputSelectCard() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void selectCard(Card card, List<Card> orderedCards) {
|
||||||
|
Input currentInput = FControl.getInputQueue().getInput();
|
||||||
|
if (currentInput == null) { return; }
|
||||||
|
|
||||||
|
List<Card> orderedCardOptions = new ArrayList<Card>(orderedCards); //copy list to allow it being modified
|
||||||
|
|
||||||
|
if (currentInput instanceof InputPassPriority) {
|
||||||
|
FCardZoom.show("Select a spell/ability", card, orderedCardOptions, new ZoomController<SpellAbility>() {
|
||||||
|
@Override
|
||||||
|
public List<SpellAbility> getOptions(final Card card) {
|
||||||
|
return card.getAllPossibleAbilities(FControl.getCurrentPlayer(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean selectOption(final Card card, final SpellAbility option) {
|
||||||
|
FControl.getInputProxy().selectAbility(option);
|
||||||
|
return true; //TODO: Avoid hiding card zoom when selecting mana abilities
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
FControl.getInputProxy().selectCard(card, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package forge.screens.match.events;
|
|
||||||
|
|
||||||
public interface IUiEventVisitor<T> {
|
|
||||||
T visit(UiEventBlockerAssigned event);
|
|
||||||
T visit(UiEventAttackerDeclared event);
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package forge.screens.match.events;
|
|
||||||
|
|
||||||
|
|
||||||
public abstract class UiEvent {
|
|
||||||
|
|
||||||
public abstract <T> T visit(IUiEventVisitor<T> visitor);
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package forge.screens.match.events;
|
|
||||||
|
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Write javadoc for this type.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class UiEventAttackerDeclared extends UiEvent {
|
|
||||||
|
|
||||||
public final Card attacker;
|
|
||||||
public final GameEntity defender;
|
|
||||||
|
|
||||||
public UiEventAttackerDeclared(Card card, GameEntity currentDefender) {
|
|
||||||
attacker = card;
|
|
||||||
defender = currentDefender;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T visit(IUiEventVisitor<T> visitor) {
|
|
||||||
return visitor.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see java.lang.Object#toString()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return attacker.toString() + ( defender == null ? " removed from combat" : " declared to attack " + defender.getName() );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package forge.screens.match.events;
|
|
||||||
|
|
||||||
import forge.game.card.Card;
|
|
||||||
|
|
||||||
public class UiEventBlockerAssigned extends UiEvent {
|
|
||||||
|
|
||||||
public final Card blocker;
|
|
||||||
public final Card attackerBeingBlocked;
|
|
||||||
|
|
||||||
public UiEventBlockerAssigned(Card card, Card currentAttacker) {
|
|
||||||
blocker = card;
|
|
||||||
attackerBeingBlocked = currentAttacker;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T visit(IUiEventVisitor<T> visitor) {
|
|
||||||
return visitor.visit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
import forge.toolbox.FButton;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages match UI OK/Cancel button enabling and focus
|
|
||||||
*/
|
|
||||||
public class ButtonUtil {
|
|
||||||
public static void setButtonText(String okLabel, String cancelLabel) {
|
|
||||||
getOk().setText(okLabel);
|
|
||||||
getCancel().setText(cancelLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void reset() {
|
|
||||||
disableAll();
|
|
||||||
getOk().setText("OK");
|
|
||||||
getCancel().setText("Cancel");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enableAll() {
|
|
||||||
getOk().setEnabled(true);
|
|
||||||
getCancel().setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void disableAll() {
|
|
||||||
getOk().setEnabled(false);
|
|
||||||
getCancel().setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enableOnlyOk() {
|
|
||||||
getOk().setEnabled(true);
|
|
||||||
getCancel().setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void enableOnlyCancel() {
|
|
||||||
getOk().setEnabled(false);
|
|
||||||
getCancel().setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FButton getOk() {
|
|
||||||
return FControl.getView().getPrompt().getBtnOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FButton getCancel() {
|
|
||||||
return FControl.getView().getPrompt().getBtnCancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
|
|
||||||
public interface Input {
|
|
||||||
|
|
||||||
// showMessage() is always the first method called
|
|
||||||
void showMessageInitial();
|
|
||||||
|
|
||||||
void selectCard(final Card card, final List<Card> orderedCardOptions);
|
|
||||||
|
|
||||||
void selectAbility(final SpellAbility ab);
|
|
||||||
|
|
||||||
void selectPlayer(final Player player);
|
|
||||||
|
|
||||||
void selectButtonOK();
|
|
||||||
|
|
||||||
void selectButtonCancel();
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,274 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.card.CardPredicates;
|
|
||||||
import forge.game.combat.AttackingBand;
|
|
||||||
import forge.game.combat.Combat;
|
|
||||||
import forge.game.combat.CombatUtil;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.zone.ZoneType;
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
import forge.screens.match.events.UiEventAttackerDeclared;
|
|
||||||
import forge.toolbox.FCardZoom;
|
|
||||||
import forge.toolbox.FCardZoom.ZoomController;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* InputAttack class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id: InputAttack.java 24769 2014-02-09 13:56:04Z Hellfish $
|
|
||||||
*/
|
|
||||||
public class InputAttack extends InputSyncronizedBase {
|
|
||||||
/** Constant <code>serialVersionUID=7849903731842214245L</code>. */
|
|
||||||
private static final long serialVersionUID = 7849903731842214245L;
|
|
||||||
|
|
||||||
private final Combat combat;
|
|
||||||
private final List<GameEntity> defenders;
|
|
||||||
private GameEntity currentDefender;
|
|
||||||
private final Player playerAttacks;
|
|
||||||
private final Player playerDeclares;
|
|
||||||
private AttackingBand activeBand = null;
|
|
||||||
|
|
||||||
public InputAttack(Player attacks, Player declares, Combat combat) {
|
|
||||||
this.playerAttacks = attacks;
|
|
||||||
this.playerDeclares = declares;
|
|
||||||
this.combat = combat;
|
|
||||||
this.defenders = combat.getDefenders();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public final void showMessage() {
|
|
||||||
// TODO still seems to have some issues with multiple planeswalkers
|
|
||||||
|
|
||||||
ButtonUtil.enableOnlyOk();
|
|
||||||
|
|
||||||
setCurrentDefender(defenders.isEmpty() ? null : defenders.get(0));
|
|
||||||
|
|
||||||
if ( null == currentDefender ) {
|
|
||||||
System.err.println("InputAttack has no potential defenders!");
|
|
||||||
return; // should even throw here!
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Card> possibleAttackers = playerAttacks.getCardsIn(ZoneType.Battlefield);
|
|
||||||
for (Card c : Iterables.filter(possibleAttackers, CardPredicates.Presets.CREATURES)) {
|
|
||||||
if (c.hasKeyword("CARDNAME attacks each turn if able.")) {
|
|
||||||
for(GameEntity def : defenders ) {
|
|
||||||
if( CombatUtil.canAttack(c, def, combat) ) {
|
|
||||||
combat.addAttacker(c, currentDefender);
|
|
||||||
FControl.fireEvent(new UiEventAttackerDeclared(c, currentDefender));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (c.hasStartOfKeyword("CARDNAME attacks specific player each combat if able")) {
|
|
||||||
final int i = c.getKeywordPosition("CARDNAME attacks specific player each combat if able");
|
|
||||||
final String defined = c.getKeyword().get(i).split(":")[1];
|
|
||||||
final Player player = AbilityUtils.getDefinedPlayers(c, defined, null).get(0);
|
|
||||||
if (player != null && CombatUtil.canAttack(c, player, combat)) {
|
|
||||||
combat.addAttacker(c, player);
|
|
||||||
FControl.fireEvent(new UiEventAttackerDeclared(c, player));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showCombat() {
|
|
||||||
// redraw sword icons
|
|
||||||
FControl.showCombat(combat);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onOk() {
|
|
||||||
// TODO Add check to see if each must attack creature is attacking
|
|
||||||
// Propaganda costs could have been paid here.
|
|
||||||
setCurrentDefender(null); // remove highlights
|
|
||||||
activateBand(null);
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onPlayerSelected(Player selected) {
|
|
||||||
if (defenders.contains(selected)) {
|
|
||||||
setCurrentDefender(selected);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
flashIncorrectAction(); // cannot attack that player
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Option {
|
|
||||||
DECLARE_AS_ATTACKER("Declare as Attacker"),
|
|
||||||
REMOVE_FROM_COMBAT("Remove from Combat"),
|
|
||||||
ATTACK_THIS_DEFENDER("Attack this Defender"),
|
|
||||||
ACTIVATE_BAND("Activate Band"),
|
|
||||||
JOIN_BAND("Join Band");
|
|
||||||
|
|
||||||
private String text;
|
|
||||||
|
|
||||||
private Option(String text0) {
|
|
||||||
text = text0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onCardSelected(final Card card, final List<Card> orderedCardOptions) {
|
|
||||||
FCardZoom.show(FControl.getView().getPrompt().getMessage(),
|
|
||||||
card, orderedCardOptions, new ZoomController<Option>() {
|
|
||||||
@Override
|
|
||||||
public List<Option> getOptions(final Card card) {
|
|
||||||
List<Option> options = new ArrayList<Option>();
|
|
||||||
|
|
||||||
if (card.getController().isOpponentOf(playerAttacks)) {
|
|
||||||
if (defenders.contains(card)) { // planeswalker?
|
|
||||||
options.add(Option.ATTACK_THIS_DEFENDER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (combat.getAttackers().contains(card)) {
|
|
||||||
if (!card.hasKeyword("CARDNAME attacks each turn if able.") &&
|
|
||||||
!card.hasStartOfKeyword("CARDNAME attacks specific player each combat if able")) {
|
|
||||||
options.add(Option.REMOVE_FROM_COMBAT);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (combat.isAttacking(card, currentDefender)) {
|
|
||||||
// Activate band by selecting/deselecting a band member
|
|
||||||
if (activeBand == null) {
|
|
||||||
options.add(Option.ACTIVATE_BAND);
|
|
||||||
}
|
|
||||||
else if (!activeBand.getAttackers().contains(card) && activeBand.canJoinBand(card)) {
|
|
||||||
options.add(Option.JOIN_BAND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (playerAttacks.getZone(ZoneType.Battlefield).contains(card) &&
|
|
||||||
CombatUtil.canAttack(card, currentDefender, combat)) {
|
|
||||||
options.add(Option.DECLARE_AS_ATTACKER);
|
|
||||||
|
|
||||||
if (activeBand != null && activeBand.canJoinBand(card)) {
|
|
||||||
options.add(Option.JOIN_BAND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean selectOption(final Card card, final Option option) {
|
|
||||||
boolean hideZoomView = false; //keep zoom open while declaring attackers by default
|
|
||||||
|
|
||||||
switch (option) {
|
|
||||||
case DECLARE_AS_ATTACKER:
|
|
||||||
if (combat.isAttacking(card)) {
|
|
||||||
combat.removeFromCombat(card);
|
|
||||||
}
|
|
||||||
declareAttacker(card);
|
|
||||||
showCombat();
|
|
||||||
break;
|
|
||||||
case REMOVE_FROM_COMBAT:
|
|
||||||
combat.removeFromCombat(card);
|
|
||||||
FControl.setUsedToPay(card, false);
|
|
||||||
showCombat();
|
|
||||||
activateBand(null); //When removing an attacker clear the attacking band
|
|
||||||
FControl.fireEvent(new UiEventAttackerDeclared(card, null));
|
|
||||||
break;
|
|
||||||
case ATTACK_THIS_DEFENDER:
|
|
||||||
setCurrentDefender(card);
|
|
||||||
hideZoomView = true; //don't keep zoom open if choosing defender
|
|
||||||
break;
|
|
||||||
case ACTIVATE_BAND:
|
|
||||||
activateBand(combat.getBandOfAttacker(card));
|
|
||||||
break;
|
|
||||||
case JOIN_BAND: //Join a band by selecting a non-active band member after activating a band
|
|
||||||
combat.removeFromCombat(card);
|
|
||||||
declareAttacker(card);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
showMessage();
|
|
||||||
return hideZoomView;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void declareAttacker(final Card card) {
|
|
||||||
combat.addAttacker(card, currentDefender, this.activeBand);
|
|
||||||
this.activateBand(this.activeBand);
|
|
||||||
updateMessage();
|
|
||||||
|
|
||||||
FControl.fireEvent(new UiEventAttackerDeclared(card, currentDefender));
|
|
||||||
}
|
|
||||||
|
|
||||||
private final void setCurrentDefender(GameEntity def) {
|
|
||||||
currentDefender = def;
|
|
||||||
for( GameEntity ge: defenders ) {
|
|
||||||
if ( ge instanceof Card) {
|
|
||||||
FControl.setUsedToPay((Card)ge, ge == def);
|
|
||||||
}
|
|
||||||
else if (ge instanceof Player) {
|
|
||||||
FControl.setHighlighted((Player) ge, ge == def);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateMessage();
|
|
||||||
|
|
||||||
// update UI
|
|
||||||
}
|
|
||||||
|
|
||||||
private final void activateBand(AttackingBand band) {
|
|
||||||
if (this.activeBand != null) {
|
|
||||||
for(Card card : this.activeBand.getAttackers()) {
|
|
||||||
FControl.setUsedToPay(card, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.activeBand = band;
|
|
||||||
|
|
||||||
if (this.activeBand != null) {
|
|
||||||
for(Card card : this.activeBand.getAttackers()) {
|
|
||||||
FControl.setUsedToPay(card, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// update UI
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateMessage() {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(playerDeclares.getName()).append(", ");
|
|
||||||
sb.append(playerAttacks == playerDeclares ? "declare attackers." : "declare attackers for " + playerAttacks.getName()).append("\n");
|
|
||||||
sb.append("Selecting Creatures to Attack ").append(currentDefender).append("\n\n");
|
|
||||||
sb.append("To change the current defender, click on the player or planeswalker you wish to attack.\n");
|
|
||||||
sb.append("To attack as a band, click an attacking creature to activate its 'band', select another to join the band.");
|
|
||||||
|
|
||||||
showMessage(sb.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,130 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import forge.game.Game;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.phase.PhaseHandler;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
import forge.toolbox.FCardZoom;
|
|
||||||
import forge.toolbox.FCardZoom.ZoomController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Abstract Input class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id: InputBase.java 24769 2014-02-09 13:56:04Z Hellfish $
|
|
||||||
*/
|
|
||||||
public abstract class InputBase implements java.io.Serializable, Input {
|
|
||||||
/** Constant <code>serialVersionUID=-6539552513871194081L</code>. */
|
|
||||||
private static final long serialVersionUID = -6539552513871194081L;
|
|
||||||
private boolean finished = false;
|
|
||||||
protected final boolean isFinished() { return finished; }
|
|
||||||
protected final void setFinished() {
|
|
||||||
FCardZoom.hideZoom(); //ensure zoom hidden when input finished
|
|
||||||
finished = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// showMessage() is always the first method called
|
|
||||||
@Override
|
|
||||||
public final void showMessageInitial() {
|
|
||||||
finished = false;
|
|
||||||
showMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void showMessage();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void selectPlayer(final Player player) {
|
|
||||||
if (isFinished()) { return; }
|
|
||||||
onPlayerSelected(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectAbility(SpellAbility ab) { }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void selectButtonCancel() {
|
|
||||||
if (isFinished()) { return; }
|
|
||||||
onCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void selectButtonOK() {
|
|
||||||
if (isFinished()) { return; }
|
|
||||||
onOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void selectCard(final Card card, final List<Card> orderedCardOptions) {
|
|
||||||
if (isFinished()) { return; }
|
|
||||||
onCardSelected(card, orderedCardOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onCardSelected(final Card card, final List<Card> orderedCardOptions) {
|
|
||||||
//for base input, just show zoom view with no options
|
|
||||||
FCardZoom.show(FControl.getView().getPrompt().getMessage(),
|
|
||||||
card, orderedCardOptions, new ZoomController<Object>() {
|
|
||||||
@Override
|
|
||||||
public List<Object> getOptions(Card card) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean selectOption(Card card, Object option) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onPlayerSelected(final Player p) {}
|
|
||||||
protected void onCancel() {}
|
|
||||||
protected void onOk() {}
|
|
||||||
|
|
||||||
// to remove need for CMatchUI dependence
|
|
||||||
protected final void showMessage(String message) {
|
|
||||||
FControl.showMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void flashIncorrectAction() {
|
|
||||||
FControl.getView().getPrompt().remind();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getTurnPhasePriorityMessage(Game game) {
|
|
||||||
final PhaseHandler ph = game.getPhaseHandler();
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
sb.append("Priority: ").append(ph.getPriorityPlayer()).append("\n");
|
|
||||||
sb.append("Turn ").append(ph.getTurn()).append(" (").append(ph.getPlayerTurn()).append(")\n");
|
|
||||||
sb.append("Phase: ").append(ph.getPhase().nameForUi).append("\n");
|
|
||||||
sb.append("Stack: ");
|
|
||||||
if (!game.getStack().isEmpty()) {
|
|
||||||
sb.append(game.getStack().size()).append(" to Resolve.");
|
|
||||||
} else {
|
|
||||||
sb.append("Empty");
|
|
||||||
}
|
|
||||||
sb.append("\n");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.combat.Combat;
|
|
||||||
import forge.game.combat.CombatUtil;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.zone.ZoneType;
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
import forge.screens.match.events.UiEventBlockerAssigned;
|
|
||||||
import forge.toolbox.FCardZoom;
|
|
||||||
import forge.toolbox.FOptionPane;
|
|
||||||
import forge.toolbox.FCardZoom.ZoomController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Input_Block class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id: InputBlock.java 24769 2014-02-09 13:56:04Z Hellfish $
|
|
||||||
*/
|
|
||||||
public class InputBlock extends InputSyncronizedBase {
|
|
||||||
/** Constant <code>serialVersionUID=6120743598368928128L</code>. */
|
|
||||||
private static final long serialVersionUID = 6120743598368928128L;
|
|
||||||
|
|
||||||
private Card currentAttacker = null;
|
|
||||||
// some cards may block several creatures at a time. (ex: Two-Headed Dragon, Vanguard's Shield)
|
|
||||||
private final Combat combat;
|
|
||||||
private final Player defender;
|
|
||||||
private final Player declarer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Write javadoc for Constructor.
|
|
||||||
* @param priority
|
|
||||||
*/
|
|
||||||
public InputBlock(Player whoDeclares, Player whoDefends, Combat combat) {
|
|
||||||
defender = whoDefends;
|
|
||||||
declarer = whoDeclares;
|
|
||||||
this.combat = combat;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void showMessage() {
|
|
||||||
// could add "Reset Blockers" button
|
|
||||||
ButtonUtil.enableOnlyOk();
|
|
||||||
|
|
||||||
String prompt = declarer == defender ? "declare blockers." : "declare blockers for " + defender.getName();
|
|
||||||
|
|
||||||
final StringBuilder sb = new StringBuilder(declarer.getName());
|
|
||||||
sb.append(", ").append(prompt).append("\n\n");
|
|
||||||
|
|
||||||
if (this.currentAttacker == null) {
|
|
||||||
sb.append("To Block, click on your opponent's attacker first, then your blocker(s).\n");
|
|
||||||
sb.append("To cancel a block right-click on your blocker");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final String attackerName = this.currentAttacker.isFaceDown() ? "Morph" : this.currentAttacker.getName();
|
|
||||||
sb.append("Select a creature to block ").append(attackerName).append(" (");
|
|
||||||
sb.append(this.currentAttacker.getUniqueNumber()).append("). ");
|
|
||||||
sb.append("To cancel a block right-click on your blocker");
|
|
||||||
}
|
|
||||||
|
|
||||||
showMessage(sb.toString());
|
|
||||||
FControl.showCombat(combat);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public final void onOk() {
|
|
||||||
String blockErrors = CombatUtil.validateBlocks(combat, defender);
|
|
||||||
if( null == blockErrors ) {
|
|
||||||
// Done blocking
|
|
||||||
ButtonUtil.reset();
|
|
||||||
setCurrentAttacker(null);
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FOptionPane.showMessageDialog(blockErrors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum Option {
|
|
||||||
DECLARE_AS_BLOCKER("Declare as Blocker"),
|
|
||||||
REMOVE_FROM_COMBAT("Remove from Combat"),
|
|
||||||
BLOCK_THIS_ATTACKER("Block this Attacker"),;
|
|
||||||
|
|
||||||
private String text;
|
|
||||||
|
|
||||||
private Option(String text0) {
|
|
||||||
text = text0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public final void onCardSelected(final Card card, final List<Card> orderedCardOptions) {
|
|
||||||
FCardZoom.show(FControl.getView().getPrompt().getMessage(),
|
|
||||||
card, orderedCardOptions, new ZoomController<Option>() {
|
|
||||||
@Override
|
|
||||||
public List<Option> getOptions(final Card card) {
|
|
||||||
List<Option> options = new ArrayList<Option>();
|
|
||||||
|
|
||||||
if (combat.isAttacking(card)) {
|
|
||||||
options.add(Option.BLOCK_THIS_ATTACKER);
|
|
||||||
}
|
|
||||||
else if (card.getController() == defender) {
|
|
||||||
if (combat.isBlocking(card)) {
|
|
||||||
options.add(Option.REMOVE_FROM_COMBAT);
|
|
||||||
}
|
|
||||||
else if (currentAttacker != null && card.isCreature() &&
|
|
||||||
defender.getZone(ZoneType.Battlefield).contains(card) &&
|
|
||||||
CombatUtil.canBlock(currentAttacker, card, combat)) {
|
|
||||||
options.add(Option.DECLARE_AS_BLOCKER);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean selectOption(final Card card, final Option option) {
|
|
||||||
switch (option) {
|
|
||||||
case DECLARE_AS_BLOCKER:
|
|
||||||
combat.addBlocker(currentAttacker, card);
|
|
||||||
FControl.fireEvent(new UiEventBlockerAssigned(card, currentAttacker));
|
|
||||||
break;
|
|
||||||
case REMOVE_FROM_COMBAT:
|
|
||||||
combat.removeFromCombat(card);
|
|
||||||
FControl.fireEvent(new UiEventBlockerAssigned(card, (Card)null));
|
|
||||||
break;
|
|
||||||
case BLOCK_THIS_ATTACKER:
|
|
||||||
setCurrentAttacker(card);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
showMessage();
|
|
||||||
return true; //hide zoom view after declaring blocker
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setCurrentAttacker(Card card) {
|
|
||||||
currentAttacker = card;
|
|
||||||
for(Card c : combat.getAttackers()) {
|
|
||||||
FControl.setUsedToPay(c, card == c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* InputConfirm class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id: InputConfirm.java 21647 2013-05-24 22:31:11Z Max mtg $
|
|
||||||
*/
|
|
||||||
public class InputConfirm extends InputSyncronizedBase {
|
|
||||||
private static final long serialVersionUID = -3591794991788531626L;
|
|
||||||
|
|
||||||
private final String message;
|
|
||||||
private final String yesButtonText;
|
|
||||||
private final String noButtonText;
|
|
||||||
private boolean result;
|
|
||||||
|
|
||||||
public InputConfirm(String message0) {
|
|
||||||
this(message0, "Yes", "No", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputConfirm(String message0, String yesButtonText0, String noButtonText0) {
|
|
||||||
this(message0, yesButtonText0, noButtonText0, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputConfirm(String message0, String yesButtonText0, String noButtonText0, boolean defaultYes0) {
|
|
||||||
this.message = message0;
|
|
||||||
this.yesButtonText = yesButtonText0;
|
|
||||||
this.noButtonText = noButtonText0;
|
|
||||||
result = defaultYes0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void showMessage() {
|
|
||||||
ButtonUtil.setButtonText(this.yesButtonText, this.noButtonText);
|
|
||||||
ButtonUtil.enableAll();
|
|
||||||
showMessage(this.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onOk() {
|
|
||||||
this.result = true;
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onCancel() {
|
|
||||||
this.result = false;
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void done() {
|
|
||||||
ButtonUtil.reset();
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean getResult() {
|
|
||||||
return this.result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,189 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.game.Game;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.zone.ZoneType;
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
import forge.toolbox.FCardZoom;
|
|
||||||
import forge.toolbox.GuiDialog;
|
|
||||||
import forge.toolbox.FCardZoom.ZoomController;
|
|
||||||
import forge.util.Lang;
|
|
||||||
import forge.util.ThreadUtil;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* InputConfirmMulligan class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id: InputConfirmMulligan.java 24769 2014-02-09 13:56:04Z Hellfish $
|
|
||||||
*/
|
|
||||||
public class InputConfirmMulligan extends InputSyncronizedBase {
|
|
||||||
/** Constant <code>serialVersionUID=-8112954303001155622L</code>. */
|
|
||||||
private static final long serialVersionUID = -8112954303001155622L;
|
|
||||||
|
|
||||||
boolean keepHand = false;
|
|
||||||
final boolean isCommander;
|
|
||||||
|
|
||||||
private final List<Card> selected = new ArrayList<Card>();
|
|
||||||
private final Player player;
|
|
||||||
private final Player startingPlayer;
|
|
||||||
|
|
||||||
public InputConfirmMulligan(Player humanPlayer, Player startsGame, boolean commander) {
|
|
||||||
player = humanPlayer;
|
|
||||||
isCommander = commander;
|
|
||||||
startingPlayer = startsGame;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public final void showMessage() {
|
|
||||||
Game game = player.getGame();
|
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
if (startingPlayer == player) {
|
|
||||||
sb.append(player).append(", you are going first!\n\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sb.append(startingPlayer.getName()).append(" is going first.\n");
|
|
||||||
sb.append(player).append(", you are going ").append(Lang.getOrdinal(game.getPosition(player, startingPlayer))).append(".\n\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCommander) {
|
|
||||||
ButtonUtil.setButtonText("Keep", "Exile");
|
|
||||||
ButtonUtil.enableOnlyOk();
|
|
||||||
sb.append("Will you keep your hand or choose some cards to exile those and draw one less card?");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ButtonUtil.setButtonText("Keep", "Mulligan");
|
|
||||||
ButtonUtil.enableAll();
|
|
||||||
sb.append("Do you want to keep your hand?");
|
|
||||||
}
|
|
||||||
|
|
||||||
showMessage(sb.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onOk() {
|
|
||||||
keepHand = true;
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onCancel() {
|
|
||||||
keepHand = false;
|
|
||||||
done();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void done() {
|
|
||||||
ButtonUtil.reset();
|
|
||||||
if (isCommander) {
|
|
||||||
// Clear the "selected" icon after clicking the done button
|
|
||||||
for (Card c : this.selected) {
|
|
||||||
FControl.setUsedToPay(c, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
volatile boolean cardSelectLocked = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCardSelected(final Card card, final List<Card> orderedCardOptions) { // the only place that would cause troubles - input is supposed only to confirm, not to fire abilities
|
|
||||||
if (cardSelectLocked) { return; }
|
|
||||||
|
|
||||||
FCardZoom.show(FControl.getView().getPrompt().getMessage(),
|
|
||||||
card, orderedCardOptions, new ZoomController<String>() {
|
|
||||||
@Override
|
|
||||||
public List<String> getOptions(final Card card) {
|
|
||||||
List<String> options = new ArrayList<String>();
|
|
||||||
|
|
||||||
if (player.getZone(ZoneType.Hand).contains(card)) {
|
|
||||||
if (card.getName().equals("Serum Powder")) {
|
|
||||||
options.add("Exile all the cards from your hand, then draw that many cards.");
|
|
||||||
}
|
|
||||||
else if (isCommander) {
|
|
||||||
if (selected.contains(card)) {
|
|
||||||
options.add("Select Card");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
options.add("Unselect Card");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean selectOption(final Card card, final String option) {
|
|
||||||
if (option == "Exile all the cards from your hand, then draw that many cards.") {
|
|
||||||
if (GuiDialog.confirm(card, "This action cannot be undone. Proceed?")) {
|
|
||||||
cardSelectLocked = true;
|
|
||||||
ThreadUtil.invokeInGameThread(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
List<Card> hand = new ArrayList<Card>(card.getController().getCardsIn(ZoneType.Hand));
|
|
||||||
for (Card c : hand) {
|
|
||||||
player.getGame().getAction().exile(c);
|
|
||||||
}
|
|
||||||
card.getController().drawCards(hand.size());
|
|
||||||
cardSelectLocked = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (isCommander) { // allow to choose cards for partial paris
|
|
||||||
if (selected.contains(card)) {
|
|
||||||
FControl.setUsedToPay(card, false);
|
|
||||||
selected.remove(card);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FControl.setUsedToPay(card, true);
|
|
||||||
selected.add(card);
|
|
||||||
}
|
|
||||||
if (selected.isEmpty()) {
|
|
||||||
ButtonUtil.enableOnlyOk();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ButtonUtil.enableAll();
|
|
||||||
}
|
|
||||||
return false; //keep zoom view open
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isKeepHand() {
|
|
||||||
return keepHand;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Card> getSelectedCards() {
|
|
||||||
return selected;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.FThreads;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
import forge.util.ThreadUtil;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
|
|
||||||
public class InputLockUI implements Input {
|
|
||||||
private final AtomicInteger iCall = new AtomicInteger();
|
|
||||||
|
|
||||||
public InputLockUI(InputQueue inputQueue) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showMessageInitial() {
|
|
||||||
int ixCall = 1 + iCall.getAndIncrement();
|
|
||||||
ThreadUtil.delay(500, new InputUpdater(ixCall));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "lockUI";
|
|
||||||
}
|
|
||||||
|
|
||||||
private class InputUpdater implements Runnable {
|
|
||||||
final int ixCall;
|
|
||||||
|
|
||||||
public InputUpdater(final int idxCall) {
|
|
||||||
ixCall = idxCall;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
if ( ixCall != iCall.get() || !isActive()) // cancel the message if it's not from latest call or input is gone already
|
|
||||||
return;
|
|
||||||
FThreads.invokeInEdtLater(showMessageFromEdt);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final Runnable showMessageFromEdt = new Runnable() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
ButtonUtil.disableAll();
|
|
||||||
showMessage("Waiting for actions...");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
protected final boolean isActive() {
|
|
||||||
return FControl.getInputQueue().getInput() == this;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void showMessage(String message) {
|
|
||||||
FControl.showMessage(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public void selectCard(final Card card, final List<Card> orderedCardOptions) {}
|
|
||||||
@Override public void selectAbility(SpellAbility ab) {}
|
|
||||||
@Override public void selectPlayer(Player player) {}
|
|
||||||
@Override public void selectButtonOK() {}
|
|
||||||
@Override public void selectButtonCancel() {}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.toolbox.FCardZoom;
|
|
||||||
import forge.toolbox.FCardZoom.ZoomController;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Input_PassPriority class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id: InputPassPriority.java 24769 2014-02-09 13:56:04Z Hellfish $
|
|
||||||
*/
|
|
||||||
public class InputPassPriority extends InputSyncronizedBase {
|
|
||||||
/** Constant <code>serialVersionUID=-581477682214137181L</code>. */
|
|
||||||
private static final long serialVersionUID = -581477682214137181L;
|
|
||||||
private final Player player;
|
|
||||||
private SpellAbility chosenSa;
|
|
||||||
|
|
||||||
public InputPassPriority(Player human) {
|
|
||||||
player = human;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public final void showMessage() {
|
|
||||||
showMessage(getTurnPhasePriorityMessage(player.getGame()));
|
|
||||||
chosenSa = null;
|
|
||||||
ButtonUtil.enableOnlyOk();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onOk() {
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SpellAbility getChosenSa() {
|
|
||||||
return chosenSa;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCardSelected(final Card card, final List<Card> orderedCardOptions) {
|
|
||||||
FCardZoom.show("Select a spell/ability", card, orderedCardOptions, new ZoomController<SpellAbility>() {
|
|
||||||
@Override
|
|
||||||
public List<SpellAbility> getOptions(final Card card) {
|
|
||||||
return card.getAllPossibleAbilities(player, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean selectOption(final Card card, final SpellAbility option) {
|
|
||||||
selectAbility(option);
|
|
||||||
return true; //TODO: Avoid hiding card zoom when selecting mana abilities
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void selectAbility(final SpellAbility ab) {
|
|
||||||
if (ab != null) {
|
|
||||||
chosenSa = ab;
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,360 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.FThreads;
|
|
||||||
import forge.ai.ComputerUtilMana;
|
|
||||||
import forge.ai.PlayerControllerAi;
|
|
||||||
import forge.card.ColorSet;
|
|
||||||
import forge.card.MagicColor;
|
|
||||||
import forge.card.mana.ManaAtom;
|
|
||||||
import forge.game.Game;
|
|
||||||
import forge.game.ability.ApiType;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.replacement.ReplacementEffect;
|
|
||||||
import forge.game.spellability.AbilityManaPart;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.player.HumanPlay;
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
import forge.toolbox.FCardZoom;
|
|
||||||
import forge.toolbox.FCardZoom.ZoomController;
|
|
||||||
import forge.util.Evaluator;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public abstract class InputPayMana extends InputSyncronizedBase {
|
|
||||||
private static final long serialVersionUID = -9133423708688480255L;
|
|
||||||
|
|
||||||
protected int phyLifeToLose = 0;
|
|
||||||
|
|
||||||
protected final Player player;
|
|
||||||
protected final Game game;
|
|
||||||
protected ManaCostBeingPaid manaCost;
|
|
||||||
protected final SpellAbility saPaidFor;
|
|
||||||
|
|
||||||
private boolean bPaid = false;
|
|
||||||
private Boolean canPayManaCost = null;
|
|
||||||
|
|
||||||
private boolean locked = false;
|
|
||||||
|
|
||||||
protected InputPayMana(SpellAbility saToPayFor, Player payer) {
|
|
||||||
this.player = payer;
|
|
||||||
this.game = player.getGame();
|
|
||||||
this.saPaidFor = saToPayFor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onCardSelected(final Card card, final List<Card> orderedCardOptions) {
|
|
||||||
if (locked) {
|
|
||||||
System.err.print("Should wait till previous call to playAbility finishes.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
FCardZoom.show(FControl.getView().getPrompt().getMessage(),
|
|
||||||
card, orderedCardOptions, new ZoomController<SpellAbility>() {
|
|
||||||
private byte colorCanUse, colorNeeded;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<SpellAbility> getOptions(final Card card) {
|
|
||||||
if (card.getController() != player || card.getManaAbility().isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
colorCanUse = 0;
|
|
||||||
colorNeeded = 0;
|
|
||||||
|
|
||||||
for (final byte color : MagicColor.WUBRG) {
|
|
||||||
if (manaCost.isAnyPartPayableWith(color, player.getManaPool())) { colorCanUse |= color; }
|
|
||||||
if (manaCost.needsColor(color, player.getManaPool())) { colorNeeded |= color; }
|
|
||||||
}
|
|
||||||
if (manaCost.isAnyPartPayableWith((byte) ManaAtom.COLORLESS, player.getManaPool()))
|
|
||||||
colorCanUse |= ManaAtom.COLORLESS;
|
|
||||||
|
|
||||||
if (colorCanUse == 0) { // no mana cost or something
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// you can't remove unneeded abilities inside a for (am:abilities) loop :(
|
|
||||||
final String typeRes = manaCost.getSourceRestriction();
|
|
||||||
if (StringUtils.isNotBlank(typeRes) && !card.isType(typeRes)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean guessAbilityWithRequiredColors = true;
|
|
||||||
List<SpellAbility> abilities = new ArrayList<SpellAbility>();
|
|
||||||
|
|
||||||
for (SpellAbility ma : card.getManaAbility()) {
|
|
||||||
ma.setActivatingPlayer(player);
|
|
||||||
|
|
||||||
AbilityManaPart m = ma.getManaPartRecursive();
|
|
||||||
if (m == null || !ma.canPlay()) { continue; }
|
|
||||||
if (!abilityProducesManaColor(ma, m, colorCanUse)) { continue; }
|
|
||||||
if (ma.isAbility() && ma.getRestrictions().isInstantSpeed()) { continue; }
|
|
||||||
if (!m.meetsManaRestrictions(saPaidFor)) { continue; }
|
|
||||||
|
|
||||||
abilities.add(ma);
|
|
||||||
|
|
||||||
// skip express mana if the ability is not undoable or reusable
|
|
||||||
if (!ma.isUndoable() || !ma.getPayCosts().isRenewableResource() || ma.getSubAbility() != null) {
|
|
||||||
guessAbilityWithRequiredColors = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abilities.isEmpty()) {
|
|
||||||
return abilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store some information about color costs to help with any mana choices
|
|
||||||
if (colorNeeded == 0) { // only colorless left
|
|
||||||
if (saPaidFor.getHostCard() != null && saPaidFor.getHostCard().hasSVar("ManaNeededToAvoidNegativeEffect")) {
|
|
||||||
String[] negEffects = saPaidFor.getHostCard().getSVar("ManaNeededToAvoidNegativeEffect").split(",");
|
|
||||||
for (String negColor : negEffects) {
|
|
||||||
byte col = MagicColor.fromName(negColor);
|
|
||||||
colorCanUse |= col;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the card has any ability that tracks mana spent, skip express Mana choice
|
|
||||||
if (saPaidFor.tracksManaSpent()) {
|
|
||||||
colorCanUse = MagicColor.ALL_COLORS;
|
|
||||||
guessAbilityWithRequiredColors = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (guessAbilityWithRequiredColors) {
|
|
||||||
// express Mana Choice
|
|
||||||
if (colorNeeded == 0) {
|
|
||||||
//avoid unnecessary prompt by pretending we need White
|
|
||||||
//for the sake of "Add one mana of any color" effects
|
|
||||||
colorNeeded = MagicColor.WHITE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final ArrayList<SpellAbility> colorMatches = new ArrayList<SpellAbility>();
|
|
||||||
for (SpellAbility sa : abilities) {
|
|
||||||
if (abilityProducesManaColor(sa, sa.getManaPartRecursive(), colorNeeded)) {
|
|
||||||
colorMatches.add(sa);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!colorMatches.isEmpty() && colorMatches.size() < abilities.size()) {
|
|
||||||
// leave behind only color matches
|
|
||||||
abilities = colorMatches;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return abilities;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean selectOption(final Card card, final SpellAbility option) {
|
|
||||||
ColorSet colors = ColorSet.fromMask(0 == colorNeeded ? colorCanUse : colorNeeded);
|
|
||||||
option.getManaPartRecursive().setExpressChoice(colors);
|
|
||||||
|
|
||||||
Runnable proc = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
HumanPlay.playSpellAbility(option.getActivatingPlayer(), option);
|
|
||||||
player.getManaPool().payManaFromAbility(saPaidFor, manaCost, option);
|
|
||||||
|
|
||||||
onManaAbilityPaid();
|
|
||||||
onStateChanged();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
locked = true;
|
|
||||||
game.getAction().invoke(proc);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void useManaFromPool(byte colorCode) {
|
|
||||||
// find the matching mana in pool.
|
|
||||||
player.getManaPool().tryPayCostWithColor(colorCode, saPaidFor, manaCost);
|
|
||||||
onManaAbilityPaid();
|
|
||||||
showMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* canMake. color is like "G", returns "Green".
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param am
|
|
||||||
* a {@link forge.card.spellability.AbilityMana} object.
|
|
||||||
* @param mana
|
|
||||||
* a {@link java.lang.String} object.
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
|
||||||
private static boolean abilityProducesManaColor(final SpellAbility am, AbilityManaPart m, final byte neededColor) {
|
|
||||||
if (0 != (neededColor & MagicColor.COLORLESS)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m.isAnyMana()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for produce mana replacement effects - they mess this up, so just use the mana ability
|
|
||||||
final Card source = am.getHostCard();
|
|
||||||
final Player activator = am.getActivatingPlayer();
|
|
||||||
final Game g = source.getGame();
|
|
||||||
final HashMap<String, Object> repParams = new HashMap<String, Object>();
|
|
||||||
repParams.put("Event", "ProduceMana");
|
|
||||||
repParams.put("Mana", m.getOrigProduced());
|
|
||||||
repParams.put("Affected", source);
|
|
||||||
repParams.put("Player", activator);
|
|
||||||
repParams.put("AbilityMana", am);
|
|
||||||
|
|
||||||
for (final Player p : g.getPlayers()) {
|
|
||||||
for (final Card crd : p.getAllCards()) {
|
|
||||||
for (final ReplacementEffect replacementEffect : crd.getReplacementEffects()) {
|
|
||||||
if (replacementEffect.requirementsCheck(g)
|
|
||||||
&& replacementEffect.canReplace(repParams)
|
|
||||||
&& replacementEffect.getMapParams().containsKey("ManaReplacement")
|
|
||||||
&& replacementEffect.zonesCheck(g.getZoneOf(crd))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (am.getApi() == ApiType.ManaReflected) {
|
|
||||||
final Iterable<String> reflectableColors = CardUtil.getReflectableManaColors(am);
|
|
||||||
for (final String color : reflectableColors) {
|
|
||||||
if (0 != (neededColor & MagicColor.fromName(color))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
String colorsProduced = m.isComboMana() ? m.getComboColors() : m.getOrigProduced();
|
|
||||||
for (final String color : colorsProduced.split(" ")) {
|
|
||||||
if (0 != (neededColor & MagicColor.fromName(color))) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if( (neededColor & ManaAtom.COLORLESS) != 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean isAlreadyPaid() {
|
|
||||||
if (manaCost.isPaid()) {
|
|
||||||
bPaid = true;
|
|
||||||
}
|
|
||||||
return bPaid;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean supportAutoPay() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void runAsAi(Runnable proc) {
|
|
||||||
this.player.runWithController(proc, new PlayerControllerAi(this.game, this.player, this.player.getOriginalLobbyPlayer()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected void onOk() {
|
|
||||||
if (supportAutoPay()) {
|
|
||||||
//use AI utility to automatically pay mana cost if possible
|
|
||||||
final Runnable proc = new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
ComputerUtilMana.payManaCost(manaCost, saPaidFor, player);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
//must run in game thread as certain payment actions can only be automated there
|
|
||||||
game.getAction().invoke(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
runAsAi(proc);
|
|
||||||
onStateChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void updateButtons() {
|
|
||||||
if (supportAutoPay()) {
|
|
||||||
ButtonUtil.setButtonText("Auto", "Cancel");
|
|
||||||
}
|
|
||||||
ButtonUtil.enableOnlyCancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void updateMessage() {
|
|
||||||
locked = false;
|
|
||||||
if (supportAutoPay()) {
|
|
||||||
if (canPayManaCost == null) {
|
|
||||||
//use AI utility to determine if mana cost can be paid if that hasn't been determined yet
|
|
||||||
Evaluator<Boolean> proc = new Evaluator<Boolean>() {
|
|
||||||
@Override
|
|
||||||
public Boolean evaluate() {
|
|
||||||
return ComputerUtilMana.canPayManaCost(manaCost, saPaidFor, player);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
runAsAi(proc);
|
|
||||||
canPayManaCost = proc.getResult();
|
|
||||||
}
|
|
||||||
if (canPayManaCost) {
|
|
||||||
ButtonUtil.enableAll(); //enabled Auto button if mana cost can be paid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
showMessage(getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onStop() {
|
|
||||||
if (supportAutoPay()) {
|
|
||||||
ButtonUtil.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public void showMessage() {
|
|
||||||
if (isFinished()) { return; }
|
|
||||||
updateButtons();
|
|
||||||
onStateChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onStateChanged() {
|
|
||||||
if (isAlreadyPaid()) {
|
|
||||||
done();
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
updateMessage();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onManaAbilityPaid() {} // some inputs overload it
|
|
||||||
protected abstract void done();
|
|
||||||
protected abstract String getMessage();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return String.format("PayManaBase %s left", manaCost.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isPaid() { return bPaid; }
|
|
||||||
|
|
||||||
protected String messagePrefix;
|
|
||||||
public void setMessagePrefix(String prompt) {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
messagePrefix = prompt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
|
|
||||||
public class InputPayManaOfCostPayment extends InputPayMana {
|
|
||||||
public InputPayManaOfCostPayment(ManaCostBeingPaid cost, SpellAbility spellAbility, Player payer) {
|
|
||||||
super(spellAbility, payer);
|
|
||||||
manaCost = cost;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 3467312982164195091L;
|
|
||||||
private int phyLifeToLose = 0;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onPlayerSelected(Player selected) {
|
|
||||||
if (player == selected) {
|
|
||||||
if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) {
|
|
||||||
this.phyLifeToLose += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done() {
|
|
||||||
final Card source = saPaidFor.getHostCard();
|
|
||||||
if (this.phyLifeToLose > 0) {
|
|
||||||
player.payLife(this.phyLifeToLose, source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCancel() {
|
|
||||||
stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getMessage() {
|
|
||||||
final String displayMana = manaCost.toString(false);
|
|
||||||
|
|
||||||
final StringBuilder msg = new StringBuilder();
|
|
||||||
if( messagePrefix != null )
|
|
||||||
msg.append(messagePrefix).append("\n");
|
|
||||||
msg.append("Pay Mana Cost: ").append(displayMana);
|
|
||||||
if (this.phyLifeToLose > 0) {
|
|
||||||
msg.append(" (");
|
|
||||||
msg.append(this.phyLifeToLose);
|
|
||||||
msg.append(" life paid for phyrexian mana)");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (manaCost.containsPhyrexianMana()) {
|
|
||||||
msg.append("\n(Click on your life total to pay life for phyrexian mana.)");
|
|
||||||
}
|
|
||||||
|
|
||||||
return msg.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,133 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.card.mana.ManaCost;
|
|
||||||
import forge.game.Game;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
|
|
||||||
//pays the cost of a card played from the player's hand
|
|
||||||
//the card is removed from the players hand if the cost is paid
|
|
||||||
//CANNOT be used for ABILITIES
|
|
||||||
public class InputPayManaSimple extends InputPayMana {
|
|
||||||
// anything that uses this should be converted to Ability_Cost
|
|
||||||
/** Constant <code>serialVersionUID=3467312982164195091L</code>. */
|
|
||||||
private static final long serialVersionUID = 3467312982164195091L;
|
|
||||||
|
|
||||||
private final Card originalCard;
|
|
||||||
private final ManaCost originalManaCost;
|
|
||||||
|
|
||||||
public InputPayManaSimple(final Game game, final SpellAbility sa, final ManaCostBeingPaid manaCostToPay) {
|
|
||||||
super(sa, sa.getActivatingPlayer());
|
|
||||||
this.originalManaCost = manaCostToPay.toManaCost();
|
|
||||||
this.originalCard = sa.getHostCard();
|
|
||||||
|
|
||||||
if (sa.getHostCard().isCopiedSpell() && sa.isSpell()) {
|
|
||||||
this.manaCost = new ManaCostBeingPaid(ManaCost.ZERO);
|
|
||||||
game.getStack().add(this.saPaidFor);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.manaCost = manaCostToPay;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onManaAbilityPaid() {
|
|
||||||
if (this.manaCost.isPaid()) {
|
|
||||||
this.originalCard.setSunburstValue(this.manaCost.getSunburst());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onPlayerSelected(Player selected) {
|
|
||||||
if (player == selected) {
|
|
||||||
if (player.canPayLife(this.phyLifeToLose + 2) && manaCost.payPhyrexian()) {
|
|
||||||
this.phyLifeToLose += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.showMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* done.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void done() {
|
|
||||||
this.originalCard.setSunburstValue(this.manaCost.getSunburst());
|
|
||||||
|
|
||||||
if (this.phyLifeToLose > 0) {
|
|
||||||
player.payLife(this.phyLifeToLose, this.originalCard);
|
|
||||||
}
|
|
||||||
if (!this.saPaidFor.getHostCard().isCopiedSpell()) {
|
|
||||||
if (this.saPaidFor.isSpell()) {
|
|
||||||
this.saPaidFor.setHostCard(game.getAction().moveToStack(this.originalCard));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
protected final void onCancel() {
|
|
||||||
player.getManaPool().refundManaPaid(this.saPaidFor);
|
|
||||||
// Update UI
|
|
||||||
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public final void showMessage() {
|
|
||||||
if (isFinished()) { return; }
|
|
||||||
|
|
||||||
updateButtons();
|
|
||||||
|
|
||||||
if (this.manaCost.isPaid() && !new ManaCostBeingPaid(this.originalManaCost).isPaid()) {
|
|
||||||
this.done();
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
updateMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see forge.control.input.InputPayManaBase#updateMessage()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected String getMessage() {
|
|
||||||
final StringBuilder msg = new StringBuilder("Pay Mana Cost: " + this.manaCost.toString());
|
|
||||||
if (this.phyLifeToLose > 0) {
|
|
||||||
msg.append(" (");
|
|
||||||
msg.append(this.phyLifeToLose);
|
|
||||||
msg.append(" life paid for phyrexian mana)");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.manaCost.containsPhyrexianMana()) {
|
|
||||||
msg.append("\n(Click on your life total to pay life for phyrexian mana.)");
|
|
||||||
}
|
|
||||||
|
|
||||||
// has its own variant of checkIfPaid
|
|
||||||
return msg.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,124 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.card.ColorSet;
|
|
||||||
import forge.card.mana.ManaCost;
|
|
||||||
import forge.card.mana.ManaCostParser;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.mana.Mana;
|
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class InputPayManaX extends InputPayMana {
|
|
||||||
private static final long serialVersionUID = -6900234444347364050L;
|
|
||||||
private int xPaid = 0;
|
|
||||||
private ArrayList<Mana> xPaidByColor = new ArrayList<>();
|
|
||||||
private byte colorsPaid;
|
|
||||||
private final ManaCost manaCostPerX;
|
|
||||||
private final boolean xCanBe0;
|
|
||||||
private boolean canceled = false;
|
|
||||||
|
|
||||||
public InputPayManaX(final SpellAbility sa0, final int amountX, final boolean xCanBe0) {
|
|
||||||
super(sa0, sa0.getActivatingPlayer());
|
|
||||||
xPaid = 0;
|
|
||||||
|
|
||||||
if (saPaidFor.hasParam("XColor")) {
|
|
||||||
String xColor = saPaidFor.getParam("XColor");
|
|
||||||
if (amountX == 1) {
|
|
||||||
manaCostPerX = new ManaCost(new ManaCostParser(xColor));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
List<String> list = new ArrayList<String>(amountX);
|
|
||||||
for (int i = 0; i < amountX; i++) {
|
|
||||||
list.add(xColor);
|
|
||||||
}
|
|
||||||
manaCostPerX = new ManaCost(new ManaCostParser(StringUtils.join(list, ' ')));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
manaCostPerX = ManaCost.get(amountX);
|
|
||||||
}
|
|
||||||
manaCost = new ManaCostBeingPaid(manaCostPerX);
|
|
||||||
|
|
||||||
this.xCanBe0 = xCanBe0;
|
|
||||||
colorsPaid = saPaidFor.getHostCard().getColorsPaid(); // for effects like sunburst
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see forge.control.input.InputPayManaBase#isPaid()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public boolean isPaid() {
|
|
||||||
//return !( xPaid == 0 && !costMana.canXbe0() || this.colorX.equals("") && !this.manaCost.toString().equals(strX) );
|
|
||||||
// return !( xPaid == 0 && !costMana.canXbe0()) && !(this.colorX.equals("") && !this.manaCost.toString().equals(strX));
|
|
||||||
return !canceled && (xPaid > 0 || xCanBe0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean supportAutoPay() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showMessage() {
|
|
||||||
if (isFinished()) { return; }
|
|
||||||
|
|
||||||
updateMessage();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected String getMessage() {
|
|
||||||
StringBuilder msg = new StringBuilder("Pay X Mana Cost for ");
|
|
||||||
msg.append(saPaidFor.getHostCard().getName()).append("\n").append(this.xPaid);
|
|
||||||
msg.append(" Paid so far.");
|
|
||||||
if (!xCanBe0) {
|
|
||||||
msg.append(" X Can't be 0.");
|
|
||||||
}
|
|
||||||
// Enable just cancel is full X value hasn't been paid for multiple X values
|
|
||||||
// or X is 0, and x can't be 0
|
|
||||||
if (!isPaid()) {
|
|
||||||
ButtonUtil.enableOnlyCancel();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ButtonUtil.enableAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
return msg.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onManaAbilityPaid() {
|
|
||||||
if (this.manaCost.isPaid()) {
|
|
||||||
this.colorsPaid |= manaCost.getColorsPaid();
|
|
||||||
this.manaCost = new ManaCostBeingPaid(manaCostPerX);
|
|
||||||
this.xPaid++;
|
|
||||||
this.xPaidByColor.add(saPaidFor.getPayingMana().get(0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onCancel() {
|
|
||||||
// If you hit cancel, isPaid needs to return false
|
|
||||||
this.canceled = true;
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onOk() {
|
|
||||||
done();
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void done() {
|
|
||||||
final Card card = saPaidFor.getHostCard();
|
|
||||||
card.setXManaCostPaid(this.xPaid);
|
|
||||||
card.setXManaCostPaidByColor(this.xPaidByColor);
|
|
||||||
card.setColorsPaid(this.colorsPaid);
|
|
||||||
card.setSunburstValue(ColorSet.fromMask(this.colorsPaid).countColors());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
import forge.screens.match.FControlGamePlayback;
|
|
||||||
|
|
||||||
public class InputPlaybackControl extends InputSyncronizedBase implements InputSynchronized {
|
|
||||||
private static final long serialVersionUID = 7979208993306642072L;
|
|
||||||
|
|
||||||
FControlGamePlayback control;
|
|
||||||
|
|
||||||
private boolean isPaused = false;
|
|
||||||
private boolean isFast = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Write javadoc for Constructor.
|
|
||||||
* @param fControlGamePlayback
|
|
||||||
*/
|
|
||||||
public InputPlaybackControl(FControlGamePlayback fControlGamePlayback) {
|
|
||||||
control = fControlGamePlayback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see forge.gui.input.InputBase#showMessage()
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
protected void showMessage() {
|
|
||||||
setPause(false);
|
|
||||||
ButtonUtil.enableAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setPause(boolean pause) {
|
|
||||||
isPaused = pause;
|
|
||||||
if ( isPaused )
|
|
||||||
ButtonUtil.setButtonText("Resume", "Step");
|
|
||||||
else {
|
|
||||||
ButtonUtil.setButtonText("Pause", isFast ? "1x Speed" : "10x Faster");
|
|
||||||
showMessage("Press pause to pause game.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onGamePaused() {
|
|
||||||
showMessage(getTurnPhasePriorityMessage(FControl.getGame()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onOk() {
|
|
||||||
if ( isPaused ) {
|
|
||||||
control.resume();
|
|
||||||
setPause(false);
|
|
||||||
} else {
|
|
||||||
control.pause();
|
|
||||||
setPause(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCancel() {
|
|
||||||
if ( isPaused ) {
|
|
||||||
control.singleStep();
|
|
||||||
} else {
|
|
||||||
isFast = !isFast;
|
|
||||||
control.setSpeed(isFast);
|
|
||||||
setPause(isPaused); // update message
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.card.CounterType;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.toolbox.GuiChoose;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
public final class InputProliferate extends InputSelectManyBase<GameEntity> {
|
|
||||||
private static final long serialVersionUID = -1779224307654698954L;
|
|
||||||
private Map<GameEntity, CounterType> chosenCounters = new HashMap<GameEntity, CounterType>();
|
|
||||||
|
|
||||||
public InputProliferate() {
|
|
||||||
super(1, Integer.MAX_VALUE);
|
|
||||||
allowUnselect = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected String getMessage() {
|
|
||||||
StringBuilder sb = new StringBuilder("Choose permanents and/or players with counters on them to add one more counter of that type.");
|
|
||||||
sb.append("\n\nYou've selected so far:\n");
|
|
||||||
if (chosenCounters.isEmpty()) {
|
|
||||||
sb.append("(none)");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (Entry<GameEntity, CounterType> ge : chosenCounters.entrySet()) {
|
|
||||||
if (ge.getKey() instanceof Player) {
|
|
||||||
sb.append("* A poison counter to player ").append(ge.getKey()).append("\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sb.append("* ").append(ge.getKey()).append(" -> ").append(ge.getValue()).append("counter\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCardSelected(final Card card, final List<Card> orderedCardOptions) {
|
|
||||||
if (!card.hasCounters()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean entityWasSelected = chosenCounters.containsKey(card);
|
|
||||||
if (entityWasSelected) {
|
|
||||||
this.chosenCounters.remove(card);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
final List<CounterType> choices = new ArrayList<CounterType>();
|
|
||||||
for (final CounterType ct : CounterType.values()) {
|
|
||||||
if (card.getCounters(ct) > 0) {
|
|
||||||
choices.add(ct);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CounterType toAdd = choices.size() == 1 ? choices.get(0) : GuiChoose.one("Select counter type", choices);
|
|
||||||
chosenCounters.put(card, toAdd);
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onPlayerSelected(Player player) {
|
|
||||||
if (player.getPoisonCounters() == 0 || player.hasKeyword("You can't get poison counters")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean entityWasSelected = chosenCounters.containsKey(player);
|
|
||||||
if (entityWasSelected) {
|
|
||||||
this.chosenCounters.remove(player);
|
|
||||||
} else
|
|
||||||
this.chosenCounters.put(player, null /* POISON counter is meant */);
|
|
||||||
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<GameEntity, CounterType> getProliferationMap() {
|
|
||||||
return chosenCounters;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean hasEnoughTargets() { return true; }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean hasAllTargets() { return false; }
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<GameEntity> getSelected() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return chosenCounters.keySet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.FThreads;
|
|
||||||
import forge.game.Game;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
import forge.toolbox.FOptionPane;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Observable;
|
|
||||||
import java.util.Observer;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* GuiInput class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id: InputProxy.java 24769 2014-02-09 13:56:04Z Hellfish $
|
|
||||||
*/
|
|
||||||
public class InputProxy implements Observer {
|
|
||||||
|
|
||||||
/** The input. */
|
|
||||||
private AtomicReference<Input> input = new AtomicReference<Input>();
|
|
||||||
private Game game = null;
|
|
||||||
|
|
||||||
// private static final boolean DEBUG_INPUT = true; // false;
|
|
||||||
|
|
||||||
public void setGame(Game game0) {
|
|
||||||
game = game0;
|
|
||||||
FControl.getInputQueue().addObserver(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean passPriority() {
|
|
||||||
Input inp = getInput();
|
|
||||||
if (inp != null && inp instanceof InputPassPriority) {
|
|
||||||
inp.selectButtonOK();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
FOptionPane.showMessageDialog("Cannot pass priority at this time.");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void update(final Observable observable, final Object obj) {
|
|
||||||
final Input nextInput = FControl.getInputQueue().getActualInput(game);
|
|
||||||
|
|
||||||
/* if(DEBUG_INPUT)
|
|
||||||
System.out.printf("%s ... \t%s on %s, \tstack = %s%n",
|
|
||||||
FThreads.debugGetStackTraceItem(6, true), nextInput == null ? "null" : nextInput.getClass().getSimpleName(),
|
|
||||||
game.getPhaseHandler().debugPrintState(), Singletons.getControl().getInputQueue().printInputStack());
|
|
||||||
*/
|
|
||||||
this.input.set(nextInput);
|
|
||||||
Runnable showMessage = new Runnable() {
|
|
||||||
@Override public void run() {
|
|
||||||
Input current = getInput();
|
|
||||||
FControl.getInputQueue().syncPoint();
|
|
||||||
//System.out.printf("\t%s > showMessage @ %s/%s during %s%n", FThreads.debugGetCurrThreadId(), nextInput.getClass().getSimpleName(), current.getClass().getSimpleName(), game.getPhaseHandler().debugPrintState());
|
|
||||||
current.showMessageInitial();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
FThreads.invokeInEdtLater(showMessage);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* selectButtonOK.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
public final void selectButtonOK() {
|
|
||||||
Input inp = getInput();
|
|
||||||
if (inp != null) {
|
|
||||||
inp.selectButtonOK();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* selectButtonCancel.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
public final void selectButtonCancel() {
|
|
||||||
Input inp = getInput();
|
|
||||||
if (inp != null) {
|
|
||||||
inp.selectButtonCancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* selectPlayer.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param player
|
|
||||||
* a {@link forge.game.player.Player} object.
|
|
||||||
*/
|
|
||||||
public final void selectPlayer(final Player player) {
|
|
||||||
Input inp = getInput();
|
|
||||||
if (inp != null) {
|
|
||||||
inp.selectPlayer(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* selectCard.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param card
|
|
||||||
* a {@link forge.game.card.Card} object.
|
|
||||||
* @param orderedCardOptions
|
|
||||||
*/
|
|
||||||
public final void selectCard(Card card, List<Card> orderedCardOptions) {
|
|
||||||
Input inp = getInput();
|
|
||||||
if (inp != null) {
|
|
||||||
inp.selectCard(card, orderedCardOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void selectAbility(SpellAbility ab) {
|
|
||||||
Input inp = getInput();
|
|
||||||
if (inp != null) {
|
|
||||||
inp.selectAbility(ab);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
|
||||||
@Override
|
|
||||||
public final String toString() {
|
|
||||||
Input inp = getInput();
|
|
||||||
return null == inp ? "(null)" : inp.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return {@link forge.gui.InputProxy.InputBase} */
|
|
||||||
private Input getInput() {
|
|
||||||
return this.input.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.game.Game;
|
|
||||||
import java.util.Observable;
|
|
||||||
import java.util.concurrent.BlockingDeque;
|
|
||||||
import java.util.concurrent.LinkedBlockingDeque;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* InputControl class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id: InputQueue.java 24769 2014-02-09 13:56:04Z Hellfish $
|
|
||||||
*/
|
|
||||||
public class InputQueue extends Observable {
|
|
||||||
private final BlockingDeque<InputSynchronized> inputStack = new LinkedBlockingDeque<InputSynchronized>();
|
|
||||||
private final InputLockUI inputLock;
|
|
||||||
|
|
||||||
public InputQueue() {
|
|
||||||
inputLock = new InputLockUI(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void updateObservers() {
|
|
||||||
this.setChanged();
|
|
||||||
this.notifyObservers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final Input getInput() {
|
|
||||||
return inputStack.isEmpty() ? null : this.inputStack.peek();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void removeInput(Input inp) {
|
|
||||||
Input topMostInput = inputStack.isEmpty() ? null : inputStack.pop();
|
|
||||||
|
|
||||||
if (topMostInput != inp) {
|
|
||||||
throw new RuntimeException("Cannot remove input " + inp.getClass().getSimpleName() + " because it's not on top of stack. Stack = " + inputStack );
|
|
||||||
}
|
|
||||||
updateObservers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* updateInput.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @return a {@link forge.gui.input.InputBase} object.
|
|
||||||
*/
|
|
||||||
public final Input getActualInput(Game game) {
|
|
||||||
Input topMost = inputStack.peek(); // incoming input to Control
|
|
||||||
if (topMost != null && !game.isGameOver()) {
|
|
||||||
return topMost;
|
|
||||||
}
|
|
||||||
return inputLock;
|
|
||||||
}
|
|
||||||
|
|
||||||
// only for debug purposes
|
|
||||||
public String printInputStack() {
|
|
||||||
return inputStack.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setInput(InputSynchronized input) {
|
|
||||||
this.inputStack.push(input);
|
|
||||||
syncPoint();
|
|
||||||
this.updateObservers();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void syncPoint() {
|
|
||||||
synchronized (inputLock) {
|
|
||||||
// acquire and release lock, so that actions from Game thread happen before EDT reads their results
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onGameOver(boolean releaseAllInputs) {
|
|
||||||
for (InputSynchronized inp : inputStack) {
|
|
||||||
inp.relaseLatchWhenGameIsOver();
|
|
||||||
if (!releaseAllInputs) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.card.mana.ManaCost;
|
|
||||||
import forge.card.mana.ManaCostShard;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.card.CardUtil;
|
|
||||||
import forge.game.mana.ManaCostBeingPaid;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
public final class InputSelectCardsForConvoke extends InputSelectManyBase<Card> {
|
|
||||||
private static final long serialVersionUID = -1779224307654698954L;
|
|
||||||
private final Map<Card, ImmutablePair<Byte, ManaCostShard>> chosenCards = new HashMap<Card, ImmutablePair<Byte, ManaCostShard>>();
|
|
||||||
private final ManaCostBeingPaid remainingCost;
|
|
||||||
private final Player player;
|
|
||||||
|
|
||||||
public InputSelectCardsForConvoke(Player p, ManaCost cost, List<Card> untapped) {
|
|
||||||
super(1, Math.min(cost.getCMC(), untapped.size()));
|
|
||||||
remainingCost = new ManaCostBeingPaid(cost);
|
|
||||||
player = p;
|
|
||||||
allowUnselect = true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected String getMessage() {
|
|
||||||
return "Choose creatures to tap for convoke.\nRemaining mana cost is " + remainingCost.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCardSelected(final Card card, final List<Card> orderedCardOptions) {
|
|
||||||
boolean entityWasSelected = chosenCards.containsKey(card);
|
|
||||||
if (entityWasSelected) {
|
|
||||||
ImmutablePair<Byte, ManaCostShard> color = this.chosenCards.remove(card);
|
|
||||||
remainingCost.increaseShard(color.right, 1);
|
|
||||||
onSelectStateChanged(card, false);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
byte chosenColor = player.getController().chooseColorAllowColorless("Convoke " + card.toString() + " for which color?", card, CardUtil.getColors(card));
|
|
||||||
|
|
||||||
if (remainingCost.getColorlessManaAmount() > 0 && (chosenColor == 0 || !remainingCost.needsColor(chosenColor, player.getManaPool()))) {
|
|
||||||
registerConvoked(card, ManaCostShard.COLORLESS, chosenColor);
|
|
||||||
} else {
|
|
||||||
for (ManaCostShard shard : remainingCost.getDistinctShards()) {
|
|
||||||
if (shard.canBePaidWithManaOfColor(chosenColor)) {
|
|
||||||
registerConvoked(card, shard, chosenColor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
showMessage("The colors provided by " + card.toString() + " you've chosen cannot be used to decrease the manacost of " + remainingCost.toString());
|
|
||||||
flashIncorrectAction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void registerConvoked(Card card, ManaCostShard shard, byte chosenColor) {
|
|
||||||
remainingCost.decreaseShard(shard, 1);
|
|
||||||
chosenCards.put(card, ImmutablePair.of(chosenColor, shard));
|
|
||||||
onSelectStateChanged(card, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onPlayerSelected(Player player) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Card, ManaCostShard> getConvokeMap() {
|
|
||||||
Map<Card, ManaCostShard> result = new HashMap<Card, ManaCostShard>();
|
|
||||||
if( !hasCancelled() )
|
|
||||||
for(Entry<Card, ImmutablePair<Byte, ManaCostShard>> c : chosenCards.entrySet())
|
|
||||||
result.put(c.getKey(), c.getValue().right);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean hasEnoughTargets() { return true; }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean hasAllTargets() { return false; }
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Collection<Card> getSelected() {
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return chosenCards.keySet();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.game.card.Card;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public class InputSelectCardsFromList extends InputSelectEntitiesFromList<Card> {
|
|
||||||
private static final long serialVersionUID = 6230360322294805986L;
|
|
||||||
|
|
||||||
public InputSelectCardsFromList(int cnt, Collection<Card> validCards) {
|
|
||||||
super(cnt, cnt, validCards); // to avoid hangs
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputSelectCardsFromList(int min, int max, Collection<Card> validCards) {
|
|
||||||
super(min, max, validCards); // to avoid hangs
|
|
||||||
}
|
|
||||||
|
|
||||||
public InputSelectCardsFromList(Collection<Card> validCards) {
|
|
||||||
super(1, 1, validCards); // to avoid hangs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class InputSelectEntitiesFromList<T extends GameEntity> extends InputSelectManyBase<T> {
|
|
||||||
private static final long serialVersionUID = -6609493252672573139L;
|
|
||||||
|
|
||||||
private final Collection<T> validChoices;
|
|
||||||
protected final List<T> selected = new ArrayList<T>();
|
|
||||||
|
|
||||||
public InputSelectEntitiesFromList(int min, int max, Collection<T> validChoices) {
|
|
||||||
super(Math.min(min, validChoices.size()), Math.min(max, validChoices.size()));
|
|
||||||
this.validChoices = validChoices;
|
|
||||||
|
|
||||||
if ( min > validChoices.size() )
|
|
||||||
System.out.println(String.format("Trying to choose at least %d cards from a list with only %d cards!", min, validChoices.size()));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onCardSelected(final Card c, final List<Card> orderedCardOptions) {
|
|
||||||
if (!selectEntity(c)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPlayerSelected(final Player p) {
|
|
||||||
if (!selectEntity(p)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final Collection<T> getSelected() {
|
|
||||||
return selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
protected boolean selectEntity(GameEntity c) {
|
|
||||||
if (!validChoices.contains(c)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean entityWasSelected = selected.contains(c);
|
|
||||||
if (entityWasSelected) {
|
|
||||||
if (!allowUnselect)
|
|
||||||
return false;
|
|
||||||
this.selected.remove(c);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.selected.add((T)c);
|
|
||||||
}
|
|
||||||
onSelectStateChanged(c, !entityWasSelected);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// might re-define later
|
|
||||||
protected boolean hasEnoughTargets() { return selected.size() >= min; }
|
|
||||||
protected boolean hasAllTargets() { return selected.size() >= max; }
|
|
||||||
|
|
||||||
protected String getMessage() {
|
|
||||||
return max == Integer.MAX_VALUE
|
|
||||||
? String.format(message, selected.size())
|
|
||||||
: String.format(message, max - selected.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
|
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
|
|
||||||
public abstract class InputSelectManyBase<T extends GameEntity> extends InputSyncronizedBase {
|
|
||||||
private static final long serialVersionUID = -2305549394512889450L;
|
|
||||||
|
|
||||||
protected boolean bCancelled = false;
|
|
||||||
protected final int min;
|
|
||||||
protected final int max;
|
|
||||||
protected boolean allowUnselect = false;
|
|
||||||
protected boolean allowCancel = false;
|
|
||||||
|
|
||||||
protected String message = "Source-Card-Name - Select %d more card(s)";
|
|
||||||
|
|
||||||
protected InputSelectManyBase(int min, int max) {
|
|
||||||
if (min > max) {
|
|
||||||
throw new IllegalArgumentException("Min must not be greater than Max");
|
|
||||||
}
|
|
||||||
this.min = min;
|
|
||||||
this.max = max;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void refresh() {
|
|
||||||
if (hasAllTargets()) {
|
|
||||||
selectButtonOK();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.showMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract boolean hasEnoughTargets();
|
|
||||||
protected abstract boolean hasAllTargets();
|
|
||||||
|
|
||||||
protected abstract String getMessage();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void showMessage() {
|
|
||||||
showMessage(getMessage());
|
|
||||||
|
|
||||||
boolean canCancel = allowCancel;
|
|
||||||
boolean canOk = hasEnoughTargets();
|
|
||||||
|
|
||||||
if (canOk && canCancel) { ButtonUtil.enableAll(); }
|
|
||||||
if (!canOk && canCancel) { ButtonUtil.enableOnlyCancel(); }
|
|
||||||
if (canOk && !canCancel) { ButtonUtil.enableOnlyOk(); }
|
|
||||||
if (!canOk && !canCancel) { ButtonUtil.disableAll(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onCancel() {
|
|
||||||
bCancelled = true;
|
|
||||||
this.getSelected().clear();
|
|
||||||
this.stop();
|
|
||||||
afterStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean hasCancelled() {
|
|
||||||
return bCancelled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Collection<T> getSelected();
|
|
||||||
public T getFirstSelected() { return Iterables.getFirst(getSelected(), null); }
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onOk() {
|
|
||||||
this.stop();
|
|
||||||
afterStop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setMessage(String message0) {
|
|
||||||
this.message = message0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onSelectStateChanged(GameEntity c, boolean newState) {
|
|
||||||
if (c instanceof Card) {
|
|
||||||
FControl.setUsedToPay((Card)c, newState); // UI supports card highlighting though this abstraction-breaking mechanism
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void afterStop() {
|
|
||||||
for (GameEntity c : getSelected()) {
|
|
||||||
if (c instanceof Card) {
|
|
||||||
FControl.setUsedToPay((Card)c, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final boolean isUnselectAllowed() { return allowUnselect; }
|
|
||||||
public final void setUnselectAllowed(boolean allow) { this.allowUnselect = allow; }
|
|
||||||
|
|
||||||
public final void setCancelAllowed(boolean allow) { this.allowCancel = allow ; }
|
|
||||||
}
|
|
||||||
@@ -1,265 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.game.GameEntity;
|
|
||||||
import forge.game.GameObject;
|
|
||||||
import forge.game.ability.ApiType;
|
|
||||||
import forge.game.card.Card;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
|
||||||
import forge.game.spellability.TargetRestrictions;
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
import forge.toolbox.GuiChoose;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
public final class InputSelectTargets extends InputSyncronizedBase {
|
|
||||||
private final List<Card> choices;
|
|
||||||
// some cards can be targeted several times (eg: distribute damage as you choose)
|
|
||||||
private final Map<GameEntity, Integer> targetDepth = new HashMap<GameEntity, Integer>();
|
|
||||||
private final TargetRestrictions tgt;
|
|
||||||
private final SpellAbility sa;
|
|
||||||
private Card lastTarget = null;
|
|
||||||
private boolean bCancel = false;
|
|
||||||
private boolean bOk = false;
|
|
||||||
private final boolean mandatory;
|
|
||||||
private static final long serialVersionUID = -1091595663541356356L;
|
|
||||||
|
|
||||||
public final boolean hasCancelled() { return bCancel; }
|
|
||||||
public final boolean hasPressedOk() { return bOk; }
|
|
||||||
/**
|
|
||||||
* TODO: Write javadoc for Constructor.
|
|
||||||
* @param select
|
|
||||||
* @param choices
|
|
||||||
* @param req
|
|
||||||
* @param alreadyTargeted
|
|
||||||
* @param targeted
|
|
||||||
* @param tgt
|
|
||||||
* @param sa
|
|
||||||
* @param mandatory
|
|
||||||
*/
|
|
||||||
public InputSelectTargets(List<Card> choices, SpellAbility sa, boolean mandatory) {
|
|
||||||
this.choices = choices;
|
|
||||||
this.tgt = sa.getTargetRestrictions();
|
|
||||||
this.sa = sa;
|
|
||||||
this.mandatory = mandatory;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showMessage() {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append("Targeted:\n");
|
|
||||||
for (final Entry<GameEntity, Integer> o : targetDepth.entrySet()) {
|
|
||||||
sb.append(o.getKey());
|
|
||||||
if( o.getValue() > 1 )
|
|
||||||
sb.append(" (").append(o.getValue()).append(" times)");
|
|
||||||
sb.append("\n");
|
|
||||||
}
|
|
||||||
if (!sa.getUniqueTargets().isEmpty()) {
|
|
||||||
sb.append("Parent Targeted:");
|
|
||||||
sb.append(sa.getUniqueTargets()).append("\n");
|
|
||||||
}
|
|
||||||
sb.append(sa.getHostCard() + " - " + tgt.getVTSelection());
|
|
||||||
|
|
||||||
int maxTargets = tgt.getMaxTargets(sa.getHostCard(), sa);
|
|
||||||
int targeted = sa.getTargets().getNumTargeted();
|
|
||||||
if(maxTargets > 1)
|
|
||||||
sb.append("\n(").append(maxTargets - targeted).append(" more can be targeted)");
|
|
||||||
|
|
||||||
showMessage(sb.toString());
|
|
||||||
|
|
||||||
// If reached Minimum targets, enable OK button
|
|
||||||
if (!tgt.isMinTargetsChosen(sa.getHostCard(), sa) || tgt.isDividedAsYouChoose()) {
|
|
||||||
if (mandatory && tgt.hasCandidates(sa, true)) {
|
|
||||||
// Player has to click on a target
|
|
||||||
ButtonUtil.disableAll();
|
|
||||||
} else {
|
|
||||||
ButtonUtil.enableOnlyCancel();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (mandatory && tgt.hasCandidates(sa, true)) {
|
|
||||||
// Player has to click on a target or ok
|
|
||||||
ButtonUtil.enableOnlyOk();
|
|
||||||
} else {
|
|
||||||
ButtonUtil.enableAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onCancel() {
|
|
||||||
bCancel = true;
|
|
||||||
this.done();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onOk() {
|
|
||||||
bOk = true;
|
|
||||||
this.done();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onCardSelected(final Card card, final List<Card> orderedCardOptions) {
|
|
||||||
if (!tgt.isUniqueTargets() && targetDepth.containsKey(card)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// leave this in temporarily, there some seriously wrong things going on here
|
|
||||||
// Can be targeted doesn't check if the target is a valid type, only if a card is generally "targetable"
|
|
||||||
if (!card.canBeTargetedBy(sa)) {
|
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this card (Shroud? Protection? Restrictions).");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// If all cards must be from the same zone
|
|
||||||
if (tgt.isSingleZone() && lastTarget != null && !card.getController().equals(lastTarget.getController())) {
|
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this card (not in the same zone)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all cards must be from different zones
|
|
||||||
if (tgt.isDifferentZone() && lastTarget != null && !card.getController().equals(lastTarget.getController().getOpponent())) {
|
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this card (not in different zones)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the cards can't share a creature type
|
|
||||||
if (tgt.isWithoutSameCreatureType() && lastTarget != null && card.sharesCreatureTypeWith(lastTarget)) {
|
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this card (should not share a creature type)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If all cards must have different controllers
|
|
||||||
if (tgt.isDifferentControllers()) {
|
|
||||||
final List<Player> targetedControllers = new ArrayList<Player>();
|
|
||||||
for (GameObject o : targetDepth.keySet()) {
|
|
||||||
if (o instanceof Card) {
|
|
||||||
Player p = ((Card) o).getController();
|
|
||||||
targetedControllers.add(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (targetedControllers.contains(card.getController())) {
|
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this card (must have different controllers)");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!choices.contains(card)) {
|
|
||||||
if (card.isPlaneswalker() && sa.getApi() == ApiType.DealDamage) {
|
|
||||||
showMessage(sa.getHostCard() + " - To deal an opposing Planeswalker direct damage, target its controller and then redirect the damage on resolution.");
|
|
||||||
} else {
|
|
||||||
showMessage(sa.getHostCard() + " - The selected card is not a valid choice to be targeted.");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tgt.isDividedAsYouChoose()) {
|
|
||||||
final int stillToDivide = tgt.getStillToDivide();
|
|
||||||
int allocatedPortion = 0;
|
|
||||||
// allow allocation only if the max targets isn't reached and there are more candidates
|
|
||||||
if ((sa.getTargets().getNumTargeted() + 1 < tgt.getMaxTargets(sa.getHostCard(), sa))
|
|
||||||
&& (tgt.getNumCandidates(sa, true) - 1 > 0) && stillToDivide > 1) {
|
|
||||||
final Integer[] choices = new Integer[stillToDivide];
|
|
||||||
for (int i = 1; i <= stillToDivide; i++) {
|
|
||||||
choices[i - 1] = i;
|
|
||||||
}
|
|
||||||
String apiBasedMessage = "Distribute how much to ";
|
|
||||||
if (sa.getApi() == ApiType.DealDamage) {
|
|
||||||
apiBasedMessage = "Select how much damage to deal to ";
|
|
||||||
} else if (sa.getApi() == ApiType.PreventDamage) {
|
|
||||||
apiBasedMessage = "Select how much damage to prevent to ";
|
|
||||||
} else if (sa.getApi() == ApiType.PutCounter) {
|
|
||||||
apiBasedMessage = "Select how many counters to distribute to ";
|
|
||||||
}
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(apiBasedMessage);
|
|
||||||
sb.append(card.toString());
|
|
||||||
Integer chosen = GuiChoose.oneOrNone(sb.toString(), choices);
|
|
||||||
if (null == chosen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
allocatedPortion = chosen;
|
|
||||||
} else { // otherwise assign the rest of the damage/protection
|
|
||||||
allocatedPortion = stillToDivide;
|
|
||||||
}
|
|
||||||
tgt.setStillToDivide(stillToDivide - allocatedPortion);
|
|
||||||
tgt.addDividedAllocation(card, allocatedPortion);
|
|
||||||
}
|
|
||||||
addTarget(card);
|
|
||||||
} // selectCard()
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected final void onPlayerSelected(Player player) {
|
|
||||||
if (!tgt.isUniqueTargets() && targetDepth.containsKey(player)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sa.canTarget(player)) {
|
|
||||||
showMessage(sa.getHostCard() + " - Cannot target this player (Hexproof? Protection? Restrictions?).");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tgt.isDividedAsYouChoose()) {
|
|
||||||
final int stillToDivide = tgt.getStillToDivide();
|
|
||||||
int allocatedPortion = 0;
|
|
||||||
// allow allocation only if the max targets isn't reached and there are more candidates
|
|
||||||
if ((sa.getTargets().getNumTargeted() + 1 < tgt.getMaxTargets(sa.getHostCard(), sa)) && (tgt.getNumCandidates(sa, true) - 1 > 0) && stillToDivide > 1) {
|
|
||||||
final Integer[] choices = new Integer[stillToDivide];
|
|
||||||
for (int i = 1; i <= stillToDivide; i++) {
|
|
||||||
choices[i - 1] = i;
|
|
||||||
}
|
|
||||||
String apiBasedMessage = "Distribute how much to ";
|
|
||||||
if (sa.getApi() == ApiType.DealDamage) {
|
|
||||||
apiBasedMessage = "Select how much damage to deal to ";
|
|
||||||
} else if (sa.getApi() == ApiType.PreventDamage) {
|
|
||||||
apiBasedMessage = "Select how much damage to prevent to ";
|
|
||||||
}
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append(apiBasedMessage);
|
|
||||||
sb.append(player.getName());
|
|
||||||
Integer chosen = GuiChoose.oneOrNone(sb.toString(), choices);
|
|
||||||
if (null == chosen) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
allocatedPortion = chosen;
|
|
||||||
} else { // otherwise assign the rest of the damage/protection
|
|
||||||
allocatedPortion = stillToDivide;
|
|
||||||
}
|
|
||||||
tgt.setStillToDivide(stillToDivide - allocatedPortion);
|
|
||||||
tgt.addDividedAllocation(player, allocatedPortion);
|
|
||||||
}
|
|
||||||
addTarget(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addTarget(GameEntity ge) {
|
|
||||||
sa.getTargets().add(ge);
|
|
||||||
if (ge instanceof Card) {
|
|
||||||
FControl.setUsedToPay((Card) ge, true);
|
|
||||||
}
|
|
||||||
Integer val = targetDepth.get(ge);
|
|
||||||
targetDepth.put(ge, val == null ? Integer.valueOf(1) : Integer.valueOf(val.intValue() + 1) );
|
|
||||||
|
|
||||||
if (hasAllTargets()) {
|
|
||||||
bOk = true;
|
|
||||||
this.done();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.showMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void done() {
|
|
||||||
for (GameEntity c : targetDepth.keySet()) {
|
|
||||||
if (c instanceof Card) {
|
|
||||||
FControl.setUsedToPay((Card)c, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasAllTargets() {
|
|
||||||
return tgt.isMaxTargetsChosen(sa.getHostCard(), sa) || ( tgt.getStillToDivide() == 0 && tgt.isDividedAsYouChoose());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
public interface InputSynchronized extends Input {
|
|
||||||
void awaitLatchRelease();
|
|
||||||
void relaseLatchWhenGameIsOver();
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
package forge.screens.match.input;
|
|
||||||
|
|
||||||
import forge.FThreads;
|
|
||||||
import forge.error.BugReporter;
|
|
||||||
import forge.screens.match.FControl;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
|
|
||||||
public abstract class InputSyncronizedBase extends InputBase implements InputSynchronized {
|
|
||||||
private static final long serialVersionUID = 8756177361251703052L;
|
|
||||||
private final CountDownLatch cdlDone;
|
|
||||||
|
|
||||||
public InputSyncronizedBase() {
|
|
||||||
cdlDone = new CountDownLatch(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void awaitLatchRelease() {
|
|
||||||
FThreads.assertExecutedByEdt(false);
|
|
||||||
try{
|
|
||||||
cdlDone.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
BugReporter.reportException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void relaseLatchWhenGameIsOver() {
|
|
||||||
cdlDone.countDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showAndWait() {
|
|
||||||
FControl.getInputQueue().setInput(this);
|
|
||||||
awaitLatchRelease();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final void stop() {
|
|
||||||
onStop();
|
|
||||||
|
|
||||||
// ensure input won't accept any user actions.
|
|
||||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
setFinished();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// thread irrelevant
|
|
||||||
FControl.getInputQueue().removeInput(InputSyncronizedBase.this);
|
|
||||||
cdlDone.countDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void onStop() { }
|
|
||||||
}
|
|
||||||
@@ -24,7 +24,7 @@ public class VAvatar extends FDisplayObject {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tap(float x, float y, int count) {
|
public boolean tap(float x, float y, int count) {
|
||||||
FControl.getInputProxy().selectPlayer(player);
|
FControl.getInputProxy().selectPlayer(player, null);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import forge.FThreads;
|
import forge.FThreads;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.screens.match.FControl;
|
import forge.screens.match.InputSelectCard;
|
||||||
import forge.toolbox.FCardPanel;
|
import forge.toolbox.FCardPanel;
|
||||||
|
|
||||||
public abstract class VCardDisplayArea extends VDisplayArea {
|
public abstract class VCardDisplayArea extends VDisplayArea {
|
||||||
@@ -166,10 +166,28 @@ public abstract class VCardDisplayArea extends VDisplayArea {
|
|||||||
return attachedPanels;
|
return attachedPanels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum AttackOption {
|
||||||
|
DECLARE_AS_ATTACKER("Declare as Attacker"),
|
||||||
|
REMOVE_FROM_COMBAT("Remove from Combat"),
|
||||||
|
ATTACK_THIS_DEFENDER("Attack this Defender"),
|
||||||
|
ACTIVATE_BAND("Activate Band"),
|
||||||
|
JOIN_BAND("Join Band");
|
||||||
|
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
private AttackOption(String text0) {
|
||||||
|
text = text0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tap(float x, float y, int count) {
|
public boolean tap(float x, float y, int count) {
|
||||||
if (displayArea != null) {
|
if (displayArea != null) {
|
||||||
FControl.getInputProxy().selectCard(getCard(), new ArrayList<Card>(displayArea.orderedCards)); //copy list to allow it being modified
|
InputSelectCard.selectCard(getCard(), displayArea.orderedCards);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import forge.game.spellability.SpellAbility;
|
|||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.item.IPaperCard;
|
import forge.item.IPaperCard;
|
||||||
import forge.item.PaperCard;
|
import forge.item.PaperCard;
|
||||||
|
import forge.match.input.InputSelectCardsFromList;
|
||||||
import forge.menu.FDropDownMenu;
|
import forge.menu.FDropDownMenu;
|
||||||
import forge.menu.FMenuItem;
|
import forge.menu.FMenuItem;
|
||||||
import forge.model.FModel;
|
import forge.model.FModel;
|
||||||
@@ -31,7 +32,6 @@ import forge.properties.ForgeConstants;
|
|||||||
import forge.properties.ForgePreferences;
|
import forge.properties.ForgePreferences;
|
||||||
import forge.properties.ForgePreferences.FPref;
|
import forge.properties.ForgePreferences.FPref;
|
||||||
import forge.screens.match.FControl;
|
import forge.screens.match.FControl;
|
||||||
import forge.screens.match.input.InputSelectCardsFromList;
|
|
||||||
import forge.toolbox.FEvent;
|
import forge.toolbox.FEvent;
|
||||||
import forge.toolbox.GuiChoose;
|
import forge.toolbox.GuiChoose;
|
||||||
import forge.toolbox.GuiDialog;
|
import forge.toolbox.GuiDialog;
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ import forge.assets.FSkinColor.Colors;
|
|||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.game.mana.ManaPool;
|
import forge.game.mana.ManaPool;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
import forge.match.input.Input;
|
||||||
|
import forge.match.input.InputPayMana;
|
||||||
import forge.net.FServer;
|
import forge.net.FServer;
|
||||||
import forge.screens.match.FControl;
|
import forge.screens.match.FControl;
|
||||||
import forge.screens.match.input.Input;
|
|
||||||
import forge.screens.match.input.InputPayMana;
|
|
||||||
import forge.toolbox.FDisplayObject;
|
import forge.toolbox.FDisplayObject;
|
||||||
|
|
||||||
public class VManaPool extends VDisplayArea {
|
public class VManaPool extends VDisplayArea {
|
||||||
|
|||||||
@@ -262,7 +262,7 @@ public class GuiChoose {
|
|||||||
return order("Sideboard", "Main Deck", -1, -1, sideboard, deck, null, true);
|
return order("Sideboard", "Main Deck", -1, -1, sideboard, deck, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> List<T> order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax,
|
public static <T> List<T> order(final String title, final String top, final int remainingObjectsMin, final int remainingObjectsMax,
|
||||||
final List<T> sourceChoices, final List<T> destChoices, final Card referenceCard, final boolean sideboardingMode) {
|
final List<T> sourceChoices, final List<T> destChoices, final Card referenceCard, final boolean sideboardingMode) {
|
||||||
// An input box for handling the order of choices.
|
// An input box for handling the order of choices.
|
||||||
|
|
||||||
|
|||||||
@@ -1,28 +1,22 @@
|
|||||||
package forge.match.input;
|
package forge.match.input;
|
||||||
|
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: Write javadoc for this type.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface Input {
|
public interface Input {
|
||||||
|
|
||||||
// showMessage() is always the first method called
|
|
||||||
void showMessageInitial();
|
void showMessageInitial();
|
||||||
|
|
||||||
void selectCard(Card c, MouseEvent triggerEvent);
|
void selectCard(Card c, MouseEvent triggerEvent);
|
||||||
|
|
||||||
void selectAbility(SpellAbility ab);
|
void selectAbility(SpellAbility ab);
|
||||||
|
|
||||||
void selectPlayer(Player player, MouseEvent triggerEven);
|
void selectPlayer(Player player, MouseEvent triggerEvent);
|
||||||
|
|
||||||
void selectButtonOK();
|
void selectButtonOK();
|
||||||
|
|
||||||
void selectButtonCancel();
|
void selectButtonCancel();
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user