mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 02:38:02 +00:00
Merge branch 'master' of git.cardforge.org:core-developers/forge into custom-pool-options
This commit is contained in:
@@ -4,6 +4,9 @@ import java.awt.image.BufferedImage;
|
||||
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.util.ImageFetcher;
|
||||
import forge.util.SwingImageFetcher;
|
||||
|
||||
|
||||
public abstract class CachedCardImage implements ImageFetcher.Callback {
|
||||
final CardView card;
|
||||
@@ -11,6 +14,8 @@ public abstract class CachedCardImage implements ImageFetcher.Callback {
|
||||
final int width;
|
||||
final int height;
|
||||
|
||||
static final SwingImageFetcher fetcher = new SwingImageFetcher();
|
||||
|
||||
public CachedCardImage(final CardView card, final Iterable<PlayerView> viewers, final int width, final int height) {
|
||||
this.card = card;
|
||||
this.viewers = viewers;
|
||||
@@ -19,7 +24,7 @@ public abstract class CachedCardImage implements ImageFetcher.Callback {
|
||||
BufferedImage image = ImageCache.getImageNoDefault(card, viewers, width, height);
|
||||
if (image == null) {
|
||||
String key = card.getCurrentState().getImageKey(viewers);
|
||||
ImageFetcher.fetchImage(card, key, this);
|
||||
fetcher.fetchImage(key, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,7 @@ import forge.sound.*;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.FSkin;
|
||||
import forge.toolbox.FSkin.SkinImage;
|
||||
import forge.util.BuildInfo;
|
||||
import forge.util.Callback;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.OperatingSystem;
|
||||
import forge.util.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -42,6 +39,8 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class GuiDesktop implements IGuiBase {
|
||||
private ImageFetcher imageFetcher = new SwingImageFetcher();
|
||||
|
||||
@Override
|
||||
public boolean isRunningOnDesktop() {
|
||||
return true;
|
||||
@@ -63,6 +62,11 @@ public class GuiDesktop implements IGuiBase {
|
||||
"../forge-gui/" : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImageFetcher getImageFetcher() {
|
||||
return imageFetcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invokeInEdtNow(final Runnable proc) {
|
||||
proc.run();
|
||||
|
||||
@@ -1,168 +0,0 @@
|
||||
package forge;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
import forge.game.card.CardView;
|
||||
import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.ImageUtil;
|
||||
|
||||
public class ImageFetcher {
|
||||
private static final ExecutorService threadPool = Executors.newCachedThreadPool();
|
||||
private static HashMap<String, HashSet<Callback>> currentFetches = new HashMap<>();
|
||||
private static HashMap<String, String> tokenImages;
|
||||
|
||||
public static void fetchImage(final CardView card, final String imageKey, final Callback callback) {
|
||||
FThreads.assertExecutedByEdt(true);
|
||||
|
||||
if (!FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ENABLE_ONLINE_IMAGE_FETCHER))
|
||||
return;
|
||||
|
||||
// Fake card (like the ante prompt) trying to be "fetched"
|
||||
if (imageKey.length() < 2)
|
||||
return;
|
||||
|
||||
final String prefix = imageKey.substring(0, 2);
|
||||
final ArrayList<String> downloadUrls = new ArrayList<>();
|
||||
File destFile = null;
|
||||
if (prefix.equals(ImageKeys.CARD_PREFIX)) {
|
||||
PaperCard paperCard = ImageUtil.getPaperCardFromImageKey(imageKey);
|
||||
if (paperCard == null) {
|
||||
System.err.println("Paper card not found for: " + imageKey);
|
||||
return;
|
||||
}
|
||||
final boolean backFace = imageKey.endsWith(ImageKeys.BACKFACE_POSTFIX);
|
||||
final String filename = ImageUtil.getImageKey(paperCard, backFace, true);
|
||||
destFile = new File(ForgeConstants.CACHE_CARD_PICS_DIR + "/" + filename + ".jpg");
|
||||
|
||||
// First try to download the LQ Set URL, then fetch from scryfall/magiccards.info
|
||||
StringBuilder setDownload = new StringBuilder(ForgeConstants.URL_PIC_DOWNLOAD);
|
||||
setDownload.append(ImageUtil.getDownloadUrl(paperCard, backFace));
|
||||
downloadUrls.add(setDownload.toString());
|
||||
|
||||
final StaticData data = StaticData.instance();
|
||||
final int cardNum = data.getCommonCards().getCardCollectorNumber(paperCard.getName(), paperCard.getEdition());
|
||||
if (cardNum != -1) {
|
||||
String suffix = "";
|
||||
if (paperCard.getRules().getOtherPart() != null) {
|
||||
suffix = (backFace ? "b" : "a");
|
||||
}
|
||||
final String editionMciCode = data.getEditions().getMciCodeByCode(paperCard.getEdition());
|
||||
downloadUrls.add(String.format("https://img.scryfall.com/cards/normal/en/%s/%d%s.jpg", editionMciCode, cardNum, suffix));
|
||||
downloadUrls.add(String.format("https://magiccards.info/scans/en/%s/%d%s.jpg", editionMciCode, cardNum, suffix));
|
||||
}
|
||||
} else if (prefix.equals(ImageKeys.TOKEN_PREFIX)) {
|
||||
if (tokenImages == null) {
|
||||
tokenImages = new HashMap<>();
|
||||
for (Pair<String, String> nameUrlPair : FileUtil.readNameUrlFile(ForgeConstants.IMAGE_LIST_TOKENS_FILE)) {
|
||||
tokenImages.put(nameUrlPair.getLeft(), nameUrlPair.getRight());
|
||||
}
|
||||
}
|
||||
final String filename = imageKey.substring(2) + ".jpg";
|
||||
String tokenUrl = tokenImages.get(filename);
|
||||
if (tokenUrl == null) {
|
||||
System.err.println("No specified file.. Attempting to download from default Url");
|
||||
tokenUrl = String.format("%s%s", ForgeConstants.URL_TOKEN_DOWNLOAD, filename);
|
||||
}
|
||||
destFile = new File(ForgeConstants.CACHE_TOKEN_PICS_DIR, filename);
|
||||
downloadUrls.add(tokenUrl);
|
||||
}
|
||||
|
||||
if (downloadUrls.isEmpty()) {
|
||||
System.err.println("No download URLs for: " + imageKey);
|
||||
return;
|
||||
}
|
||||
|
||||
if (destFile.exists()) {
|
||||
// TODO: Figure out why this codepath gets reached. Ideally, fetchImage() wouldn't
|
||||
// be called if we already have the image.
|
||||
return;
|
||||
}
|
||||
final String destPath = destFile.getAbsolutePath();
|
||||
|
||||
// Note: No synchronization is needed here because this is executed on
|
||||
// EDT thread (see assert on top) and so is the notification of observers.
|
||||
HashSet<Callback> observers = currentFetches.get(destPath);
|
||||
if (observers != null) {
|
||||
// Already in the queue, simply add the new observer.
|
||||
observers.add(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
observers = new HashSet<>();
|
||||
observers.add(callback);
|
||||
currentFetches.put(destPath, observers);
|
||||
|
||||
final Runnable notifyObservers = new Runnable() {
|
||||
public void run() {
|
||||
FThreads.assertExecutedByEdt(true);
|
||||
|
||||
for (Callback o : currentFetches.get(destPath)) {
|
||||
o.onImageFetched();
|
||||
}
|
||||
currentFetches.remove(destPath);
|
||||
}
|
||||
};
|
||||
threadPool.submit(new DownloadTask(downloadUrls.toArray(new String[0]), destPath, notifyObservers));
|
||||
}
|
||||
|
||||
public static interface Callback {
|
||||
public void onImageFetched();
|
||||
}
|
||||
|
||||
private static class DownloadTask implements Runnable {
|
||||
private final String[] downloadUrls;
|
||||
private final String destPath;
|
||||
private final Runnable notifyObservers;
|
||||
|
||||
public DownloadTask(String[] downloadUrls, String destPath, Runnable notifyObservers) {
|
||||
this.downloadUrls = downloadUrls;
|
||||
this.destPath = destPath;
|
||||
this.notifyObservers = notifyObservers;
|
||||
}
|
||||
|
||||
private void doFetch(String urlToDownload) throws IOException {
|
||||
URL url = new URL(urlToDownload);
|
||||
System.out.println("Attempting to fetch: " + url);
|
||||
java.net.URLConnection c = url.openConnection();
|
||||
c.setRequestProperty("User-Agent", "");
|
||||
BufferedImage image = ImageIO.read(c.getInputStream());
|
||||
// First, save to a temporary file so that nothing tries to read
|
||||
// a partial download.
|
||||
File destFile = new File(destPath + ".tmp");
|
||||
destFile.mkdirs();
|
||||
ImageIO.write(image, "jpg", destFile);
|
||||
// Now, rename it to the correct name.
|
||||
destFile.renameTo(new File(destPath));
|
||||
System.out.println("Saved image to " + destPath);
|
||||
SwingUtilities.invokeLater(notifyObservers);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
for (String urlToDownload : downloadUrls) {
|
||||
try {
|
||||
doFetch(urlToDownload);
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
System.out.println("Failed to download card [" + destPath + "] image: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,9 @@ import java.awt.image.WritableRaster;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import forge.GuiBase;
|
||||
import forge.ImageCache;
|
||||
import forge.ImageFetcher;
|
||||
import forge.util.ImageFetcher;
|
||||
import forge.ImageKeys;
|
||||
import forge.game.card.CardView.CardStateView;
|
||||
import forge.item.InventoryItem;
|
||||
@@ -115,7 +116,7 @@ public final class CardPicturePanel extends JPanel implements ImageFetcher.Callb
|
||||
CardStateView card = (CardStateView) displayed;
|
||||
BufferedImage image = ImageCache.getOriginalImage(card.getImageKey(), false);
|
||||
if (image == null) {
|
||||
ImageFetcher.fetchImage(card.getCard(), card.getImageKey(), this);
|
||||
GuiBase.getInterface().getImageFetcher().fetchImage(card.getImageKey(), this);
|
||||
}
|
||||
return FImageUtil.getImage((CardStateView) displayed);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import forge.item.PaperCard;
|
||||
import forge.model.FModel;
|
||||
import forge.screens.match.CMatchUI;
|
||||
import forge.toolbox.FOptionPane;
|
||||
|
||||
import forge.view.arcane.ListCardArea;
|
||||
|
||||
public class GuiChoose {
|
||||
|
||||
@@ -285,5 +285,30 @@ public class GuiChoose {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static List<CardView> manipulateCardList(final CMatchUI gui, final String title, final Iterable<CardView> cards, final Iterable<CardView> manipulable,
|
||||
final boolean toTop, final boolean toBottom, final boolean toAnywhere) {
|
||||
gui.setSelectables(manipulable);
|
||||
final Callable<List<CardView>> callable = new Callable<List<CardView>>() {
|
||||
@Override
|
||||
public List<CardView> call() throws Exception {
|
||||
ListCardArea tempArea = ListCardArea.show(gui,title,cards,manipulable,toTop,toBottom,toAnywhere);
|
||||
// tempArea.pack();
|
||||
tempArea.show();
|
||||
final List<CardView> cardList = tempArea.getCards();
|
||||
return cardList;
|
||||
}
|
||||
};
|
||||
final FutureTask<List<CardView>> ft = new FutureTask<List<CardView>>(callable);
|
||||
FThreads.invokeInEdtAndWait(ft);
|
||||
gui.clearSelectables();
|
||||
try {
|
||||
List<CardView> result = ft.get();
|
||||
return result;
|
||||
} catch (final Exception e) { // we have waited enough
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -147,27 +147,72 @@ public final class DeckManager extends ItemManager<DeckProxy> implements IHasGam
|
||||
return new DeckSearchFilter(this);
|
||||
}
|
||||
|
||||
private Map<String, HashMap> buildHierarchy(String path) {
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
Map hierarchy = new HashMap();
|
||||
String[] components = path.split("/", 2);
|
||||
Map value = new HashMap();
|
||||
if (components.length > 1) {
|
||||
value = buildHierarchy(components[1]);
|
||||
}
|
||||
hierarchy.put("/" + components[0], value);
|
||||
return hierarchy;
|
||||
}
|
||||
|
||||
// borrowed from: https://stackoverflow.com/a/46052477
|
||||
private void merge(Map<String, HashMap> mapLeft, Map<String, HashMap> mapRight) {
|
||||
// go over all the keys of the right map
|
||||
for (String key : mapRight.keySet()) {
|
||||
// if the left map already has this key, merge the maps that are behind that key
|
||||
if (mapLeft.containsKey(key)) {
|
||||
merge(mapLeft.get(key), mapRight.get(key));
|
||||
} else {
|
||||
// otherwise just add the map under that key
|
||||
mapLeft.put(key, mapRight.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void buildNestedMenu(Map tree, JMenu menu, String parentPath) {
|
||||
if (tree.size() > 0) {
|
||||
for (final Object key : tree.keySet()) {
|
||||
String fullPath = key.toString();
|
||||
if (parentPath != null) {
|
||||
fullPath = parentPath + key.toString();
|
||||
}
|
||||
String finalFullPath = fullPath;
|
||||
GuiUtils.addMenuItem(menu, key.toString(), null, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
addFilter(new DeckFolderFilter(DeckManager.this, finalFullPath));
|
||||
}
|
||||
}, true);
|
||||
Map value = (Map) tree.get(key);
|
||||
if (value.size() > 0) {
|
||||
final JMenu submenu = GuiUtils.createMenu(key.toString());
|
||||
buildNestedMenu(value, submenu, finalFullPath);
|
||||
menu.add(submenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildAddFilterMenu(final JMenu menu) {
|
||||
GuiUtils.addSeparator(menu); //separate from current search item
|
||||
|
||||
final SortedSet<String> folders = new TreeSet<String>();
|
||||
Map hierarchy = new HashMap();
|
||||
for (final Entry<DeckProxy, Integer> deckEntry : getPool()) {
|
||||
final String path = deckEntry.getKey().getPath();
|
||||
if (StringUtils.isNotEmpty(path)) { //don't include root folder as option
|
||||
folders.add(path);
|
||||
merge(hierarchy, buildHierarchy(path));
|
||||
}
|
||||
}
|
||||
final JMenu folder = GuiUtils.createMenu("Folder");
|
||||
if (folders.size() > 0) {
|
||||
for (final String f : folders) {
|
||||
GuiUtils.addMenuItem(folder, f, null, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
addFilter(new DeckFolderFilter(DeckManager.this, f));
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
if (hierarchy.size() > 0) {
|
||||
buildNestedMenu(hierarchy, folder, null);
|
||||
}
|
||||
else {
|
||||
folder.setEnabled(false);
|
||||
|
||||
@@ -17,8 +17,11 @@ import forge.Singletons;
|
||||
import forge.gui.GuiUtils;
|
||||
import forge.screens.home.online.OnlineMenu;
|
||||
import forge.util.ReflectionUtil;
|
||||
import forge.util.Localizer;
|
||||
|
||||
|
||||
public final class ForgeMenu {
|
||||
|
||||
private JPopupMenu popupMenu;
|
||||
private IMenuProvider provider;
|
||||
private static HashMap<KeyStroke, JMenuItem> activeShortcuts = new HashMap<KeyStroke, JMenuItem>();
|
||||
@@ -123,7 +126,8 @@ public final class ForgeMenu {
|
||||
}
|
||||
|
||||
private static JMenuItem getMenuItem_Restart() {
|
||||
JMenuItem menuItem = new JMenuItem("Restart");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
JMenuItem menuItem = new JMenuItem(localizer.getMessage("lblRestart"));
|
||||
menuItem.setMnemonic(KeyEvent.VK_R);
|
||||
menuItem.addActionListener(getRestartAction());
|
||||
return menuItem;
|
||||
@@ -139,7 +143,8 @@ public final class ForgeMenu {
|
||||
}
|
||||
|
||||
private static JMenuItem getMenuItem_Exit() {
|
||||
JMenuItem menuItem = new JMenuItem("Exit");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
JMenuItem menuItem = new JMenuItem(localizer.getMessage("lblExit"));
|
||||
menuItem.setMnemonic(KeyEvent.VK_X);
|
||||
menuItem.addActionListener(getExitAction());
|
||||
return menuItem;
|
||||
|
||||
@@ -4,6 +4,7 @@ import forge.properties.ForgeConstants;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.util.BuildInfo;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.Localizer;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
@@ -18,7 +19,8 @@ public final class HelpMenu {
|
||||
private HelpMenu() { }
|
||||
|
||||
public static JMenu getMenu() {
|
||||
JMenu menu = new JMenu("Help");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
JMenu menu = new JMenu(localizer.getMessage("lblHelp"));
|
||||
menu.setMnemonic(KeyEvent.VK_H);
|
||||
menu.add(getMenu_GettingStarted());
|
||||
menu.add(getMenu_Articles());
|
||||
@@ -32,7 +34,8 @@ public final class HelpMenu {
|
||||
}
|
||||
|
||||
private static JMenuItem getMenuItem_About() {
|
||||
JMenuItem menuItem = new JMenuItem("About Forge...");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
JMenuItem menuItem = new JMenuItem(localizer.getMessage("lblAboutForge")+ "...");
|
||||
menuItem.addActionListener(getAboutForgeAction());
|
||||
return menuItem;
|
||||
}
|
||||
@@ -41,15 +44,17 @@ public final class HelpMenu {
|
||||
return new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
FOptionPane.showMessageDialog(
|
||||
"Version : " + BuildInfo.getVersionString(),
|
||||
"About Forge");
|
||||
localizer.getMessage("lblAboutForge"));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static JMenu getMenu_Troubleshooting() {
|
||||
JMenu mnu = new JMenu("Troubleshooting");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
JMenu mnu = new JMenu(localizer.getMessage("lblTroubleshooting"));
|
||||
mnu.add(getMenuItem_UrlLink("How to Provide a Useful Bug Report", "http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=9621"));
|
||||
mnu.addSeparator();
|
||||
mnu.add(getMenuItem_ReadMeFile());
|
||||
@@ -57,14 +62,16 @@ public final class HelpMenu {
|
||||
}
|
||||
|
||||
private static JMenu getMenu_Articles() {
|
||||
JMenu mnu = new JMenu("Articles");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
JMenu mnu = new JMenu(localizer.getMessage("lblArticles"));
|
||||
mnu.add(getMenuItem_UrlLink("HOW-TO: Customize your Sealed Deck games with fantasy blocks", "http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=8164"));
|
||||
mnu.add(getMenuItem_UrlLink("Quest Mode: Guide to Formats, Worlds, and everything", "http://www.slightlymagic.net/forum/viewtopic.php?f=26&t=9258"));
|
||||
return mnu;
|
||||
}
|
||||
|
||||
private static JMenu getMenu_GettingStarted() {
|
||||
JMenu mnu = new JMenu("Getting Started");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
JMenu mnu = new JMenu(localizer.getMessage("lblGettingStarted"));
|
||||
mnu.add(getMenuItem_HowToPlayFile());
|
||||
mnu.addSeparator();
|
||||
mnu.add(getMenuItem_UrlLink("Forge Wiki", "http://www.slightlymagic.net/wiki/Forge", KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0)));
|
||||
@@ -73,7 +80,8 @@ public final class HelpMenu {
|
||||
}
|
||||
|
||||
private static JMenuItem getMenuItem_HowToPlayFile() {
|
||||
JMenuItem menuItem = new JMenuItem("How to Play");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
JMenuItem menuItem = new JMenuItem(localizer.getMessage("lblHowtoPlay"));
|
||||
menuItem.addActionListener(getOpenFileAction(getFile(ForgeConstants.HOWTO_FILE)));
|
||||
return menuItem;
|
||||
}
|
||||
@@ -85,13 +93,15 @@ public final class HelpMenu {
|
||||
}
|
||||
|
||||
private static JMenuItem getMenuItem_License() {
|
||||
JMenuItem menuItem = new JMenuItem("Forge License");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
JMenuItem menuItem = new JMenuItem(localizer.getMessage("lblForgeLicense"));
|
||||
menuItem.addActionListener(getOpenFileAction(getFile(ForgeConstants.LICENSE_FILE)));
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
private static JMenuItem getMenuItem_ReleaseNotes() {
|
||||
JMenuItem menuItem = new JMenuItem("Release Notes");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
JMenuItem menuItem = new JMenuItem(localizer.getMessage("lblReleaseNotes"));
|
||||
menuItem.addActionListener(getOpenFileAction(getFile(ForgeConstants.CHANGES_FILE)));
|
||||
return menuItem;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import forge.toolbox.FSkin;
|
||||
import forge.toolbox.FSkin.SkinnedMenuItem;
|
||||
import forge.view.FFrame;
|
||||
import forge.view.FView;
|
||||
import forge.util.Localizer;
|
||||
|
||||
/**
|
||||
* Returns a JMenu containing options associated with game screen layout.
|
||||
@@ -42,8 +43,8 @@ public final class LayoutMenu {
|
||||
|
||||
public JMenu getMenu() {
|
||||
currentScreen = Singletons.getControl().getCurrentScreen();
|
||||
|
||||
final JMenu menu = new JMenu("Layout");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final JMenu menu = new JMenu(localizer.getMessage("lblLayout"));
|
||||
menu.setMnemonic(KeyEvent.VK_L);
|
||||
if (currentScreen != FScreen.HOME_SCREEN) {
|
||||
menu.add(getMenu_ViewOptions());
|
||||
@@ -60,7 +61,8 @@ public final class LayoutMenu {
|
||||
}
|
||||
|
||||
private JMenu getMenu_ViewOptions() {
|
||||
final JMenu menu = new JMenu("View");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final JMenu menu = new JMenu(localizer.getMessage("lblView"));
|
||||
menu.add(getMenuItem_ShowTabs());
|
||||
if (currentScreen != null && currentScreen.isMatchScreen()) {
|
||||
menu.add(getMenuItem_ShowBackgroundImage());
|
||||
@@ -69,14 +71,16 @@ public final class LayoutMenu {
|
||||
}
|
||||
|
||||
private JMenu getMenu_FileOptions() {
|
||||
final JMenu menu = new JMenu("File");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final JMenu menu = new JMenu(localizer.getMessage("lblFile"));
|
||||
menu.add(getMenuItem_OpenLayout());
|
||||
menu.add(getMenuItem_SaveLayout());
|
||||
return menu;
|
||||
}
|
||||
|
||||
private static JMenu getMenu_ThemeOptions() {
|
||||
final JMenu menu = new JMenu("Theme");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final JMenu menu = new JMenu(localizer.getMessage("lblTheme"));
|
||||
JRadioButtonMenuItem menuItem;
|
||||
final ButtonGroup group = new ButtonGroup();
|
||||
final String currentSkin = prefs.getPref(FPref.UI_SKIN);
|
||||
@@ -102,7 +106,8 @@ public final class LayoutMenu {
|
||||
};
|
||||
|
||||
private static JMenuItem getMenuItem_ShowBackgroundImage() {
|
||||
final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem("Background Image");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(localizer.getMessage("lblBackgroundImage"));
|
||||
menuItem.setState(prefs.getPrefBoolean(FPref.UI_MATCH_IMAGE_VISIBLE));
|
||||
menuItem.addActionListener(getShowBackgroundImageAction(menuItem));
|
||||
return menuItem;
|
||||
@@ -124,7 +129,8 @@ public final class LayoutMenu {
|
||||
}
|
||||
|
||||
private static JMenuItem getMenuItem_ShowTabs() {
|
||||
final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem("Panel Tabs");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(localizer.getMessage("lblPanelTabs"));
|
||||
menuItem.setAccelerator(MenuUtil.getAcceleratorKey(KeyEvent.VK_T));
|
||||
menuItem.setState(!prefs.getPrefBoolean(FPref.UI_HIDE_GAME_TABS));
|
||||
menuItem.addActionListener(getShowTabsAction(menuItem));
|
||||
@@ -142,7 +148,8 @@ public final class LayoutMenu {
|
||||
}
|
||||
|
||||
private JMenuItem getMenuItem_SaveLayout() {
|
||||
final SkinnedMenuItem menuItem = new SkinnedMenuItem("Save Current Layout");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final SkinnedMenuItem menuItem = new SkinnedMenuItem(localizer.getMessage("lblSaveCurrentLayout"));
|
||||
menuItem.setIcon((showIcons ? MenuUtil.getMenuIcon(FSkinProp.ICO_SAVELAYOUT) : null));
|
||||
menuItem.addActionListener(getSaveLayoutAction());
|
||||
return menuItem;
|
||||
@@ -157,7 +164,8 @@ public final class LayoutMenu {
|
||||
}
|
||||
|
||||
private JMenuItem getMenuItem_OpenLayout() {
|
||||
final SkinnedMenuItem menuItem = new SkinnedMenuItem("Open...");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final SkinnedMenuItem menuItem = new SkinnedMenuItem(localizer.getMessage("lblOpen") +"..");
|
||||
menuItem.setIcon((showIcons ? MenuUtil.getMenuIcon(FSkinProp.ICO_OPENLAYOUT) : null));
|
||||
menuItem.addActionListener(getOpenLayoutAction());
|
||||
return menuItem;
|
||||
@@ -172,7 +180,8 @@ public final class LayoutMenu {
|
||||
}
|
||||
|
||||
private JMenuItem getMenuItem_RevertLayout() {
|
||||
final SkinnedMenuItem menuItem = new SkinnedMenuItem("Refresh");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final SkinnedMenuItem menuItem = new SkinnedMenuItem(localizer.getMessage("lblRefresh"));
|
||||
menuItem.setIcon((showIcons ? MenuUtil.getMenuIcon(FSkinProp.ICO_REVERTLAYOUT) : null));
|
||||
menuItem.addActionListener(getRevertLayoutAction());
|
||||
return menuItem;
|
||||
@@ -187,7 +196,8 @@ public final class LayoutMenu {
|
||||
}
|
||||
|
||||
private static JMenuItem getMenuItem_SetWindowSize() {
|
||||
final JMenuItem menuItem = new JMenuItem("Set Window Size");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final JMenuItem menuItem = new JMenuItem(localizer.getMessage("lblSetWindowSize"));
|
||||
menuItem.addActionListener(getSetWindowSizeAction());
|
||||
return menuItem;
|
||||
}
|
||||
@@ -196,7 +206,8 @@ public final class LayoutMenu {
|
||||
return new ActionListener() {
|
||||
@Override public void actionPerformed(final ActionEvent e) {
|
||||
final String[] options = {"800x600", "1024x768", "1280x720"};
|
||||
final String choice = GuiChoose.oneOrNone("Choose new window size", options);
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
final String choice = GuiChoose.oneOrNone(localizer.getMessage("lblChooseNewWindowSize"), options);
|
||||
if (choice != null) {
|
||||
final String[] dims = choice.split("x");
|
||||
Singletons.getView().getFrame().setSize(Integer.parseInt(dims[0]), Integer.parseInt(dims[1]));
|
||||
@@ -207,10 +218,12 @@ public final class LayoutMenu {
|
||||
|
||||
private static JMenuItem fullScreenItem;
|
||||
public static void updateFullScreenItemText() {
|
||||
fullScreenItem.setText(Singletons.getView().getFrame().isFullScreen() ? "Exit Full Screen" : "Full Screen");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
fullScreenItem.setText(Singletons.getView().getFrame().isFullScreen() ? localizer.getMessage("lblExitFullScreen") : localizer.getMessage("lblFullScreen"));
|
||||
}
|
||||
private static JMenuItem getMenuItem_FullScreen() {
|
||||
fullScreenItem = new JMenuItem("Full Screen");
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
fullScreenItem = new JMenuItem(localizer.getMessage("lblFullScreen"));
|
||||
updateFullScreenItemText();
|
||||
fullScreenItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0));
|
||||
fullScreenItem.addActionListener(getFullScreenAction());
|
||||
|
||||
@@ -201,8 +201,7 @@ public abstract class ACEditorBase<TItem extends InventoryItem, TModel extends D
|
||||
int qty = itemEntry.getValue();
|
||||
|
||||
int max;
|
||||
if (deck == null || card == null || card.getRules().getType().isBasic() ||
|
||||
limit == CardLimit.None || DeckFormat.getLimitExceptions().contains(card.getName())) {
|
||||
if (deck == null || card == null || limit == CardLimit.None || DeckFormat.canHaveAnyNumberOf(card)) {
|
||||
max = Integer.MAX_VALUE;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.awt.Dialog.ModalityType;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.SwingUtilities;
|
||||
@@ -22,6 +23,7 @@ import forge.screens.deckeditor.CDeckEditorUI;
|
||||
import forge.screens.deckeditor.DeckImport;
|
||||
import forge.screens.deckeditor.SEditorIO;
|
||||
import forge.screens.deckeditor.views.VCurrentDeck;
|
||||
import forge.toolbox.FOptionPane;
|
||||
|
||||
/**
|
||||
* Controls the "current deck" panel in the deck editor UI.
|
||||
@@ -244,8 +246,17 @@ public enum CCurrentDeck implements ICDoc {
|
||||
if (fileChooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
final File file = fileChooser.getSelectedFile();
|
||||
final String check = file.getAbsolutePath();
|
||||
|
||||
previousDirectory = file.getParentFile();
|
||||
|
||||
if (!previousDirectory.exists()) {
|
||||
FOptionPane.showErrorDialog("Cannot save deck to " + check);
|
||||
return null;
|
||||
}
|
||||
|
||||
if(isFileNameInvalid(file)) {
|
||||
FOptionPane.showErrorDialog("Cannot save deck to " + check + "\nDeck name may not include any of the characters / \\ : * ? \" < > |");
|
||||
return null;
|
||||
}
|
||||
|
||||
return check.endsWith(".dck") ? file : new File(check + ".dck");
|
||||
}
|
||||
@@ -261,14 +272,29 @@ public enum CCurrentDeck implements ICDoc {
|
||||
if (save.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) {
|
||||
final File file = save.getSelectedFile();
|
||||
final String check = file.getAbsolutePath();
|
||||
|
||||
previousDirectory = file.getParentFile();
|
||||
|
||||
if (!previousDirectory.exists()) {
|
||||
FOptionPane.showErrorDialog("Cannot save proxies to " + check);
|
||||
return null;
|
||||
}
|
||||
|
||||
if(isFileNameInvalid(file)) {
|
||||
FOptionPane.showErrorDialog("Cannot save proxies to " + check + "\nFile name may not include any of the characters / \\ : * ? \" < > |");
|
||||
return null;
|
||||
}
|
||||
|
||||
return check.endsWith(".html") ? file : new File(check + ".html");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Checks if the file name includes any of the invalid characters / \ : * ? " < > : */
|
||||
private static boolean isFileNameInvalid(File file) {
|
||||
final Pattern pattern = Pattern.compile("[/\\\\:*?\\\"<>|]");
|
||||
return pattern.matcher(file.getName()).find();
|
||||
}
|
||||
|
||||
/** The Constant HTML_FILTER. */
|
||||
public static final FileFilter HTML_FILTER = new FileFilter() {
|
||||
@Override
|
||||
@@ -281,4 +307,5 @@ public enum CCurrentDeck implements ICDoc {
|
||||
return "Proxy File .html";
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -18,8 +18,14 @@
|
||||
package forge.screens.deckeditor.controllers;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.common.base.Supplier;
|
||||
import forge.UiCommand;
|
||||
import forge.card.CardRules;
|
||||
import forge.card.CardRulesPredicates;
|
||||
import forge.card.ColorSet;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckSection;
|
||||
@@ -35,6 +41,7 @@ import forge.itemmanager.views.ItemTableColumn;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.quest.QuestController;
|
||||
import forge.quest.data.DeckConstructionRules;
|
||||
import forge.screens.deckeditor.AddBasicLandsDialog;
|
||||
import forge.screens.deckeditor.SEditorIO;
|
||||
import forge.screens.deckeditor.views.VAllDecks;
|
||||
@@ -103,6 +110,14 @@ public final class CEditorQuest extends CDeckEditor<Deck> {
|
||||
allSections.add(DeckSection.Main);
|
||||
allSections.add(DeckSection.Sideboard);
|
||||
|
||||
//Add sub-format specific sections
|
||||
switch(FModel.getQuest().getDeckConstructionRules()){
|
||||
case Default: break;
|
||||
case Commander:
|
||||
allSections.add(DeckSection.Commander);
|
||||
break;
|
||||
}
|
||||
|
||||
this.questData = questData0;
|
||||
|
||||
final CardManager catalogManager = new CardManager(cDetailPicture, false, true);
|
||||
@@ -158,6 +173,10 @@ public final class CEditorQuest extends CDeckEditor<Deck> {
|
||||
@Override
|
||||
protected CardLimit getCardLimit() {
|
||||
if (FModel.getPreferences().getPrefBoolean(FPref.ENFORCE_DECK_LEGALITY)) {
|
||||
//If this is a commander quest, only allow single copies of cards
|
||||
if(FModel.getQuest().getDeckConstructionRules() == DeckConstructionRules.Commander){
|
||||
return CardLimit.Singleton;
|
||||
}
|
||||
return CardLimit.Default;
|
||||
}
|
||||
return CardLimit.None; //if not enforcing deck legality, don't enforce default limit
|
||||
@@ -245,16 +264,103 @@ public final class CEditorQuest extends CDeckEditor<Deck> {
|
||||
public void resetTables() {
|
||||
this.sectionMode = DeckSection.Main;
|
||||
|
||||
final Deck deck = this.controller.getModel();
|
||||
|
||||
final CardPool cardpool = getInitialCatalog();
|
||||
// remove bottom cards that are in the deck from the card pool
|
||||
cardpool.removeAll(deck.getMain());
|
||||
// remove sideboard cards from the catalog
|
||||
cardpool.removeAll(deck.getOrCreate(DeckSection.Sideboard));
|
||||
// show cards, makes this user friendly
|
||||
this.getCatalogManager().setPool(cardpool);
|
||||
this.getDeckManager().setPool(deck.getMain());
|
||||
this.getCatalogManager().setPool(getRemainingCardPool());
|
||||
this.getDeckManager().setPool(getDeck().getMain());
|
||||
}
|
||||
|
||||
/***
|
||||
* Provides the pool of cards the player has available to add to his or her deck. Also manages showing available cards
|
||||
* to choose from for special deck construction rules, e.g.: Commander.
|
||||
* @return CardPool of cards available to add to the player's deck.
|
||||
*/
|
||||
private CardPool getRemainingCardPool(){
|
||||
final CardPool cardpool = getInitialCatalog();
|
||||
|
||||
// remove bottom cards that are in the deck from the card pool
|
||||
cardpool.removeAll(getDeck().getMain());
|
||||
|
||||
// remove sideboard cards from the catalog
|
||||
cardpool.removeAll(getDeck().getOrCreate(DeckSection.Sideboard));
|
||||
|
||||
switch(FModel.getQuest().getDeckConstructionRules()){
|
||||
case Default: break;
|
||||
case Commander:
|
||||
//remove this deck's currently selected commander(s) from the catalog
|
||||
cardpool.removeAll(getDeck().getOrCreate(DeckSection.Commander));
|
||||
|
||||
//TODO: Only thin if deck conformance is being applied
|
||||
if(getDeck().getOrCreate(DeckSection.Commander).toFlatList().size() > 0) {
|
||||
Predicate<PaperCard> identityPredicate = new MatchCommanderColorIdentity(getDeckColorIdentity());
|
||||
CardPool filteredPool = cardpool.getFilteredPool(identityPredicate);
|
||||
|
||||
return filteredPool;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return cardpool;
|
||||
}
|
||||
|
||||
/**
|
||||
* Predicate that filters out based on a color identity provided upon instantiation. Used to filter the card
|
||||
* list when a commander is chosen so the user can more easily see what cards are available for his or her deck
|
||||
* and avoid making additions that are not legal.
|
||||
*/
|
||||
public static class MatchCommanderColorIdentity implements Predicate<PaperCard> {
|
||||
private final ColorSet allowedColor;
|
||||
|
||||
public MatchCommanderColorIdentity(ColorSet color) {
|
||||
allowedColor = color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean apply(PaperCard subject) {
|
||||
CardRules cr = subject.getRules();
|
||||
ManaCost mc = cr.getManaCost();
|
||||
return allowedColor.containsAllColorsFrom(cr.getColorIdentity().getColor());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the color identity of the loaded deck based on the commanders.
|
||||
* @return A ColorSet containing the color identity of the currently loaded deck.
|
||||
*/
|
||||
public ColorSet getDeckColorIdentity(){
|
||||
|
||||
List<PaperCard> commanders = getDeck().getOrCreate(DeckSection.Commander).toFlatList();
|
||||
List<String> colors = new ArrayList<>();
|
||||
|
||||
//Return early if there are no current commanders
|
||||
if(commanders.size() == 0){
|
||||
colors.add("c");
|
||||
return ColorSet.fromNames(colors);
|
||||
}
|
||||
|
||||
//For each commander,add each color of its color identity if not already added
|
||||
for(PaperCard pc : commanders){
|
||||
if(!colors.contains("w") && pc.getRules().getColorIdentity().hasWhite()) colors.add("w");
|
||||
if(!colors.contains("u") && pc.getRules().getColorIdentity().hasBlue()) colors.add("u");
|
||||
if(!colors.contains("b") && pc.getRules().getColorIdentity().hasBlack()) colors.add("b");
|
||||
if(!colors.contains("r") && pc.getRules().getColorIdentity().hasRed()) colors.add("r");
|
||||
if(!colors.contains("g") && pc.getRules().getColorIdentity().hasGreen()) colors.add("g");
|
||||
}
|
||||
|
||||
colors.add("c");
|
||||
|
||||
return ColorSet.fromNames(colors);
|
||||
}
|
||||
|
||||
/*
|
||||
Used to make the code more readable in game terms.
|
||||
*/
|
||||
private Deck getDeck(){
|
||||
return this.controller.getModel();
|
||||
}
|
||||
|
||||
private ItemPool<PaperCard> getCommanderCardPool(){
|
||||
Predicate<PaperCard> commanderPredicate = Predicates.compose(CardRulesPredicates.Presets.CAN_BE_COMMANDER, PaperCard.FN_GET_RULES);
|
||||
return getRemainingCardPool().getFilteredPool(commanderPredicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -280,14 +386,33 @@ public final class CEditorQuest extends CDeckEditor<Deck> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch between the main deck and the sideboard editor.
|
||||
* Switch between the main deck and the sideboard/Command Zone editor.
|
||||
*/
|
||||
public void setEditorMode(DeckSection sectionMode) {
|
||||
if (sectionMode == DeckSection.Sideboard) {
|
||||
this.getDeckManager().setPool(this.controller.getModel().getOrCreate(DeckSection.Sideboard));
|
||||
}
|
||||
else {
|
||||
this.getDeckManager().setPool(this.controller.getModel().getMain());
|
||||
//Fixes null pointer error on switching tabs while quest deck editor is open. TODO: Find source of bug possibly?
|
||||
if(sectionMode == null) sectionMode = DeckSection.Main;
|
||||
|
||||
final Map<ColumnDef, ItemTableColumn> colOverridesCatalog = new HashMap<ColumnDef, ItemTableColumn>();
|
||||
ItemTableColumn.addColOverride(ItemManagerConfig.QUEST_EDITOR_POOL, colOverridesCatalog, ColumnDef.NEW, this.questData.getCards().getFnNewCompare(), this.questData.getCards().getFnNewGet());
|
||||
|
||||
//Based on which section the editor is in, display the remaining card pool (or applicable card pool if in
|
||||
//Commander) and the current section's cards
|
||||
switch(sectionMode){
|
||||
case Main :
|
||||
this.getCatalogManager().setup(ItemManagerConfig.QUEST_EDITOR_POOL, colOverridesCatalog);
|
||||
this.getCatalogManager().setPool(getRemainingCardPool());
|
||||
this.getDeckManager().setPool(this.controller.getModel().getMain());
|
||||
break;
|
||||
case Sideboard :
|
||||
this.getCatalogManager().setup(ItemManagerConfig.QUEST_EDITOR_POOL, colOverridesCatalog);
|
||||
this.getCatalogManager().setPool(getRemainingCardPool());
|
||||
this.getDeckManager().setPool(getDeck().getOrCreate(DeckSection.Sideboard));
|
||||
break;
|
||||
case Commander :
|
||||
this.getCatalogManager().setup(ItemManagerConfig.COMMANDER_POOL);
|
||||
this.getCatalogManager().setPool(getCommanderCardPool());
|
||||
this.getDeckManager().setPool(getDeck().getOrCreate(DeckSection.Commander));
|
||||
break;
|
||||
}
|
||||
|
||||
this.sectionMode = sectionMode;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package forge.screens.home;
|
||||
|
||||
/**
|
||||
import forge.util.Localizer;
|
||||
/**
|
||||
* Submenus each belong to a menu group, which
|
||||
* is used for several functions, such as expanding
|
||||
* and collapsing in the menu.
|
||||
@@ -8,12 +8,12 @@ package forge.screens.home;
|
||||
* <br><br><i>(E at beginning of class name denotes an enum.)</i>
|
||||
*/
|
||||
public enum EMenuGroup {
|
||||
SANCTIONED ("Sanctioned Formats"),
|
||||
ONLINE ("Online Multiplayer"),
|
||||
QUEST ("Quest Mode"),
|
||||
PUZZLE ("Puzzle Mode"),
|
||||
GAUNTLET ("Gauntlets"),
|
||||
SETTINGS ("Game Settings");
|
||||
SANCTIONED ("lblSanctionedFormats"),
|
||||
ONLINE ("lblOnlineMultiplayer"),
|
||||
QUEST ("lblQuestMode"),
|
||||
PUZZLE ("lblPuzzleMode"),
|
||||
GAUNTLET ("lblGauntlets"),
|
||||
SETTINGS ("lblGameSettings");
|
||||
|
||||
private final String strTitle;
|
||||
|
||||
@@ -21,5 +21,9 @@ public enum EMenuGroup {
|
||||
private EMenuGroup(final String s0) { strTitle = s0; }
|
||||
|
||||
/** @return {@link java.lang.String} */
|
||||
public String getTitle() { return this.strTitle; }
|
||||
public String getTitle() {
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
String t = localizer.getMessage(this.strTitle);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,9 +51,11 @@ import forge.toolbox.FTextField;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.NameGenerator;
|
||||
import forge.util.gui.SOptionPane;
|
||||
import forge.util.Localizer;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class PlayerPanel extends FPanel {
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
private final static ForgePreferences prefs = FModel.getPreferences();
|
||||
private static final SkinColor unfocusedPlayerOverlay = FSkin.getColor(FSkin.Colors.CLR_OVERLAY).alphaColor(120);
|
||||
|
||||
@@ -77,23 +79,23 @@ public class PlayerPanel extends FPanel {
|
||||
private final FComboBoxWrapper<Object> aeTeamComboBox = new FComboBoxWrapper<Object>();
|
||||
|
||||
private final FLabel closeBtn;
|
||||
private final FLabel deckBtn = new FLabel.ButtonBuilder().text("Select a deck").build();
|
||||
private final FLabel deckBtn = new FLabel.ButtonBuilder().text(localizer.getMessage("lblSelectaDeck")).build();
|
||||
private final FLabel deckLabel;
|
||||
|
||||
private final String variantBtnConstraints = "height 30px, hidemode 3";
|
||||
|
||||
private final FLabel scmDeckSelectorBtn = new FLabel.ButtonBuilder().text("Select a scheme deck").build();
|
||||
private final FLabel scmDeckEditor = new FLabel.ButtonBuilder().text("Scheme Deck Editor").build();
|
||||
private final FLabel scmDeckSelectorBtn = new FLabel.ButtonBuilder().text(localizer.getMessage("lblSelectaSchemeDeck")).build();
|
||||
private final FLabel scmDeckEditor = new FLabel.ButtonBuilder().text(localizer.getMessage("lblSchemeDeckEditor")).build();
|
||||
private final FLabel scmLabel;
|
||||
|
||||
private final FLabel cmdDeckSelectorBtn = new FLabel.ButtonBuilder().text("Select a Commander deck").build();
|
||||
private final FLabel cmdDeckSelectorBtn = new FLabel.ButtonBuilder().text(localizer.getMessage("lblSelectaCommanderDeck")).build();
|
||||
private final FLabel cmdLabel;
|
||||
|
||||
private final FLabel pchDeckSelectorBtn = new FLabel.ButtonBuilder().text("Select a planar deck").build();
|
||||
private final FLabel pchDeckEditor = new FLabel.ButtonBuilder().text("Planar Deck Editor").build();
|
||||
private final FLabel pchDeckSelectorBtn = new FLabel.ButtonBuilder().text(localizer.getMessage("lblSelectaPlanarDeck")).build();
|
||||
private final FLabel pchDeckEditor = new FLabel.ButtonBuilder().text(localizer.getMessage("lblPlanarDeckEditor")).build();
|
||||
private final FLabel pchLabel;
|
||||
|
||||
private final FLabel vgdSelectorBtn = new FLabel.ButtonBuilder().text("Select a Vanguard avatar").build();
|
||||
private final FLabel vgdSelectorBtn = new FLabel.ButtonBuilder().text(localizer.getMessage("lblSelectaVanguardAvatar")).build();
|
||||
private final FLabel vgdLabel;
|
||||
|
||||
private FCheckBox chkDevMode;
|
||||
@@ -110,11 +112,11 @@ public class PlayerPanel extends FPanel {
|
||||
this.mayControl = mayControl;
|
||||
this.allowNetworking = allowNetworking;
|
||||
|
||||
this.deckLabel = lobby.newLabel("Deck:");
|
||||
this.scmLabel = lobby.newLabel("Scheme deck:");
|
||||
this.cmdLabel = lobby.newLabel("Commander deck:");
|
||||
this.pchLabel = lobby.newLabel("Planar deck:");
|
||||
this.vgdLabel = lobby.newLabel("Vanguard:");
|
||||
this.deckLabel = lobby.newLabel(localizer.getMessage("lblDeck") + ":");
|
||||
this.scmLabel = lobby.newLabel(localizer.getMessage("lblSchemeDeck") + ":");
|
||||
this.cmdLabel = lobby.newLabel(localizer.getMessage("lblCommanderDeck") + ":");
|
||||
this.pchLabel = lobby.newLabel(localizer.getMessage("lblPlanarDeck") + ":");
|
||||
this.vgdLabel = lobby.newLabel(localizer.getMessage("lblVanguard") + ":");
|
||||
|
||||
setLayout(new MigLayout("insets 10px, gap 5px"));
|
||||
|
||||
@@ -449,8 +451,8 @@ public class PlayerPanel extends FPanel {
|
||||
}
|
||||
|
||||
private void populateTeamsComboBoxes() {
|
||||
aeTeamComboBox.addItem("Archenemy");
|
||||
aeTeamComboBox.addItem("Heroes");
|
||||
aeTeamComboBox.addItem(localizer.getMessage("lblArchenemy"));
|
||||
aeTeamComboBox.addItem(localizer.getMessage("lblHeroes"));
|
||||
|
||||
for (int i = 1; i <= VLobby.MAX_PLAYERS; i++) {
|
||||
teamComboBox.addItem(i);
|
||||
@@ -553,12 +555,12 @@ public class PlayerPanel extends FPanel {
|
||||
* @param index
|
||||
*/
|
||||
private void createPlayerTypeOptions() {
|
||||
radioHuman = new FRadioButton("Human");
|
||||
radioAi = new FRadioButton("AI");
|
||||
radioOpen = new FRadioButton("Open");
|
||||
radioHuman = new FRadioButton(localizer.getMessage("lblHuman"));
|
||||
radioAi = new FRadioButton(localizer.getMessage("lblAI"));
|
||||
radioOpen = new FRadioButton(localizer.getMessage("lblOpen"));
|
||||
|
||||
final JPopupMenu menu = new JPopupMenu();
|
||||
radioAiUseSimulation = new JCheckBoxMenuItem("Use Simulation");
|
||||
radioAiUseSimulation = new JCheckBoxMenuItem(localizer.getMessage("lblUseSimulation"));
|
||||
menu.add(radioAiUseSimulation);
|
||||
radioAiUseSimulation.addActionListener(new ActionListener() {
|
||||
@Override public final void actionPerformed(final ActionEvent e) {
|
||||
@@ -577,7 +579,7 @@ public class PlayerPanel extends FPanel {
|
||||
}
|
||||
|
||||
private void createReadyButton() {
|
||||
chkReady = new FCheckBox("Ready");
|
||||
chkReady = new FCheckBox(localizer.getMessage("lblReady"));
|
||||
chkReady.addActionListener(new ActionListener() {
|
||||
@Override public final void actionPerformed(final ActionEvent e) {
|
||||
lobby.setReady(index, chkReady.isSelected());
|
||||
@@ -586,7 +588,7 @@ public class PlayerPanel extends FPanel {
|
||||
}
|
||||
|
||||
private void createDevModeButton() {
|
||||
chkDevMode = new FCheckBox("Dev Mode");
|
||||
chkDevMode = new FCheckBox(localizer.getMessage("cbDevMode"));
|
||||
|
||||
chkDevMode.addActionListener(new ActionListener() {
|
||||
@Override public final void actionPerformed(final ActionEvent e) {
|
||||
@@ -621,7 +623,7 @@ public class PlayerPanel extends FPanel {
|
||||
* @return
|
||||
*/
|
||||
private FLabel createNameRandomizer() {
|
||||
final FLabel newNameBtn = new FLabel.Builder().tooltip("Get a new random name").iconInBackground(false)
|
||||
final FLabel newNameBtn = new FLabel.Builder().tooltip(localizer.getMessage("lblGetaNewRandomName")).iconInBackground(false)
|
||||
.icon(FSkin.getIcon(FSkinProp.ICO_EDIT)).hoverable(true).opaque(false)
|
||||
.unhoveredAlpha(0.9f).build();
|
||||
newNameBtn.setCommand(new UiCommand() {
|
||||
@@ -654,7 +656,7 @@ public class PlayerPanel extends FPanel {
|
||||
if (index == 0) {
|
||||
name = FModel.getPreferences().getPref(FPref.PLAYER_NAME);
|
||||
if (name.isEmpty()) {
|
||||
name = "Human";
|
||||
name = localizer.getMessage("lblHuman");
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -669,11 +671,11 @@ public class PlayerPanel extends FPanel {
|
||||
}
|
||||
|
||||
private FLabel createCloseButton() {
|
||||
final FLabel closeBtn = new FLabel.Builder().tooltip("Remove").iconInBackground(false)
|
||||
final FLabel closeBtn = new FLabel.Builder().tooltip(localizer.getMessage("lblRemove")).iconInBackground(false)
|
||||
.icon(FSkin.getIcon(FSkinProp.ICO_CLOSE)).hoverable(true).build();
|
||||
closeBtn.setCommand(new Runnable() {
|
||||
@Override public final void run() {
|
||||
if (type == LobbySlotType.REMOTE && !SOptionPane.showConfirmDialog(String.format("Really kick %s?", playerName), "Kick", false)) {
|
||||
if (type == LobbySlotType.REMOTE && !SOptionPane.showConfirmDialog(String.format(localizer.getMessage("lblReallyKick"), playerName), localizer.getMessage("lblKick"), false)) {
|
||||
return;
|
||||
}
|
||||
lobby.removePlayer(index);
|
||||
@@ -691,7 +693,7 @@ public class PlayerPanel extends FPanel {
|
||||
setRandomAvatar(false);
|
||||
}
|
||||
|
||||
avatarLabel.setToolTipText("L-click: Select avatar. R-click: Randomize avatar.");
|
||||
avatarLabel.setToolTipText(localizer.getMessage("ttlblAvatar"));
|
||||
avatarLabel.addFocusListener(avatarFocusListener);
|
||||
avatarLabel.addMouseListener(avatarMouseListener);
|
||||
}
|
||||
|
||||
@@ -1,39 +1,11 @@
|
||||
package forge.screens.home;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Vector;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import forge.UiCommand;
|
||||
import forge.ai.AIOption;
|
||||
import forge.deck.CardPool;
|
||||
import forge.deck.Deck;
|
||||
import forge.deck.DeckProxy;
|
||||
import forge.deck.DeckSection;
|
||||
import forge.deck.DeckType;
|
||||
import forge.deck.DeckgenUtil;
|
||||
import forge.deck.RandomDeckGenerator;
|
||||
import forge.deck.*;
|
||||
import forge.deckchooser.FDeckChooser;
|
||||
import forge.game.GameType;
|
||||
import forge.game.card.CardView;
|
||||
@@ -48,20 +20,24 @@ import forge.model.FModel;
|
||||
import forge.net.event.UpdateLobbyPlayerEvent;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.toolbox.FCheckBox;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FList;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.toolbox.FPanel;
|
||||
import forge.toolbox.FScrollPane;
|
||||
import forge.toolbox.FScrollPanel;
|
||||
import forge.toolbox.FSkin;
|
||||
import forge.toolbox.*;
|
||||
import forge.toolbox.FSkin.SkinImage;
|
||||
import forge.toolbox.FTextField;
|
||||
import forge.util.Aggregates;
|
||||
import forge.util.Lang;
|
||||
import forge.util.NameGenerator;
|
||||
import forge.util.gui.SOptionPane;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.ListSelectionListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ItemEvent;
|
||||
import java.awt.event.ItemListener;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Lobby view. View of a number of players at the deck selection stage.
|
||||
@@ -1009,17 +985,17 @@ public class VLobby implements ILobbyView {
|
||||
return vgdAllAvatars;
|
||||
}
|
||||
|
||||
/** Return the Vanguard avatars not flagged RemAIDeck. */
|
||||
/** Return the Vanguard avatars not flagged RemoveDeck:All. */
|
||||
public List<PaperCard> getAllAiAvatars() {
|
||||
return vgdAllAiAvatars;
|
||||
}
|
||||
|
||||
/** Return the Vanguard avatars not flagged RemRandomDeck. */
|
||||
/** Return the Vanguard avatars not flagged RemoveDeck:Random. */
|
||||
public List<PaperCard> getNonRandomHumanAvatars() {
|
||||
return nonRandomHumanAvatars;
|
||||
}
|
||||
|
||||
/** Return the Vanguard avatars not flagged RemAIDeck or RemRandomDeck. */
|
||||
/** Return the Vanguard avatars not flagged RemoveDeck:All or RemoveDeck:Random. */
|
||||
public List<PaperCard> getNonRandomAiAvatars() {
|
||||
return nonRandomAiAvatars;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import forge.model.FModel;
|
||||
import forge.properties.ForgeConstants;
|
||||
import forge.quest.*;
|
||||
import forge.quest.StartingPoolPreferences.PoolType;
|
||||
import forge.quest.data.DeckConstructionRules;
|
||||
import forge.quest.data.GameFormatQuest;
|
||||
import forge.quest.data.QuestData;
|
||||
import forge.quest.data.QuestPreferences.QPref;
|
||||
@@ -340,9 +341,16 @@ public enum CSubmenuQuestData implements ICDoc {
|
||||
break;
|
||||
}
|
||||
|
||||
//Apply the appropriate deck construction rules for this quest
|
||||
DeckConstructionRules dcr = DeckConstructionRules.Default;
|
||||
|
||||
if(VSubmenuQuestData.SINGLETON_INSTANCE.isCommander()){
|
||||
dcr = DeckConstructionRules.Commander;
|
||||
}
|
||||
|
||||
final QuestController qc = FModel.getQuest();
|
||||
|
||||
qc.newGame(questName, difficulty, mode, fmtPrizes, view.isUnlockSetsAllowed(), dckStartPool, fmtStartPool, view.getStartingWorldName(), userPrefs);
|
||||
qc.newGame(questName, difficulty, mode, fmtPrizes, view.isUnlockSetsAllowed(), dckStartPool, fmtStartPool, view.getStartingWorldName(), userPrefs, dcr);
|
||||
FModel.getQuest().save();
|
||||
|
||||
// Save in preferences.
|
||||
|
||||
@@ -62,6 +62,7 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
|
||||
private final FRadioButton radHard = new FRadioButton("Hard");
|
||||
private final FRadioButton radExpert = new FRadioButton("Expert");
|
||||
private final FCheckBox boxFantasy = new FCheckBox("Fantasy Mode");
|
||||
private final FCheckBox boxCommander = new FCheckBox("Commander Subformat");
|
||||
|
||||
private final FLabel lblStartingWorld = new FLabel.Builder().text("Starting world:").build();
|
||||
private final FComboBoxWrapper<QuestWorld> cbxStartingWorld = new FComboBoxWrapper<>();
|
||||
@@ -274,9 +275,25 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
|
||||
}
|
||||
});
|
||||
|
||||
// Fantasy box enabled by Default
|
||||
// Fantasy box selected by Default
|
||||
boxFantasy.setSelected(true);
|
||||
boxFantasy.setEnabled(true);
|
||||
|
||||
// Commander box unselected by Default
|
||||
boxCommander.setSelected(false);
|
||||
boxCommander.setEnabled(true);
|
||||
|
||||
boxCommander.addActionListener(
|
||||
new ActionListener(){
|
||||
public void actionPerformed(ActionEvent e){
|
||||
if(!isCommander()) return; //do nothing if unselecting Commander Subformat
|
||||
//Otherwise, set the starting world to Random Commander
|
||||
cbxStartingWorld.setSelectedItem(FModel.getWorlds().get("Random Commander"));
|
||||
}
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
boxCompleteSet.setEnabled(true);
|
||||
boxAllowDuplicates.setEnabled(true);
|
||||
|
||||
@@ -286,6 +303,7 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
|
||||
final JPanel pnlDifficultyMode = new JPanel(new MigLayout("insets 0, gap 1%, flowy"));
|
||||
pnlDifficultyMode.add(difficultyPanel, "gapright 4%");
|
||||
pnlDifficultyMode.add(boxFantasy, "h 25px!, gapbottom 15, gapright 4%");
|
||||
pnlDifficultyMode.add(boxCommander, "h 25px!, gapbottom 15, gapright 4%");
|
||||
pnlDifficultyMode.add(lblStartingWorld, "h 25px!, hidemode 3");
|
||||
cbxStartingWorld.addTo(pnlDifficultyMode, "h 27px!, w 40%, pushx, gapbottom 7");
|
||||
pnlDifficultyMode.setOpaque(false);
|
||||
@@ -487,6 +505,14 @@ public enum VSubmenuQuestData implements IVSubmenu<CSubmenuQuestData> {
|
||||
return boxFantasy.isSelected();
|
||||
}
|
||||
|
||||
/**
|
||||
* Auth. Imakuni
|
||||
* @return True if the "Commander Subformat" check box is selected.
|
||||
*/
|
||||
public boolean isCommander() {
|
||||
return boxCommander.isSelected();
|
||||
}
|
||||
|
||||
public boolean startWithCompleteSet() {
|
||||
return boxCompleteSet.isSelected();
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import forge.screens.home.EMenuGroup;
|
||||
import forge.screens.home.IVSubmenu;
|
||||
import forge.screens.home.VHomeUI;
|
||||
import forge.screens.home.VLobby;
|
||||
import forge.util.Localizer;
|
||||
|
||||
/**
|
||||
* Assembles Swing components of constructed submenu singleton.
|
||||
@@ -25,12 +26,12 @@ import forge.screens.home.VLobby;
|
||||
*
|
||||
*/
|
||||
public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
||||
SINGLETON_INSTANCE;
|
||||
|
||||
SINGLETON_INSTANCE;
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
// Fields used with interface IVDoc
|
||||
private DragCell parentCell;
|
||||
private final DragTab tab = new DragTab("Constructed Mode");
|
||||
|
||||
private final DragTab tab = new DragTab(localizer.getMessage("lblConstructedMode"));
|
||||
private final GameLobby lobby = new LocalLobby();
|
||||
private final VLobby vLobby = new VLobby(lobby);
|
||||
private VSubmenuConstructed() {
|
||||
@@ -105,7 +106,8 @@ public enum VSubmenuConstructed implements IVSubmenu<CSubmenuConstructed> {
|
||||
*/
|
||||
@Override
|
||||
public String getMenuTitle() {
|
||||
return "Constructed";
|
||||
|
||||
return localizer.getMessage("lblConstructed");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -18,6 +18,7 @@ import forge.toolbox.FComboBox;
|
||||
import forge.toolbox.FComboBoxPanel;
|
||||
import forge.toolbox.FLabel;
|
||||
import forge.toolbox.FOptionPane;
|
||||
import forge.util.Localizer;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
|
||||
@@ -38,6 +39,8 @@ import java.util.List;
|
||||
public enum CSubmenuPreferences implements ICDoc {
|
||||
/** */
|
||||
SINGLETON_INSTANCE;
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
|
||||
|
||||
private VSubmenuPreferences view;
|
||||
private ForgePreferences prefs;
|
||||
@@ -66,7 +69,7 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
if (updating) { return; }
|
||||
// prevent changing DEV_MODE while network game running
|
||||
if (FServerManager.getInstance().isMatchActive()) {
|
||||
System.out.println("Can't change DEV_MODE while a network match is in progress!");
|
||||
System.out.println(localizer.getMessage("CantChangeDevModeWhileNetworkMath"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -192,7 +195,7 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
public void run() {
|
||||
prefs.setPref(FPref.DISABLE_DISPLAY_JAVA_8_UPDATE_WARNING, false);
|
||||
prefs.save();
|
||||
FOptionPane.showMessageDialog("Compatibility warnings re-enabled!");
|
||||
FOptionPane.showMessageDialog(localizer.getMessage("CompatibilityWarningsReEnabled"));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -242,10 +245,8 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
}
|
||||
|
||||
private void resetForgeSettingsToDefault() {
|
||||
final String userPrompt =
|
||||
"This will reset all preferences to their defaults and restart Forge.\n\n" +
|
||||
"Reset and restart Forge?";
|
||||
if (FOptionPane.showConfirmDialog(userPrompt, "Reset Settings")) {
|
||||
final String userPrompt =localizer.getMessage("AresetForgeSettingsToDefault");
|
||||
if (FOptionPane.showConfirmDialog(userPrompt, localizer.getMessage("TresetForgeSettingsToDefault"))) {
|
||||
final ForgePreferences prefs = FModel.getPreferences();
|
||||
prefs.reset();
|
||||
prefs.save();
|
||||
@@ -255,38 +256,28 @@ public enum CSubmenuPreferences implements ICDoc {
|
||||
}
|
||||
|
||||
private void resetDeckEditorLayout() {
|
||||
final String userPrompt =
|
||||
"This will reset the Deck Editor screen layout.\n" +
|
||||
"All tabbed views will be restored to their default positions.\n\n" +
|
||||
"Reset layout?";
|
||||
if (FOptionPane.showConfirmDialog(userPrompt, "Reset Deck Editor Layout")) {
|
||||
final String userPrompt =localizer.getMessage("AresetDeckEditorLayout");
|
||||
if (FOptionPane.showConfirmDialog(userPrompt, localizer.getMessage("TresetDeckEditorLayout"))) {
|
||||
if (FScreen.DECK_EDITOR_CONSTRUCTED.deleteLayoutFile()) {
|
||||
FOptionPane.showMessageDialog("Deck Editor layout has been reset.");
|
||||
FOptionPane.showMessageDialog(localizer.getMessage("OKresetDeckEditorLayout"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetWorkshopLayout() {
|
||||
final String userPrompt =
|
||||
"This will reset the Workshop screen layout.\n" +
|
||||
"All tabbed views will be restored to their default positions.\n\n" +
|
||||
"Reset layout?";
|
||||
if (FOptionPane.showConfirmDialog(userPrompt, "Reset Workshop Layout")) {
|
||||
final String userPrompt =localizer.getMessage("AresetWorkshopLayout");
|
||||
if (FOptionPane.showConfirmDialog(userPrompt, localizer.getMessage("TresetWorkshopLayout"))) {
|
||||
if (FScreen.WORKSHOP_SCREEN.deleteLayoutFile()) {
|
||||
FOptionPane.showMessageDialog("Workshop layout has been reset.");
|
||||
FOptionPane.showMessageDialog(localizer.getMessage("OKresetWorkshopLayout"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void resetMatchScreenLayout() {
|
||||
final String userPrompt =
|
||||
"This will reset the layout of the Match screen.\n" +
|
||||
"If you want to save the current layout first, please use " +
|
||||
"the Dock tab -> Save Layout option in the Match screen.\n\n" +
|
||||
"Reset layout?";
|
||||
if (FOptionPane.showConfirmDialog(userPrompt, "Reset Match Screen Layout")) {
|
||||
final String userPrompt =localizer.getMessage("AresetMatchScreenLayout");
|
||||
if (FOptionPane.showConfirmDialog(userPrompt, localizer.getMessage("TresetMatchScreenLayout"))) {
|
||||
if (FScreen.deleteMatchLayoutFile()) {
|
||||
FOptionPane.showMessageDialog("Match Screen layout has been reset.");
|
||||
FOptionPane.showMessageDialog(localizer.getMessage("OKresetMatchScreenLayout"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import forge.toolbox.FSkin.SkinColor;
|
||||
import forge.toolbox.FSkin.SkinFont;
|
||||
import forge.toolbox.FSkin.SkinImage;
|
||||
import forge.toolbox.special.CardZoomer;
|
||||
import forge.util.Localizer;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -54,12 +55,13 @@ public enum VSubmenuAchievements implements IVSubmenu<CSubmenuAchievements> {
|
||||
private static final SkinColor NOT_EARNED_COLOR = TEXT_COLOR.alphaColor(128);
|
||||
private static final SkinColor TEXTURE_OVERLAY_COLOR = FSkin.getColor(Colors.CLR_THEME);
|
||||
private static final SkinColor BORDER_COLOR = FSkin.getColor(Colors.CLR_BORDERS);
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
|
||||
// Fields used with interface IVDoc
|
||||
private DragCell parentCell;
|
||||
private final DragTab tab = new DragTab("Achievements");
|
||||
private final DragTab tab = new DragTab(localizer.getMessage("Achievements"));
|
||||
private final FLabel lblTitle = new FLabel.Builder()
|
||||
.text("Achievements").fontAlign(SwingConstants.CENTER)
|
||||
.text(localizer.getMessage("Achievements")).fontAlign(SwingConstants.CENTER)
|
||||
.opaque(true).fontSize(16).build();
|
||||
private final FComboBox<AchievementCollection> cbCollections = new FComboBox<AchievementCollection>();
|
||||
private final TrophyCase trophyCase = new TrophyCase();
|
||||
@@ -167,7 +169,7 @@ public enum VSubmenuAchievements implements IVSubmenu<CSubmenuAchievements> {
|
||||
*/
|
||||
@Override
|
||||
public String getMenuTitle() {
|
||||
return "Achievements";
|
||||
return localizer.getMessage("Achievements");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -12,6 +12,7 @@ import forge.screens.home.IVSubmenu;
|
||||
import forge.screens.home.VHomeUI;
|
||||
import forge.toolbox.*;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.RuntimeVersion;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
@@ -29,6 +30,8 @@ import java.awt.event.ActionListener;
|
||||
public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
||||
/** */
|
||||
SINGLETON_INSTANCE;
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
|
||||
|
||||
// Fields used with interface IVDoc
|
||||
private DragCell parentCell;
|
||||
@@ -38,15 +41,15 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
||||
private final JPanel pnlContent = new JPanel(new MigLayout("insets 0, gap 0, wrap, ay center"));
|
||||
private final FScrollPane scrContent = new FScrollPane(pnlContent, false);
|
||||
|
||||
private final FLabel btnDownloadSetPics = _makeButton("Download LQ Set Pictures");
|
||||
private final FLabel btnDownloadPics = _makeButton("Download LQ Card Pictures");
|
||||
private final FLabel btnDownloadQuestImages = _makeButton("Download Quest Images");
|
||||
private final FLabel btnDownloadAchievementImages = _makeButton("Download Achievement Images");
|
||||
private final FLabel btnReportBug = _makeButton("Report a Bug");
|
||||
private final FLabel btnImportPictures = _makeButton("Import Data");
|
||||
private final FLabel btnHowToPlay = _makeButton("How To Play");
|
||||
private final FLabel btnDownloadPrices = _makeButton("Download Card Prices");
|
||||
private final FLabel btnLicensing = _makeButton("License Details");
|
||||
private final FLabel btnDownloadSetPics = _makeButton(localizer.getMessage("btnDownloadSetPics"));
|
||||
private final FLabel btnDownloadPics = _makeButton(localizer.getMessage("btnDownloadPics"));
|
||||
private final FLabel btnDownloadQuestImages = _makeButton(localizer.getMessage("btnDownloadQuestImages"));
|
||||
private final FLabel btnDownloadAchievementImages = _makeButton(localizer.getMessage("btnDownloadAchievementImages"));
|
||||
private final FLabel btnReportBug = _makeButton(localizer.getMessage("btnReportBug"));
|
||||
private final FLabel btnImportPictures = _makeButton(localizer.getMessage("btnImportPictures"));
|
||||
private final FLabel btnHowToPlay = _makeButton(localizer.getMessage("btnHowToPlay"));
|
||||
private final FLabel btnDownloadPrices = _makeButton(localizer.getMessage("btnDownloadPrices"));
|
||||
private final FLabel btnLicensing = _makeButton(localizer.getMessage("btnLicensing"));
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -61,47 +64,48 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
||||
if (javaRecentEnough()) {
|
||||
|
||||
pnlContent.add(btnDownloadPics, constraintsBTN);
|
||||
pnlContent.add(_makeLabel("Download default card picture for each card."), constraintsLBL);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPics")), constraintsLBL);
|
||||
|
||||
pnlContent.add(btnDownloadSetPics, constraintsBTN);
|
||||
pnlContent.add(_makeLabel("Download all pictures of each card (one for each set the card appeared in)"), constraintsLBL);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadSetPics")), constraintsLBL);
|
||||
|
||||
pnlContent.add(btnDownloadQuestImages, constraintsBTN);
|
||||
pnlContent.add(_makeLabel("Download tokens and icons used in Quest mode."), constraintsLBL);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadQuestImages")), constraintsLBL);
|
||||
|
||||
pnlContent.add(btnDownloadAchievementImages, constraintsBTN);
|
||||
pnlContent.add(_makeLabel("Download achievement images to really make your trophies stand out."), constraintsLBL);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadAchievementImages")), constraintsLBL);
|
||||
|
||||
pnlContent.add(btnDownloadPrices, constraintsBTN);
|
||||
pnlContent.add(_makeLabel("Download up-to-date price list for in-game card shops."), constraintsLBL);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPrices")), constraintsLBL);
|
||||
|
||||
} else {
|
||||
|
||||
String text = "Your version of Java is too old to use the content downloaders.";
|
||||
String text = localizer.getMessage("lblYourVersionOfJavaIsTooOld");
|
||||
FLabel label = new FLabel.Builder().fontAlign(SwingConstants.CENTER).text(text).fontStyle(Font.BOLD).fontSize(18).build();
|
||||
pnlContent.add(label, "w 90%!, h 25px!, center, gap 0 0 30px 3px");
|
||||
|
||||
text = "Please update to the latest version of Java 8 to use this feature.";
|
||||
text = localizer.getMessage("lblPleaseUpdateToTheLatestVersionOfJava");
|
||||
label = new FLabel.Builder().fontAlign(SwingConstants.CENTER).text(text).fontStyle(Font.BOLD).fontSize(18).build();
|
||||
pnlContent.add(label, "w 90%!, h 25px!, center, gap 0 0 0 36px");
|
||||
|
||||
text = "You're running " + System.getProperty("java.version") + ". You need at least version 1.8.0_101.";
|
||||
text = localizer.getMessage("lblYoureRunning") + " " + System.getProperty("java.version");
|
||||
text = text + " . " + localizer.getMessage("lblYouNeedAtLeastJavaVersion") ;
|
||||
label = new FLabel.Builder().fontAlign(SwingConstants.CENTER).text(text).fontStyle(Font.BOLD).fontSize(18).build();
|
||||
pnlContent.add(label, "w 90%!, h 25px!, center, gap 0 0 0 36px");
|
||||
|
||||
}
|
||||
|
||||
pnlContent.add(btnImportPictures, constraintsBTN);
|
||||
pnlContent.add(_makeLabel("Import data from a local directory."), constraintsLBL);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblImportPictures")), constraintsLBL);
|
||||
|
||||
pnlContent.add(btnReportBug, constraintsBTN);
|
||||
pnlContent.add(_makeLabel("Something broken?"), constraintsLBL);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblReportBug")), constraintsLBL);
|
||||
|
||||
pnlContent.add(btnHowToPlay, constraintsBTN);
|
||||
pnlContent.add(_makeLabel("Rules of the Game."), constraintsLBL);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblHowToPlay")), constraintsLBL);
|
||||
|
||||
pnlContent.add(btnLicensing, constraintsBTN);
|
||||
pnlContent.add(_makeLabel("Forge legal."), constraintsLBL);
|
||||
pnlContent.add(_makeLabel(localizer.getMessage("lblLicensing")), constraintsLBL);
|
||||
|
||||
}
|
||||
|
||||
@@ -210,7 +214,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
||||
*/
|
||||
@Override
|
||||
public String getMenuTitle() {
|
||||
return "Content Downloaders";
|
||||
return localizer.getMessage("ContentDownloaders");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -15,6 +15,7 @@ import forge.screens.home.VHomeUI;
|
||||
import forge.toolbox.*;
|
||||
import forge.toolbox.FSkin.SkinnedLabel;
|
||||
import forge.toolbox.FSkin.SkinnedTextField;
|
||||
import forge.util.Localizer;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -27,91 +28,94 @@ import java.awt.event.KeyEvent;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* Assembles Swing components of preferences submenu singleton.
|
||||
*
|
||||
* <br><br><i>(V at beginning of class name denotes a view class.)</i>
|
||||
*/
|
||||
public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
|
||||
/** */
|
||||
SINGLETON_INSTANCE;
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
|
||||
// Fields used with interface IVDoc
|
||||
private DragCell parentCell;
|
||||
private final DragTab tab = new DragTab("Preferences");
|
||||
private final DragTab tab = new DragTab(localizer.getMessage("Preferences"));
|
||||
|
||||
/** */
|
||||
private final JPanel pnlPrefs = new JPanel();
|
||||
private final FScrollPane scrContent = new FScrollPane(pnlPrefs, false,
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||
|
||||
private final FLabel btnReset = new FLabel.Builder().opaque(true).hoverable(true).text("Reset to Default Settings").build();
|
||||
private final FLabel btnDeleteMatchUI = new FLabel.Builder().opaque(true).hoverable(true).text("Reset Match Layout").build();
|
||||
private final FLabel btnDeleteEditorUI = new FLabel.Builder().opaque(true).hoverable(true).text("Reset Editor Layout").build();
|
||||
private final FLabel btnDeleteWorkshopUI = new FLabel.Builder().opaque(true).hoverable(true).text("Reset Workshop Layout").build();
|
||||
private final FLabel btnUserProfileUI = new FLabel.Builder().opaque(true).hoverable(true).text("Open User Directory").build();
|
||||
private final FLabel btnContentDirectoryUI = new FLabel.Builder().opaque(true).hoverable(true).text("Open Content Directory").build();
|
||||
private final FLabel btnResetJavaFutureCompatibilityWarnings = new FLabel.Builder().opaque(true).hoverable(true).text("Reset Java Compatibility Warnings").build();
|
||||
private final FLabel btnReset = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnReset")).build();
|
||||
private final FLabel btnDeleteMatchUI = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnDeleteMatchUI")).build();
|
||||
private final FLabel btnDeleteEditorUI = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnDeleteEditorUI")).build();
|
||||
private final FLabel btnDeleteWorkshopUI = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnDeleteWorkshopUI")).build();
|
||||
private final FLabel btnUserProfileUI = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnUserProfileUI")).build();
|
||||
private final FLabel btnContentDirectoryUI = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnContentDirectoryUI")).build();
|
||||
private final FLabel btnResetJavaFutureCompatibilityWarnings = new FLabel.Builder().opaque(true).hoverable(true).text(localizer.getMessage("btnResetJavaFutureCompatibilityWarnings")).build();
|
||||
private final FLabel btnPlayerName = new FLabel.Builder().opaque(true).hoverable(true).text("").build();
|
||||
|
||||
private final JCheckBox cbRemoveSmall = new OptionsCheckBox("Remove Small Creatures");
|
||||
private final JCheckBox cbCardBased = new OptionsCheckBox("Include Card-based Deck Generation");
|
||||
private final JCheckBox cbSingletons = new OptionsCheckBox("Singleton Mode");
|
||||
private final JCheckBox cbRemoveArtifacts = new OptionsCheckBox("Remove Artifacts");
|
||||
private final JCheckBox cbAnte = new OptionsCheckBox("Play for Ante");
|
||||
private final JCheckBox cbAnteMatchRarity = new OptionsCheckBox("Match Ante Rarity");
|
||||
private final JCheckBox cbEnableAICheats = new OptionsCheckBox("Allow AI Cheating");
|
||||
private final JCheckBox cbManaBurn = new OptionsCheckBox("Mana Burn");
|
||||
private final JCheckBox cbManaLostPrompt = new OptionsCheckBox("Prompt Mana Pool Emptying");
|
||||
private final JCheckBox cbDevMode = new OptionsCheckBox("Developer Mode");
|
||||
private final JCheckBox cbLoadCardsLazily = new OptionsCheckBox("Load Card Scripts Lazily");
|
||||
private final JCheckBox cbLoadHistoricFormats = new OptionsCheckBox("Load Historic Formats");
|
||||
private final JCheckBox cbWorkshopSyntax = new OptionsCheckBox("Workshop Syntax Checker");
|
||||
private final JCheckBox cbEnforceDeckLegality = new OptionsCheckBox("Deck Conformance");
|
||||
private final JCheckBox cbPerformanceMode = new OptionsCheckBox("Performance Mode");
|
||||
private final JCheckBox cbFilteredHands = new OptionsCheckBox("Filtered Hands");
|
||||
private final JCheckBox cbImageFetcher = new OptionsCheckBox("Automatically Download Missing Card Art");
|
||||
private final JCheckBox cbCloneImgSource = new OptionsCheckBox("Clones Use Original Card Art");
|
||||
private final JCheckBox cbScaleLarger = new OptionsCheckBox("Scale Image Larger");
|
||||
private final JCheckBox cbRenderBlackCardBorders = new OptionsCheckBox("Render Black Card Borders");
|
||||
private final JCheckBox cbLargeCardViewers = new OptionsCheckBox("Use Large Card Viewers");
|
||||
private final JCheckBox cbSmallDeckViewer = new OptionsCheckBox("Use Small Deck Viewer");
|
||||
private final JCheckBox cbDisplayFoil = new OptionsCheckBox("Display Foil Overlay");
|
||||
private final JCheckBox cbRandomFoil = new OptionsCheckBox("Random Foil");
|
||||
private final JCheckBox cbRandomArtInPools = new OptionsCheckBox("Randomize Card Art in Generated Card Pools");
|
||||
private final JCheckBox cbEnableSounds = new OptionsCheckBox("Enable Sounds");
|
||||
private final JCheckBox cbEnableMusic = new OptionsCheckBox("Enable Music");
|
||||
private final JCheckBox cbAltSoundSystem = new OptionsCheckBox("Use Alternate Sound System");
|
||||
private final JCheckBox cbUiForTouchScreen = new OptionsCheckBox("Enhance UI for Touchscreens");
|
||||
private final JCheckBox cbTimedTargOverlay = new OptionsCheckBox("Enable Targeting Overlay Optimization");
|
||||
private final JCheckBox cbCompactMainMenu = new OptionsCheckBox("Use Compact Main Sidebar Menu");
|
||||
private final JCheckBox cbDetailedPaymentDesc = new OptionsCheckBox("Spell Description in Payment Prompt");
|
||||
private final JCheckBox cbPromptFreeBlocks = new OptionsCheckBox("Free Block Handling");
|
||||
private final JCheckBox cbPauseWhileMinimized = new OptionsCheckBox("Pause While Minimized");
|
||||
private final JCheckBox cbCompactPrompt = new OptionsCheckBox("Compact Prompt");
|
||||
private final JCheckBox cbEscapeEndsTurn = new OptionsCheckBox("Use Escape Key to End Turn");
|
||||
private final JCheckBox cbPreselectPrevAbOrder = new OptionsCheckBox("Preselect Last Order of Abilities");
|
||||
private final JCheckBox cbHideReminderText = new OptionsCheckBox("Hide Reminder Text");
|
||||
private final JCheckBox cbOpenPacksIndiv = new OptionsCheckBox("Open Packs Individually");
|
||||
private final JCheckBox cbTokensInSeparateRow = new OptionsCheckBox("Display Tokens in a Separate Row");
|
||||
private final JCheckBox cbStackCreatures = new OptionsCheckBox("Stack Creatures");
|
||||
private final JCheckBox cbFilterLandsByColorId = new OptionsCheckBox("Filter Lands by Color in Activated Abilities");
|
||||
private final JCheckBox cbShowStormCount = new OptionsCheckBox("Show Storm Count in Prompt Pane");
|
||||
private final JCheckBox cbRemindOnPriority = new OptionsCheckBox("Visually Alert on Receipt of Priority");
|
||||
private final JCheckBox cbUseSentry = new OptionsCheckBox("Automatically submit bug reports.");
|
||||
private final JCheckBox cbRemoveSmall = new OptionsCheckBox(localizer.getMessage("cbRemoveSmall"));
|
||||
private final JCheckBox cbCardBased = new OptionsCheckBox(localizer.getMessage("cbCardBased"));
|
||||
private final JCheckBox cbSingletons = new OptionsCheckBox(localizer.getMessage("cbSingletons"));
|
||||
private final JCheckBox cbRemoveArtifacts = new OptionsCheckBox(localizer.getMessage("cbRemoveArtifacts"));
|
||||
private final JCheckBox cbAnte = new OptionsCheckBox(localizer.getMessage("cbAnte"));
|
||||
private final JCheckBox cbAnteMatchRarity = new OptionsCheckBox(localizer.getMessage("cbAnteMatchRarity"));
|
||||
private final JCheckBox cbEnableAICheats = new OptionsCheckBox(localizer.getMessage("cbEnableAICheats"));
|
||||
private final JCheckBox cbManaBurn = new OptionsCheckBox(localizer.getMessage("cbManaBurn"));
|
||||
private final JCheckBox cbManaLostPrompt = new OptionsCheckBox(localizer.getMessage("cbManaLostPrompt"));
|
||||
private final JCheckBox cbDevMode = new OptionsCheckBox(localizer.getMessage("cbDevMode"));
|
||||
private final JCheckBox cbLoadCardsLazily = new OptionsCheckBox(localizer.getMessage("cbLoadCardsLazily"));
|
||||
private final JCheckBox cbLoadHistoricFormats = new OptionsCheckBox(localizer.getMessage("cbLoadHistoricFormats"));
|
||||
private final JCheckBox cbWorkshopSyntax = new OptionsCheckBox(localizer.getMessage("cbWorkshopSyntax"));
|
||||
private final JCheckBox cbEnforceDeckLegality = new OptionsCheckBox(localizer.getMessage("cbEnforceDeckLegality"));
|
||||
private final JCheckBox cbPerformanceMode = new OptionsCheckBox(localizer.getMessage("cbPerformanceMode"));
|
||||
private final JCheckBox cbFilteredHands = new OptionsCheckBox(localizer.getMessage("cbFilteredHands"));
|
||||
private final JCheckBox cbImageFetcher = new OptionsCheckBox(localizer.getMessage("cbImageFetcher"));
|
||||
private final JCheckBox cbCloneImgSource = new OptionsCheckBox(localizer.getMessage("cbCloneImgSource"));
|
||||
private final JCheckBox cbScaleLarger = new OptionsCheckBox(localizer.getMessage("cbScaleLarger"));
|
||||
private final JCheckBox cbRenderBlackCardBorders = new OptionsCheckBox(localizer.getMessage("cbRenderBlackCardBorders"));
|
||||
private final JCheckBox cbLargeCardViewers = new OptionsCheckBox(localizer.getMessage("cbLargeCardViewers"));
|
||||
private final JCheckBox cbSmallDeckViewer = new OptionsCheckBox(localizer.getMessage("cbSmallDeckViewer"));
|
||||
private final JCheckBox cbDisplayFoil = new OptionsCheckBox(localizer.getMessage("cbDisplayFoil"));
|
||||
private final JCheckBox cbRandomFoil= new OptionsCheckBox(localizer.getMessage("cbRandomFoil"));
|
||||
private final JCheckBox cbRandomArtInPools = new OptionsCheckBox(localizer.getMessage("cbRandomArtInPools"));
|
||||
private final JCheckBox cbEnableSounds = new OptionsCheckBox(localizer.getMessage("cbEnableSounds"));
|
||||
private final JCheckBox cbEnableMusic = new OptionsCheckBox(localizer.getMessage("cbEnableMusic"));
|
||||
private final JCheckBox cbAltSoundSystem = new OptionsCheckBox(localizer.getMessage("cbAltSoundSystem"));
|
||||
private final JCheckBox cbUiForTouchScreen = new OptionsCheckBox(localizer.getMessage("cbUiForTouchScreen"));
|
||||
private final JCheckBox cbTimedTargOverlay = new OptionsCheckBox(localizer.getMessage("cbTimedTargOverlay"));
|
||||
private final JCheckBox cbCompactMainMenu = new OptionsCheckBox(localizer.getMessage("cbCompactMainMenu"));
|
||||
private final JCheckBox cbDetailedPaymentDesc = new OptionsCheckBox(localizer.getMessage("cbDetailedPaymentDesc"));
|
||||
private final JCheckBox cbPromptFreeBlocks = new OptionsCheckBox(localizer.getMessage("cbPromptFreeBlocks"));
|
||||
private final JCheckBox cbPauseWhileMinimized = new OptionsCheckBox(localizer.getMessage("cbPauseWhileMinimized"));
|
||||
private final JCheckBox cbCompactPrompt = new OptionsCheckBox(localizer.getMessage("cbCompactPrompt"));
|
||||
private final JCheckBox cbEscapeEndsTurn = new OptionsCheckBox(localizer.getMessage("cbEscapeEndsTurn"));
|
||||
private final JCheckBox cbPreselectPrevAbOrder = new OptionsCheckBox(localizer.getMessage("cbPreselectPrevAbOrder"));
|
||||
private final JCheckBox cbHideReminderText = new OptionsCheckBox(localizer.getMessage("cbHideReminderText"));
|
||||
private final JCheckBox cbOpenPacksIndiv = new OptionsCheckBox(localizer.getMessage("cbOpenPacksIndiv"));
|
||||
private final JCheckBox cbTokensInSeparateRow = new OptionsCheckBox(localizer.getMessage("cbTokensInSeparateRow"));
|
||||
private final JCheckBox cbStackCreatures = new OptionsCheckBox(localizer.getMessage("cbStackCreatures"));
|
||||
private final JCheckBox cbFilterLandsByColorId = new OptionsCheckBox(localizer.getMessage("cbFilterLandsByColorId"));
|
||||
private final JCheckBox cbShowStormCount = new OptionsCheckBox(localizer.getMessage("cbShowStormCount"));
|
||||
private final JCheckBox cbRemindOnPriority = new OptionsCheckBox(localizer.getMessage("cbRemindOnPriority"));
|
||||
private final JCheckBox cbUseSentry = new OptionsCheckBox(localizer.getMessage("cbUseSentry"));
|
||||
|
||||
private final Map<FPref, KeyboardShortcutField> shortcutFields = new HashMap<>();
|
||||
|
||||
// ComboBox items are added in CSubmenuPreferences since this is just the View.
|
||||
private final FComboBoxPanel<GameLogEntryType> cbpGameLogEntryType = new FComboBoxPanel<>("Game Log Verbosity:");
|
||||
private final FComboBoxPanel<CloseAction> cbpCloseAction = new FComboBoxPanel<>("Close Action:");
|
||||
private final FComboBoxPanel<String> cbpDefaultFontSize = new FComboBoxPanel<>("Default Font Size:");
|
||||
private final FComboBoxPanel<String> cbpAiProfiles = new FComboBoxPanel<>("AI Personality:");
|
||||
private final FComboBoxPanel<String> cbpDisplayCurrentCardColors = new FComboBoxPanel<>("Show Detailed Card Color:");
|
||||
private final FComboBoxPanel<String> cbpAutoYieldMode = new FComboBoxPanel<>("Auto-Yield:");
|
||||
private final FComboBoxPanel<String> cbpCounterDisplayType = new FComboBoxPanel<>("Counter Display Type:");
|
||||
private final FComboBoxPanel<String> cbpCounterDisplayLocation = new FComboBoxPanel<>("Counter Display Location:");
|
||||
private final FComboBoxPanel<String> cbpGraveyardOrdering = new FComboBoxPanel<>("Allow Ordering Cards Put in Graveyard:");
|
||||
private final FComboBoxPanel<GameLogEntryType> cbpGameLogEntryType = new FComboBoxPanel<>(localizer.getMessage("cbpGameLogEntryType")+":");
|
||||
private final FComboBoxPanel<CloseAction> cbpCloseAction = new FComboBoxPanel<>(localizer.getMessage("cbpCloseAction")+":");
|
||||
private final FComboBoxPanel<String> cbpDefaultFontSize = new FComboBoxPanel<>(localizer.getMessage("cbpDefaultFontSize")+":");
|
||||
private final FComboBoxPanel<String> cbpAiProfiles = new FComboBoxPanel<>(localizer.getMessage("cbpAiProfiles")+":");
|
||||
private final FComboBoxPanel<String> cbpDisplayCurrentCardColors = new FComboBoxPanel<>(localizer.getMessage("cbpDisplayCurrentCardColors")+":");
|
||||
private final FComboBoxPanel<String> cbpAutoYieldMode = new FComboBoxPanel<>(localizer.getMessage("cbpAutoYieldMode")+":");
|
||||
private final FComboBoxPanel<String> cbpCounterDisplayType = new FComboBoxPanel<>(localizer.getMessage("cbpCounterDisplayType")+":");
|
||||
private final FComboBoxPanel<String> cbpCounterDisplayLocation =new FComboBoxPanel<>(localizer.getMessage("cbpCounterDisplayLocation")+":");
|
||||
private final FComboBoxPanel<String> cbpGraveyardOrdering = new FComboBoxPanel<>(localizer.getMessage("cbpGraveyardOrdering")+":");
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
@@ -128,7 +132,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
final String descriptionConstraints = "w 80%!, h 22px!, gap 28px 0 0 20px, span 2 1";
|
||||
|
||||
// Troubleshooting
|
||||
pnlPrefs.add(new SectionLabel("Troubleshooting"), sectionConstraints);
|
||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("Troubleshooting")), sectionConstraints);
|
||||
|
||||
// Reset buttons
|
||||
final String twoButtonConstraints1 = "w 38%!, h 30px!, gap 25px 0 0 10px";
|
||||
@@ -141,199 +145,199 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
||||
pnlPrefs.add(btnContentDirectoryUI, twoButtonConstraints2);
|
||||
|
||||
// General Configuration
|
||||
pnlPrefs.add(new SectionLabel("General Configuration"), sectionConstraints);
|
||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("GeneralConfiguration")), sectionConstraints);
|
||||
|
||||
pnlPrefs.add(getPlayerNamePanel(), titleConstraints + ", h 26px!");
|
||||
pnlPrefs.add(new NoteLabel("Sets the name that you will be referred to by Forge during gameplay."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlPlayerName")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbCompactMainMenu, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Enable for a space efficient sidebar that displays only one menu group at a time (RESTART REQUIRED)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlCompactMainMenu")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbUseSentry, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled, automatically submits bug reports to developers."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlUseSentry")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(btnResetJavaFutureCompatibilityWarnings, "w 300px!, h 30px!, gap 27px 0 0 20px, span 2 1");
|
||||
|
||||
// Gameplay Options
|
||||
pnlPrefs.add(new SectionLabel("Gameplay"), sectionConstraints);
|
||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("GamePlay")), sectionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpAiProfiles, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Choose your AI opponent."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlpAiProfiles")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbAnte, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Determines whether or not the game is played for ante."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlAnte")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbAnteMatchRarity, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Attempts to make antes the same rarity for all players."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlAnteMatchRarity")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbEnableAICheats, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Allow the AI to cheat to gain advantage (for personalities that have cheat shuffling options set)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlEnableAICheats")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbManaBurn, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Play with mana burn (from pre-Magic 2010 rules)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlManaBurn")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbManaLostPrompt, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled, you get a warning if passing priority would cause you to lose mana in your mana pool."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlManaLostPrompt")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbEnforceDeckLegality, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Enforces deck legality relevant to each environment (minimum deck sizes, max card count etc)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlEnforceDeckLegality")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbPerformanceMode, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Disables additional static abilities checks to speed up the game engine. (Warning: breaks some 'as if had flash' scenarios when casting cards owned by opponents)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlPerformanceMode")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbFilteredHands, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Generates two starting hands and keeps the one with the closest to average land count for the deck. (Requires restart)"), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlFilteredHands")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbCloneImgSource, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled clones will use their original art instead of the cloned card's art."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlCloneImgSource")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbPromptFreeBlocks, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled, if you would have to pay 0 to block, pay automatically without prompt."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlPromptFreeBlocks")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbPauseWhileMinimized, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled, Forge pauses when minimized (primarily for AI vs AI)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlPauseWhileMinimized")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbEscapeEndsTurn, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled, Escape key functions as an alternative shortcut to end the current turn."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlEscapeEndsTurn")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbDetailedPaymentDesc, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled, detailed spell/ability descriptions are shown when choosing targets and paying costs."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlDetailedPaymentDesc")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbShowStormCount, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled, displays the current storm count in the prompt pane."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlShowStormCount")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbRemindOnPriority, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled, flashes the player choice area upon receiving priority."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlRemindOnPriority")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbPreselectPrevAbOrder, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When enabled, preselects the last defined simultaneous ability order in the ordering dialog."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlPreselectPrevAbOrder")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpGraveyardOrdering, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Determines when to let the player choose the order of cards simultaneously put in graveyard (never, always, or only when playing with cards for which it matters, for example, Volrath's Shapeshifter)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlpGraveyardOrdering")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpAutoYieldMode, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Defines the granularity level of auto-yields (per unique ability or per unique card)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlpAutoYieldMode")), descriptionConstraints);
|
||||
|
||||
// Deck building options
|
||||
pnlPrefs.add(new SectionLabel("Random Deck Generation"), sectionConstraints);
|
||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("RandomDeckGeneration")), sectionConstraints);
|
||||
|
||||
pnlPrefs.add(cbRemoveSmall, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Disables 1/1 and 0/X creatures in generated decks."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlRemoveSmall")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbSingletons, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Disables non-land duplicates in generated decks."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlSingletons")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbRemoveArtifacts, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Disables artifact cards in generated decks."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlRemoveArtifacts")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbCardBased, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Builds more synergistic random decks (requires restart)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlCardBased")), descriptionConstraints);
|
||||
|
||||
// Deck building options
|
||||
pnlPrefs.add(new SectionLabel("Deck Editor Options"), sectionConstraints);
|
||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("DeckEditorOptions")), sectionConstraints);
|
||||
|
||||
pnlPrefs.add(cbFilterLandsByColorId, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When using card color filters, filter lands in a way to make it easier to find relevant mana producing lands."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlFilterLandsByColorId")), descriptionConstraints);
|
||||
|
||||
// Advanced
|
||||
pnlPrefs.add(new SectionLabel("Advanced Settings"), sectionConstraints);
|
||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("AdvancedSettings")), sectionConstraints);
|
||||
|
||||
pnlPrefs.add(cbDevMode, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Enables menu with functions for testing during development."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlDevMode")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbWorkshopSyntax, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Enables syntax checking of card scripts in the Workshop. Note: functionality still in testing phase!"), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlWorkshopSyntax")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpGameLogEntryType, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Changes how much information is displayed in the game log. Sorted by least to most verbose."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlGameLogEntryType")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpCloseAction, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Changes what happens when clicking the X button in the upper right."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlCloseAction")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbLoadCardsLazily, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("If turned on, Forge will load card scripts as they're needed instead of at start up. (Warning: Experimental)"), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlLoadCardsLazily")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbLoadHistoricFormats, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("If turned on, Forge will load all historic format definitions, this may take slightly longer to load at startup."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlLoadHistoricFormats")), descriptionConstraints);
|
||||
|
||||
// Graphic Options
|
||||
pnlPrefs.add(new SectionLabel("Graphic Options"), sectionConstraints + ", gaptop 2%");
|
||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("GraphicOptions")), sectionConstraints + ", gaptop 2%");
|
||||
|
||||
pnlPrefs.add(cbpDefaultFontSize, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("The default font size within the UI. All font elements are scaled relative to this. (Needs restart)"), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlDefaultFontSize")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbImageFetcher, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Enables live fetching of missing card images from an online resource."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlImageFetcher")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbDisplayFoil, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Displays foil cards with the visual foil overlay effect."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlDisplayFoil")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbRandomFoil, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Adds foil effect to random cards."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlRandomFoil")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbScaleLarger, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Allows card pictures to be expanded larger than their original size."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlScaleLarger")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbRenderBlackCardBorders, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Render black borders around card images."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlRenderBlackCardBorders")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbLargeCardViewers, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Makes all card viewers much larger for use with high resolution images. Will not fit on smaller screens."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlLargeCardViewers")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbSmallDeckViewer, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Sets the deck viewer window to be 800x600 rather than a proportion of the screen size."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlSmallDeckViewer")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbRandomArtInPools, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Generates cards with random art in generated limited mode card pools."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlRandomArtInPools")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbUiForTouchScreen, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Increases some UI elements to provide a better experience on touchscreen devices. (Needs restart)"), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlUiForTouchScreen")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbCompactPrompt, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Hide header and use smaller font in Prompt pane to make it more compact."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlCompactPrompt")), descriptionConstraints);
|
||||
|
||||
/*pnlPrefs.add(cbStackCardView, titleConstraints); TODO: Show this checkbox when setting can support being enabled
|
||||
pnlPrefs.add(new NoteLabel("Show cards and abilities on Stack in card view rather than list view."), descriptionConstraints);*/
|
||||
|
||||
pnlPrefs.add(cbHideReminderText, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Hide reminder text in Card Detail pane."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlHideReminderText")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbOpenPacksIndiv, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("When opening Fat Packs and Booster Boxes, booster packs will be opened and displayed one at a time."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlOpenPacksIndiv")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbTokensInSeparateRow, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Displays tokens in a separate row on the battlefield below the non-token creatures."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlTokensInSeparateRow")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbStackCreatures, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Stacks identical creatures on the battlefield like lands, artifacts, and enchantments."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlStackCreatures")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbTimedTargOverlay, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Enables throttling-based optimization of targeting overlay to reduce CPU use (only disable if you experience choppiness on older hardware, requires starting a new match)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlTimedTargOverlay")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpCounterDisplayType, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Selects the style of the in-game counter display for cards. Text-based is a new tab-like display on the cards. Image-based is the old counter image. Hybrid displays both at once."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlCounterDisplayType")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpCounterDisplayLocation, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Determines where to position the text-based counters on the card: close to the top or close to the bottom."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlCounterDisplayLocation")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbpDisplayCurrentCardColors, comboBoxConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Displays the breakdown of the current color of cards in the card detail information panel."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlDisplayCurrentCardColors")), descriptionConstraints);
|
||||
|
||||
// Sound options
|
||||
pnlPrefs.add(new SectionLabel("Sound Options"), sectionConstraints + ", gaptop 2%");
|
||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("SoundOptions")), sectionConstraints + ", gaptop 2%");
|
||||
|
||||
pnlPrefs.add(cbEnableSounds, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Enable sound effects during the game."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlEnableSounds")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbEnableMusic, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Enable background music during the game."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlEnableMusic")), descriptionConstraints);
|
||||
|
||||
pnlPrefs.add(cbAltSoundSystem, titleConstraints);
|
||||
pnlPrefs.add(new NoteLabel("Use the alternate sound system (only use if you have issues with sound not playing or disappearing)."), descriptionConstraints);
|
||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlAltSoundSystem")), descriptionConstraints);
|
||||
|
||||
|
||||
// Keyboard shortcuts
|
||||
pnlPrefs.add(new SectionLabel("Keyboard Shortcuts"), sectionConstraints);
|
||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("KeyboardShortcuts")), sectionConstraints);
|
||||
|
||||
final List<Shortcut> shortcuts = KeyboardShortcuts.getKeyboardShortcuts();
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ import forge.toolbox.FScrollPane;
|
||||
import forge.toolbox.FSkin;
|
||||
import forge.toolbox.FSkin.SkinnedTextArea;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
|
||||
import forge.util.Localizer;
|
||||
import javax.swing.*;
|
||||
|
||||
/**
|
||||
@@ -40,10 +40,11 @@ import javax.swing.*;
|
||||
public enum VSubmenuReleaseNotes implements IVSubmenu<CSubmenuReleaseNotes> {
|
||||
|
||||
SINGLETON_INSTANCE;
|
||||
final Localizer localizer = Localizer.getInstance();
|
||||
|
||||
// Fields used with interface IVDoc
|
||||
private DragCell parentCell;
|
||||
private final DragTab tab = new DragTab("Release Notes");
|
||||
private final DragTab tab = new DragTab(localizer.getMessage("ReleaseNotes"));
|
||||
|
||||
private final JPanel pnlMain = new JPanel();
|
||||
private SkinnedTextArea tar;
|
||||
@@ -93,7 +94,7 @@ public enum VSubmenuReleaseNotes implements IVSubmenu<CSubmenuReleaseNotes> {
|
||||
*/
|
||||
@Override
|
||||
public String getMenuTitle() {
|
||||
return "Release Notes";
|
||||
return localizer.getMessage("ReleaseNotes");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -100,7 +100,8 @@ import forge.util.ITriggerEvent;
|
||||
import forge.util.gui.SOptionPane;
|
||||
import forge.view.FView;
|
||||
import forge.view.arcane.CardPanel;
|
||||
import forge.view.arcane.FloatingCardArea;
|
||||
import forge.view.arcane.FloatingZone;
|
||||
import forge.match.input.*;
|
||||
|
||||
/**
|
||||
* Constructs instance of match UI controller, used as a single point of
|
||||
@@ -395,10 +396,12 @@ public final class CMatchUI
|
||||
break;
|
||||
case Hand:
|
||||
updateHand = true;
|
||||
//$FALL-THROUGH$
|
||||
updateZones = true;
|
||||
FloatingZone.refresh(owner, zone);
|
||||
break;
|
||||
default:
|
||||
updateZones = true;
|
||||
FloatingCardArea.refresh(owner, zone);
|
||||
FloatingZone.refresh(owner, zone);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -412,6 +415,8 @@ public final class CMatchUI
|
||||
if (vHand != null) {
|
||||
vHand.getLayoutControl().updateHand();
|
||||
}
|
||||
// update Cards in Hand
|
||||
vField.updateDetails();
|
||||
}
|
||||
if (updateAnte) {
|
||||
cAntes.update();
|
||||
@@ -422,6 +427,59 @@ public final class CMatchUI
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<PlayerZoneUpdate> tempShowZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> zonesToUpdate) {
|
||||
for (final PlayerZoneUpdate update : zonesToUpdate) {
|
||||
final PlayerView player = update.getPlayer();
|
||||
for (final ZoneType zone : update.getZones()) {
|
||||
switch (zone) {
|
||||
case Battlefield: // always shown
|
||||
break;
|
||||
case Hand: // controller hand always shown
|
||||
if (controller != player) {
|
||||
FloatingZone.show(this,player,zone);
|
||||
}
|
||||
break;
|
||||
case Library:
|
||||
case Graveyard:
|
||||
case Exile:
|
||||
case Flashback:
|
||||
case Command:
|
||||
FloatingZone.show(this,player,zone);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return zonesToUpdate; //pfps should return only the newly shown zones
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hideZones(final PlayerView controller, final Iterable<PlayerZoneUpdate> zonesToUpdate) {
|
||||
if ( zonesToUpdate != null ) {
|
||||
for (final PlayerZoneUpdate update : zonesToUpdate) {
|
||||
final PlayerView player = update.getPlayer();
|
||||
for (final ZoneType zone : update.getZones()) {
|
||||
switch (zone) {
|
||||
case Battlefield: // always shown
|
||||
break;
|
||||
case Hand: // the controller's hand should never be temporarily shown, but ...
|
||||
case Library:
|
||||
case Graveyard:
|
||||
case Exile:
|
||||
case Flashback:
|
||||
case Command:
|
||||
FloatingZone.hide(this,player,zone);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Player's mana pool changes
|
||||
@Override
|
||||
public void updateManaPool(final Iterable<PlayerView> manaPoolUpdate) {
|
||||
@@ -463,11 +521,51 @@ public final class CMatchUI
|
||||
}
|
||||
break;
|
||||
default:
|
||||
FloatingZone.refresh(c.getController(),zone); // in case the card is visible in the zone
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSelectables(final Iterable<CardView> cards) {
|
||||
super.setSelectables(cards);
|
||||
// update zones on tabletop and floating zones - non-selectable cards may be rendered differently
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
for (final PlayerView p : getGameView().getPlayers()) {
|
||||
if ( p.getCards(ZoneType.Battlefield) != null ) {
|
||||
updateCards(p.getCards(ZoneType.Battlefield));
|
||||
}
|
||||
if ( p.getCards(ZoneType.Hand) != null ) {
|
||||
updateCards(p.getCards(ZoneType.Hand));
|
||||
}
|
||||
}
|
||||
FloatingZone.refreshAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSelectables() {
|
||||
super.clearSelectables();
|
||||
// update zones on tabletop and floating zones - non-selectable cards may be rendered differently
|
||||
FThreads.invokeInEdtNowOrLater(new Runnable() {
|
||||
@Override public final void run() {
|
||||
for (final PlayerView p : getGameView().getPlayers()) {
|
||||
if ( p.getCards(ZoneType.Battlefield) != null ) {
|
||||
updateCards(p.getCards(ZoneType.Battlefield));
|
||||
}
|
||||
if ( p.getCards(ZoneType.Hand) != null ) {
|
||||
updateCards(p.getCards(ZoneType.Hand));
|
||||
}
|
||||
}
|
||||
FloatingZone.refreshAll();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<JMenu> getMenus() {
|
||||
return menus.getMenus();
|
||||
@@ -502,7 +600,7 @@ public final class CMatchUI
|
||||
layoutControl.initialize();
|
||||
layoutControl.update();
|
||||
}
|
||||
FloatingCardArea.closeAll();
|
||||
FloatingZone.closeAll();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -560,7 +658,7 @@ public final class CMatchUI
|
||||
case Exile:
|
||||
case Graveyard:
|
||||
case Library:
|
||||
return FloatingCardArea.getCardPanel(this, card);
|
||||
return FloatingZone.getCardPanel(this, card);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -671,7 +769,7 @@ public final class CMatchUI
|
||||
|
||||
@Override
|
||||
public void finishGame() {
|
||||
FloatingCardArea.closeAll(); //ensure floating card areas cleared and closed after the game
|
||||
FloatingZone.closeAll(); //ensure floating card areas cleared and closed after the game
|
||||
final GameView gameView = getGameView();
|
||||
if (hasLocalPlayers() || gameView.isMatchOver()) {
|
||||
new ViewWinLose(gameView, this).show();
|
||||
@@ -785,7 +883,7 @@ public final class CMatchUI
|
||||
} else {
|
||||
final ZoneType zone = hostCard.getZone();
|
||||
if (ImmutableList.of(ZoneType.Command, ZoneType.Exile, ZoneType.Graveyard, ZoneType.Library).contains(zone)) {
|
||||
FloatingCardArea.show(this, hostCard.getController(), zone);
|
||||
FloatingZone.show(this, hostCard.getController(), zone);
|
||||
}
|
||||
menuParent = panel.getParent();
|
||||
x = triggerEvent.getX();
|
||||
@@ -940,11 +1038,16 @@ public final class CMatchUI
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<GameEntityView> chooseEntitiesForEffect(final String title, final List<? extends GameEntityView> optionList, final DelayedReveal delayedReveal) {
|
||||
public List<GameEntityView> chooseEntitiesForEffect(final String title, final List<? extends GameEntityView> optionList, final int min, final int max, final DelayedReveal delayedReveal) {
|
||||
if (delayedReveal != null) {
|
||||
reveal(delayedReveal.getMessagePrefix(), delayedReveal.getCards()); //TODO: Merge this into search dialog
|
||||
}
|
||||
return (List<GameEntityView>) order(title,"Selected", 0, optionList.size(), optionList, null, null, false);
|
||||
return (List<GameEntityView>) order(title,"Selected", min, max, optionList, null, null, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CardView> manipulateCardList(final String title, final Iterable<CardView> cards, final Iterable<CardView> manipulable, final boolean toTop, final boolean toBottom, final boolean toAnywhere) {
|
||||
return GuiChoose.manipulateCardList(this, title, cards, manipulable, toTop, toBottom, toAnywhere);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -79,6 +79,13 @@ public class TargetingOverlay {
|
||||
x2 = end.x;
|
||||
y2 = end.y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
Arc arc = (Arc)obj;
|
||||
return ((arc.x1 == x1) && (arc.x2 == x2) && (arc.y1 == y1) && (arc.y2 == y2));
|
||||
}
|
||||
}
|
||||
|
||||
private final Set<CardView> cardsVisualized = new HashSet<CardView>();
|
||||
@@ -331,13 +338,24 @@ public class TargetingOverlay {
|
||||
activeStackItem.addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseEntered(final MouseEvent e) {
|
||||
assembleStackArrows();
|
||||
FView.SINGLETON_INSTANCE.getFrame().repaint();
|
||||
if (matchUI.getCDock().getArcState() == ArcState.MOUSEOVER) {
|
||||
assembleStackArrows();
|
||||
FView.SINGLETON_INSTANCE.getFrame().repaint();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void mouseExited(final MouseEvent e) {
|
||||
assembleStackArrows();
|
||||
FView.SINGLETON_INSTANCE.getFrame().repaint();
|
||||
if (matchUI.getCDock().getArcState() == ArcState.MOUSEOVER) {
|
||||
assembleStackArrows();
|
||||
FView.SINGLETON_INSTANCE.getFrame().repaint();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void mouseClicked(final MouseEvent e) {
|
||||
if (matchUI.getCDock().getArcState() == ArcState.ON) {
|
||||
assembleStackArrows();
|
||||
FView.SINGLETON_INSTANCE.getFrame().repaint();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -384,18 +402,27 @@ public class TargetingOverlay {
|
||||
if (start == null || end == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Arc newArc = new Arc(end,start);
|
||||
|
||||
switch (connects) {
|
||||
case Friends:
|
||||
case FriendsStackTargeting:
|
||||
arcsFriend.add(new Arc(end, start));
|
||||
if (!arcsFriend.contains(newArc)) {
|
||||
arcsFriend.add(newArc);
|
||||
}
|
||||
break;
|
||||
case FoesAttacking:
|
||||
arcsFoeAtk.add(new Arc(end, start));
|
||||
if (!arcsFoeAtk.contains(newArc)) {
|
||||
arcsFoeAtk.add(newArc);
|
||||
}
|
||||
break;
|
||||
case FoesBlocking:
|
||||
case FoesStackTargeting:
|
||||
arcsFoeDef.add(new Arc(end, start));
|
||||
if (!arcsFoeDef.contains(newArc)) {
|
||||
arcsFoeDef.add(newArc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,56 +431,24 @@ public class TargetingOverlay {
|
||||
return; //don't add arcs for cards if card already visualized
|
||||
}
|
||||
|
||||
final CardView enchanting = c.getEnchantingCard();
|
||||
final CardView equipping = c.getEquipping();
|
||||
final CardView fortifying = c.getFortifying();
|
||||
final Iterable<CardView> enchantedBy = c.getEnchantedBy();
|
||||
final Iterable<CardView> equippedBy = c.getEquippedBy();
|
||||
final Iterable<CardView> fortifiedBy = c.getFortifiedBy();
|
||||
final CardView attachedTo = c.getAttachedTo();
|
||||
final Iterable<CardView> attachedCards = c.getAttachedCards();
|
||||
final CardView paired = c.getPairedWith();
|
||||
|
||||
if (null != enchanting) {
|
||||
if (enchanting.getController() != null && !enchanting.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(enchanting.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(enchanting);
|
||||
if (null != attachedTo) {
|
||||
if (attachedTo.getController() != null && !attachedTo.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(attachedTo.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(attachedTo);
|
||||
}
|
||||
}
|
||||
if (null != equipping) {
|
||||
if (equipping.getController() != null && !equipping.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(equipping.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(equipping);
|
||||
}
|
||||
}
|
||||
if (null != fortifying) {
|
||||
if (fortifying.getController() != null && !fortifying.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(fortifying.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(fortifying);
|
||||
}
|
||||
}
|
||||
if (null != enchantedBy) {
|
||||
for (final CardView enc : enchantedBy) {
|
||||
if (null != attachedCards) {
|
||||
for (final CardView enc : attachedCards) {
|
||||
if (enc.getController() != null && !enc.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(c.getId()), endpoints.get(enc.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(enc);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (null != equippedBy) {
|
||||
for (final CardView eq : equippedBy) {
|
||||
if (eq.getController() != null && !eq.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(c.getId()), endpoints.get(eq.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(eq);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (null != fortifiedBy) {
|
||||
for (final CardView eq : fortifiedBy) {
|
||||
if (eq.getController() != null && !eq.getController().equals(c.getController())) {
|
||||
addArc(endpoints.get(c.getId()), endpoints.get(eq.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(eq);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (null != paired) {
|
||||
addArc(endpoints.get(paired.getId()), endpoints.get(c.getId()), ArcConnection.Friends);
|
||||
cardsVisualized.add(paired);
|
||||
@@ -475,8 +470,8 @@ public class TargetingOverlay {
|
||||
if (!attackingCard.equals(c) && !blockingCard.equals(c)) { continue; }
|
||||
addArc(endpoints.get(attackingCard.getId()), endpoints.get(blockingCard.getId()), ArcConnection.FoesBlocking);
|
||||
cardsVisualized.add(blockingCard);
|
||||
cardsVisualized.add(attackingCard);
|
||||
}
|
||||
cardsVisualized.add(attackingCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package forge.screens.match;
|
||||
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.view.arcane.FloatingCardArea;
|
||||
import forge.view.arcane.FloatingZone;
|
||||
|
||||
/**
|
||||
* Receives click and programmatic requests for viewing data stacks in the
|
||||
@@ -27,6 +27,6 @@ public final class ZoneAction implements Runnable {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
FloatingCardArea.showOrHide(matchUI, player, zone);
|
||||
FloatingZone.showOrHide(matchUI, player, zone);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import forge.gui.framework.DragTab;
|
||||
import forge.gui.framework.EDocID;
|
||||
import forge.gui.framework.IVDoc;
|
||||
import forge.screens.match.controllers.CStack;
|
||||
import forge.screens.match.controllers.CDock.ArcState;
|
||||
import forge.toolbox.FMouseAdapter;
|
||||
import forge.toolbox.FScrollPanel;
|
||||
import forge.toolbox.FSkin;
|
||||
@@ -194,19 +195,45 @@ public class VStack implements IVDoc<CStack> {
|
||||
setFont(FSkin.getFont());
|
||||
setWrapStyleWord(true);
|
||||
setMinimumSize(new Dimension(CARD_WIDTH + 2 * PADDING, CARD_HEIGHT + 2 * PADDING));
|
||||
|
||||
// if the top of the stack is not assigned yet...
|
||||
if (hoveredItem == null)
|
||||
{
|
||||
// set things up to draw an arc from it...
|
||||
hoveredItem = StackInstanceTextArea.this;
|
||||
controller.getMatchUI().setCard(item.getSourceCard());
|
||||
}
|
||||
|
||||
addMouseListener(new MouseAdapter() {
|
||||
@Override
|
||||
public void mouseEntered(final MouseEvent e) {
|
||||
hoveredItem = StackInstanceTextArea.this;
|
||||
controller.getMatchUI().setCard(item.getSourceCard());
|
||||
if (controller.getMatchUI().getCDock().getArcState() == ArcState.MOUSEOVER) {
|
||||
hoveredItem = StackInstanceTextArea.this;
|
||||
controller.getMatchUI().setCard(item.getSourceCard());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(final MouseEvent e) {
|
||||
if (hoveredItem == StackInstanceTextArea.this) {
|
||||
hoveredItem = null;
|
||||
}
|
||||
if (controller.getMatchUI().getCDock().getArcState() == ArcState.MOUSEOVER) {
|
||||
if (hoveredItem == StackInstanceTextArea.this) {
|
||||
hoveredItem = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(final MouseEvent e) {
|
||||
if (controller.getMatchUI().getCDock().getArcState() == ArcState.ON) {
|
||||
if (hoveredItem == StackInstanceTextArea.this) {
|
||||
hoveredItem = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
hoveredItem = StackInstanceTextArea.this;
|
||||
controller.getMatchUI().setCard(item.getSourceCard());
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
package forge.util;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
public class SwingImageFetcher extends ImageFetcher {
|
||||
|
||||
@Override
|
||||
protected Runnable getDownloadTask(String[] downloadUrls, String destPath, Runnable notifyObservers) {
|
||||
return new SwingDownloadTask(downloadUrls, destPath, notifyObservers);
|
||||
}
|
||||
|
||||
private static class SwingDownloadTask implements Runnable {
|
||||
private final String[] downloadUrls;
|
||||
private final String destPath;
|
||||
private final Runnable notifyObservers;
|
||||
|
||||
public SwingDownloadTask(String[] downloadUrls, String destPath, Runnable notifyObservers) {
|
||||
this.downloadUrls = downloadUrls;
|
||||
this.destPath = destPath;
|
||||
this.notifyObservers = notifyObservers;
|
||||
}
|
||||
|
||||
private void doFetch(String urlToDownload) throws IOException {
|
||||
URL url = new URL(urlToDownload);
|
||||
System.out.println("Attempting to fetch: " + url);
|
||||
java.net.URLConnection c = url.openConnection();
|
||||
c.setRequestProperty("User-Agent", "");
|
||||
BufferedImage image = ImageIO.read(c.getInputStream());
|
||||
// First, save to a temporary file so that nothing tries to read
|
||||
// a partial download.
|
||||
File destFile = new File(destPath + ".tmp");
|
||||
destFile.mkdirs();
|
||||
ImageIO.write(image, "jpg", destFile);
|
||||
// Now, rename it to the correct name.
|
||||
destFile.renameTo(new File(destPath));
|
||||
System.out.println("Saved image to " + destPath);
|
||||
SwingUtilities.invokeLater(notifyObservers);
|
||||
}
|
||||
|
||||
public void run() {
|
||||
for (String urlToDownload : downloadUrls) {
|
||||
try {
|
||||
doFetch(urlToDownload);
|
||||
break;
|
||||
} catch (IOException e) {
|
||||
System.out.println("Failed to download card [" + destPath + "] image: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -246,8 +246,8 @@ public class CardArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
dragPanel.setDisplayEnabled(false);
|
||||
|
||||
CardPanel.setDragAnimationPanel(new CardPanel(dragPanel.getMatchUI(), dragPanel.getCard()));
|
||||
final JFrame frame = (JFrame) SwingUtilities.windowForComponent(this);
|
||||
final JLayeredPane layeredPane = frame.getLayeredPane();
|
||||
final RootPaneContainer frame = (RootPaneContainer) SwingUtilities.windowForComponent(this);
|
||||
final JLayeredPane layeredPane = frame.getLayeredPane();
|
||||
layeredPane.add(CardPanel.getDragAnimationPanel());
|
||||
layeredPane.moveToFront(CardPanel.getDragAnimationPanel());
|
||||
final Point p = SwingUtilities.convertPoint(this, this.mouseDragStartX, this.mouseDragStartY, layeredPane);
|
||||
|
||||
@@ -253,7 +253,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
g2d.rotate(getTappedAngle(), cardXOffset + edgeOffset, (cardYOffset + cardHeight)
|
||||
- edgeOffset);
|
||||
}
|
||||
super.paint(g2d);
|
||||
super.paint(g2d);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -268,12 +268,12 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
final int cornerSize = noBorderPref && !cardImgHasAlpha ? 0 : Math.max(4, Math.round(cardWidth * CardPanel.ROUNDED_CORNER_SIZE));
|
||||
final int offset = isTapped() && (!noBorderPref || cardImgHasAlpha) ? 1 : 0;
|
||||
|
||||
// Magenta outline for when card was chosen to pay
|
||||
// Magenta outline for when card is chosen
|
||||
if (matchUI.isUsedToPay(getCard())) {
|
||||
g2d.setColor(Color.magenta);
|
||||
final int n2 = Math.max(1, Math.round(2 * cardWidth * CardPanel.SELECTED_BORDER_SIZE));
|
||||
g2d.fillRoundRect(cardXOffset - n2, (cardYOffset - n2) + offset, cardWidth + (n2 * 2), cardHeight + (n2 * 2), cornerSize + n2, cornerSize + n2);
|
||||
}
|
||||
}
|
||||
|
||||
// Green outline for hover
|
||||
if (isSelected) {
|
||||
@@ -282,7 +282,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
g2d.fillRoundRect(cardXOffset - n, (cardYOffset - n) + offset, cardWidth + (n * 2), cardHeight + (n * 2), cornerSize + n , cornerSize + n);
|
||||
}
|
||||
|
||||
// Black fill - (will become outline for white bordered cards)
|
||||
// Black fill - (will become an outline for white bordered cards)
|
||||
g2d.setColor(Color.black);
|
||||
g2d.fillRoundRect(cardXOffset, cardYOffset + offset, cardWidth, cardHeight, cornerSize, cornerSize);
|
||||
|
||||
@@ -305,6 +305,12 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
g2d.fillRoundRect(cardXOffset + ins, cardYOffset + ins, cardWidth - ins*2, cardHeight - ins*2, cornerSize-ins, cornerSize-ins);
|
||||
}
|
||||
}
|
||||
|
||||
if (matchUI.isSelectable(getCard())) { // White border for selectable cards to further highlight them
|
||||
g2d.setColor(Color.WHITE);
|
||||
final int ins = 1;
|
||||
g2d.fillRoundRect(cardXOffset+ins, cardYOffset+ins, cardWidth-ins*2, cardHeight-ins*2, cornerSize-ins, cornerSize-ins);
|
||||
}
|
||||
}
|
||||
|
||||
private void drawManaCost(final Graphics g, final ManaCost cost, final int deltaY) {
|
||||
@@ -328,6 +334,17 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
drawFoilEffect(g, card, cardXOffset, cardYOffset,
|
||||
cardWidth, cardHeight, Math.round(cardWidth * BLACK_BORDER_SIZE));
|
||||
}
|
||||
|
||||
boolean nonselectable = matchUI.isSelecting() && !matchUI.isSelectable(getCard());
|
||||
// if selecting, darken non-selectable cards
|
||||
if ( nonselectable ) {
|
||||
boolean noBorderPref = !isPreferenceEnabled(FPref.UI_RENDER_BLACK_BORDERS);
|
||||
boolean cardImgHasAlpha = imagePanel != null && imagePanel.getSrcImage() != null && imagePanel.getSrcImage().getColorModel().hasAlpha();
|
||||
final int cornerSize = noBorderPref && !cardImgHasAlpha ? 0 : Math.max(4, Math.round(cardWidth * CardPanel.ROUNDED_CORNER_SIZE));
|
||||
final int offset = isTapped() && (!noBorderPref || cardImgHasAlpha) ? 1 : 0;
|
||||
g.setColor(new Color(0.0f,0.0f,0.0f,0.6f));
|
||||
g.fillRoundRect(cardXOffset, cardYOffset + offset, cardWidth, cardHeight, cornerSize, cornerSize);
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawFoilEffect(final Graphics g, final CardView card2, final int x, final int y, final int width, final int height, final int borderSize) {
|
||||
@@ -779,6 +796,7 @@ public class CardPanel extends SkinnedPanel implements CardContainer, IDisposabl
|
||||
return FModel.getPreferences().getPrefBoolean(preferenceName);
|
||||
}
|
||||
|
||||
// don't show overlays on non-selectable cards when selecting
|
||||
private boolean isShowingOverlays() {
|
||||
return isPreferenceEnabled(FPref.UI_SHOW_CARD_OVERLAYS) && card != null;
|
||||
}
|
||||
|
||||
@@ -182,6 +182,10 @@ public abstract class CardPanelContainer extends SkinnedPanel {
|
||||
});
|
||||
}
|
||||
|
||||
protected boolean cardPanelDraggable(final CardPanel panel) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private MouseMotionListener setupMotionMouseListener() {
|
||||
final MouseMotionListener mml = new MouseMotionListener() {
|
||||
@Override
|
||||
@@ -207,20 +211,23 @@ public abstract class CardPanelContainer extends SkinnedPanel {
|
||||
if (panel != mouseDownPanel) {
|
||||
return;
|
||||
}
|
||||
if (intialMouseDragX == -1) {
|
||||
intialMouseDragX = x;
|
||||
intialMouseDragY = y;
|
||||
return;
|
||||
}
|
||||
if ((Math.abs(x - intialMouseDragX) < CardPanelContainer.DRAG_SMUDGE)
|
||||
|
||||
if (cardPanelDraggable(panel)) { // allow for non-draggable cards
|
||||
if (intialMouseDragX == -1) {
|
||||
intialMouseDragX = x;
|
||||
intialMouseDragY = y;
|
||||
return;
|
||||
}
|
||||
if ((Math.abs(x - intialMouseDragX) < CardPanelContainer.DRAG_SMUDGE)
|
||||
&& (Math.abs(y - intialMouseDragY) < CardPanelContainer.DRAG_SMUDGE)) {
|
||||
return;
|
||||
}
|
||||
mouseDownPanel = null;
|
||||
setMouseDragPanel(panel);
|
||||
mouseDragOffsetX = panel.getX() - intialMouseDragX;
|
||||
mouseDragOffsetY = panel.getY() - intialMouseDragY;
|
||||
mouseDragStart(getMouseDragPanel(), evt);
|
||||
return;
|
||||
}
|
||||
mouseDownPanel = null;
|
||||
setMouseDragPanel(panel);
|
||||
mouseDragOffsetX = panel.getX() - intialMouseDragX;
|
||||
mouseDragOffsetY = panel.getY() - intialMouseDragY;
|
||||
mouseDragStart(getMouseDragPanel(), evt);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -284,6 +291,10 @@ public abstract class CardPanelContainer extends SkinnedPanel {
|
||||
}
|
||||
|
||||
public final void removeCardPanel(final CardPanel fromPanel) {
|
||||
removeCardPanel(fromPanel,true);
|
||||
}
|
||||
|
||||
public final void removeCardPanel(final CardPanel fromPanel, final boolean repaint) {
|
||||
FThreads.assertExecutedByEdt(true);
|
||||
if (getMouseDragPanel() != null) {
|
||||
CardPanel.getDragAnimationPanel().setVisible(false);
|
||||
@@ -296,9 +307,11 @@ public abstract class CardPanelContainer extends SkinnedPanel {
|
||||
fromPanel.dispose();
|
||||
getCardPanels().remove(fromPanel);
|
||||
remove(fromPanel);
|
||||
invalidate();
|
||||
repaint();
|
||||
doingLayout();
|
||||
if ( repaint ) {
|
||||
invalidate();
|
||||
repaint();
|
||||
doingLayout();
|
||||
}
|
||||
}
|
||||
|
||||
public final void setCardPanels(final List<CardPanel> cardPanels) {
|
||||
@@ -318,23 +331,28 @@ public abstract class CardPanelContainer extends SkinnedPanel {
|
||||
for (final CardPanel cardPanel : cardPanels) {
|
||||
this.add(cardPanel);
|
||||
}
|
||||
this.doLayout();
|
||||
//pfps the validate just below will do the layout, so don't do it here this.doLayout();
|
||||
this.invalidate();
|
||||
this.getParent().validate();
|
||||
this.repaint();
|
||||
}
|
||||
|
||||
public final void clear() {
|
||||
clear(true);
|
||||
}
|
||||
public final void clear(final boolean repaint) {
|
||||
FThreads.assertExecutedByEdt(true);
|
||||
for (final CardPanel p : getCardPanels()) {
|
||||
p.dispose();
|
||||
}
|
||||
getCardPanels().clear();
|
||||
removeAll();
|
||||
setPreferredSize(new Dimension(0, 0));
|
||||
invalidate();
|
||||
getParent().validate();
|
||||
repaint();
|
||||
if ( repaint ) {
|
||||
setPreferredSize(new Dimension(0, 0));
|
||||
invalidate();
|
||||
getParent().validate();
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
public final FScrollPane getScrollPane() {
|
||||
@@ -453,4 +471,4 @@ public abstract class CardPanelContainer extends SkinnedPanel {
|
||||
this.layoutListeners.add(listener);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,25 +17,20 @@
|
||||
*/
|
||||
package forge.view.arcane;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.Timer;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.gui.framework.SDisplayUtil;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgePreferences;
|
||||
@@ -43,87 +38,66 @@ import forge.properties.ForgePreferences.FPref;
|
||||
import forge.screens.match.CMatchUI;
|
||||
import forge.toolbox.FMouseAdapter;
|
||||
import forge.toolbox.FScrollPane;
|
||||
import forge.toolbox.FSkin;
|
||||
import forge.toolbox.MouseTriggerEvent;
|
||||
import forge.util.collect.FCollectionView;
|
||||
import forge.util.Lang;
|
||||
//import forge.util.collect.FCollectionView;
|
||||
import forge.view.FDialog;
|
||||
import forge.view.FFrame;
|
||||
|
||||
public class FloatingCardArea extends CardArea {
|
||||
private static final long serialVersionUID = 1927906492186378596L;
|
||||
// show some cards in a new window
|
||||
public abstract class FloatingCardArea extends CardArea {
|
||||
|
||||
private static final String COORD_DELIM = ",";
|
||||
protected static final String COORD_DELIM = ",";
|
||||
protected static final ForgePreferences prefs = FModel.getPreferences();
|
||||
|
||||
private static final ForgePreferences prefs = FModel.getPreferences();
|
||||
private static final Map<Integer, FloatingCardArea> floatingAreas = new HashMap<Integer, FloatingCardArea>();
|
||||
protected String title;
|
||||
protected FPref locPref;
|
||||
protected boolean hasBeenShown, locLoaded;
|
||||
|
||||
private static int getKey(final PlayerView player, final ZoneType zone) {
|
||||
return 40 * player.getId() + zone.hashCode();
|
||||
}
|
||||
public static void showOrHide(final CMatchUI matchUI, final PlayerView player, final ZoneType zone) {
|
||||
final FloatingCardArea cardArea = _init(matchUI, player, zone);
|
||||
cardArea.showOrHideWindow();
|
||||
}
|
||||
public static void show(final CMatchUI matchUI, final PlayerView player, final ZoneType zone) {
|
||||
final FloatingCardArea cardArea = _init(matchUI, player, zone);
|
||||
cardArea.showWindow();
|
||||
}
|
||||
private static FloatingCardArea _init(final CMatchUI matchUI, final PlayerView player, final ZoneType zone) {
|
||||
final int key = getKey(player, zone);
|
||||
FloatingCardArea cardArea = floatingAreas.get(key);
|
||||
if (cardArea == null || cardArea.getMatchUI() != matchUI) {
|
||||
cardArea = new FloatingCardArea(matchUI, player, zone);
|
||||
floatingAreas.put(key, cardArea);
|
||||
} else {
|
||||
cardArea.setPlayer(player); //ensure player is updated if needed
|
||||
}
|
||||
return cardArea;
|
||||
}
|
||||
public static CardPanel getCardPanel(final CMatchUI matchUI, final CardView card) {
|
||||
final FloatingCardArea window = _init(matchUI, card.getController(), card.getZone());
|
||||
return window.getCardPanel(card.getId());
|
||||
}
|
||||
public static void refresh(final PlayerView player, final ZoneType zone) {
|
||||
FloatingCardArea cardArea = floatingAreas.get(getKey(player, zone));
|
||||
if (cardArea != null) {
|
||||
cardArea.setPlayer(player); //ensure player is updated if needed
|
||||
cardArea.refresh();
|
||||
}
|
||||
protected abstract Iterable<CardView> getCards();
|
||||
|
||||
//refresh flashback zone when graveyard, library, or exile zones updated
|
||||
switch (zone) {
|
||||
case Graveyard:
|
||||
case Library:
|
||||
case Exile:
|
||||
refresh(player, ZoneType.Flashback);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
protected FloatingCardArea(final CMatchUI matchUI) {
|
||||
this(matchUI, new FScrollPane(false, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER));
|
||||
}
|
||||
protected FloatingCardArea(final CMatchUI matchUI, final FScrollPane scrollPane) {
|
||||
super(matchUI, scrollPane);
|
||||
}
|
||||
|
||||
protected void showWindow() {
|
||||
onShow();
|
||||
getWindow().setFocusableWindowState(false); // should probably do this earlier
|
||||
getWindow().setVisible(true);
|
||||
}
|
||||
protected void hideWindow() {
|
||||
onShow();
|
||||
getWindow().setFocusableWindowState(false); // should probably do this earlier
|
||||
getWindow().setVisible(false);
|
||||
getWindow().dispose(); //pfps so that old content does not show up
|
||||
}
|
||||
protected void showOrHideWindow() {
|
||||
if (getWindow().isVisible()) {
|
||||
hideWindow();
|
||||
} else {
|
||||
showWindow();
|
||||
}
|
||||
}
|
||||
protected void onShow() {
|
||||
if (!hasBeenShown) {
|
||||
loadLocation();
|
||||
getWindow().getTitleBar().addMouseListener(new FMouseAdapter() {
|
||||
@Override public final void onLeftDoubleClick(final MouseEvent e) {
|
||||
getWindow().setVisible(false); //hide window if titlebar double-clicked
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
public static void closeAll() {
|
||||
for (final FloatingCardArea cardArea : floatingAreas.values()) {
|
||||
cardArea.window.setVisible(false);
|
||||
}
|
||||
floatingAreas.clear();
|
||||
}
|
||||
|
||||
private final ZoneType zone;
|
||||
private PlayerView player;
|
||||
private String title;
|
||||
private FPref locPref;
|
||||
private boolean hasBeenShown, locLoaded;
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private final FDialog window = new FDialog(false, true, "0") {
|
||||
protected final FDialog window = new FDialog(false, true, "0") {
|
||||
@Override
|
||||
public void setLocationRelativeTo(Component c) {
|
||||
//don't change location this way if dialog has already been shown or location was loaded from preferences
|
||||
if (hasBeenShown || locLoaded) { return; }
|
||||
super.setLocationRelativeTo(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setVisible(boolean b0) {
|
||||
if (isVisible() == b0) { return; }
|
||||
@@ -134,94 +108,19 @@ public class FloatingCardArea extends CardArea {
|
||||
getWidth() + COORD_DELIM + getHeight());
|
||||
//don't call prefs.save(), instead allowing them to be saved when match ends
|
||||
}
|
||||
super.setVisible(b0);
|
||||
if (b0) {
|
||||
refresh();
|
||||
doRefresh(); // force a refresh before showing to pick up any changes when hidden
|
||||
hasBeenShown = true;
|
||||
}
|
||||
}
|
||||
super.setVisible(b0);
|
||||
}
|
||||
};
|
||||
|
||||
private FloatingCardArea(final CMatchUI matchUI, final PlayerView player0, final ZoneType zone0) {
|
||||
super(matchUI, new FScrollPane(false, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER));
|
||||
window.add(getScrollPane(), "grow, push");
|
||||
getScrollPane().setViewportView(this);
|
||||
setOpaque(false);
|
||||
switch (zone0) {
|
||||
case Exile:
|
||||
window.setIconImage(FSkin.getImage(FSkinProp.IMG_ZONE_EXILE));
|
||||
break;
|
||||
case Graveyard:
|
||||
window.setIconImage(FSkin.getImage(FSkinProp.IMG_ZONE_GRAVEYARD));
|
||||
break;
|
||||
case Hand:
|
||||
window.setIconImage(FSkin.getImage(FSkinProp.IMG_ZONE_HAND));
|
||||
break;
|
||||
case Library:
|
||||
window.setIconImage(FSkin.getImage(FSkinProp.IMG_ZONE_LIBRARY));
|
||||
break;
|
||||
case Flashback:
|
||||
window.setIconImage(FSkin.getImage(FSkinProp.IMG_ZONE_FLASHBACK));
|
||||
break;
|
||||
default:
|
||||
locPref = null;
|
||||
break;
|
||||
}
|
||||
zone = zone0;
|
||||
setPlayer(player0);
|
||||
setVertical(true);
|
||||
protected FDialog getWindow() {
|
||||
return window;
|
||||
}
|
||||
|
||||
private void setPlayer(PlayerView player0) {
|
||||
if (player == player0) { return; }
|
||||
player = player0;
|
||||
title = Lang.getPossessedObject(player0.getName(), zone.name()) + " (%d)";
|
||||
|
||||
boolean isAi = player0.isAI();
|
||||
switch (zone) {
|
||||
case Exile:
|
||||
locPref = isAi ? FPref.ZONE_LOC_AI_EXILE : FPref.ZONE_LOC_HUMAN_EXILE;
|
||||
break;
|
||||
case Graveyard:
|
||||
locPref = isAi ? FPref.ZONE_LOC_AI_GRAVEYARD : FPref.ZONE_LOC_HUMAN_GRAVEYARD;
|
||||
break;
|
||||
case Hand:
|
||||
locPref = isAi ? FPref.ZONE_LOC_AI_HAND : FPref.ZONE_LOC_HUMAN_HAND;
|
||||
break;
|
||||
case Library:
|
||||
locPref = isAi ? FPref.ZONE_LOC_AI_LIBRARY : FPref.ZONE_LOC_HUMAN_LIBRARY;
|
||||
break;
|
||||
case Flashback:
|
||||
locPref = isAi ? FPref.ZONE_LOC_AI_FLASHBACK : FPref.ZONE_LOC_HUMAN_FLASHBACK;
|
||||
break;
|
||||
default:
|
||||
locPref = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void showWindow() {
|
||||
onShow();
|
||||
window.setFocusableWindowState(false); // should probably do this earlier
|
||||
window.setVisible(true);
|
||||
}
|
||||
private void showOrHideWindow() {
|
||||
onShow();
|
||||
window.setFocusableWindowState(false); // should probably do this earlier
|
||||
window.setVisible(!window.isVisible());
|
||||
}
|
||||
private void onShow() {
|
||||
if (!hasBeenShown) {
|
||||
loadLocation();
|
||||
window.getTitleBar().addMouseListener(new FMouseAdapter() {
|
||||
@Override public final void onLeftDoubleClick(final MouseEvent e) {
|
||||
window.setVisible(false); //hide window if titlebar double-clicked
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void loadLocation() {
|
||||
protected void loadLocation() {
|
||||
if (locPref != null) {
|
||||
String value = prefs.getPref(locPref);
|
||||
if (value.length() > 0) {
|
||||
@@ -255,7 +154,7 @@ public class FloatingCardArea extends CardArea {
|
||||
y = screenBounds.y;
|
||||
}
|
||||
}
|
||||
window.setBounds(x, y, w, h);
|
||||
getWindow().setBounds(x, y, w, h);
|
||||
locLoaded = true;
|
||||
return;
|
||||
}
|
||||
@@ -269,14 +168,17 @@ public class FloatingCardArea extends CardArea {
|
||||
}
|
||||
//fallback default size
|
||||
FFrame mainFrame = Singletons.getView().getFrame();
|
||||
window.setSize(mainFrame.getWidth() / 5, mainFrame.getHeight() / 2);
|
||||
getWindow().setSize(mainFrame.getWidth() / 5, mainFrame.getHeight() / 2);
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
if (!window.isVisible()) { return; } //don't refresh while window hidden
|
||||
protected void refresh() {
|
||||
if (!getWindow().isVisible()) { return; } //don't refresh while window hidden
|
||||
doRefresh();
|
||||
}
|
||||
|
||||
protected void doRefresh() {
|
||||
List<CardPanel> cardPanels = new ArrayList<CardPanel>();
|
||||
FCollectionView<CardView> cards = player.getCards(zone);
|
||||
Iterable<CardView> cards = getCards();
|
||||
if (cards != null) {
|
||||
for (final CardView card : cards) {
|
||||
CardPanel cardPanel = getCardPanel(card.getId());
|
||||
@@ -293,27 +195,27 @@ public class FloatingCardArea extends CardArea {
|
||||
|
||||
boolean hadCardPanels = getCardPanels().size() > 0;
|
||||
setCardPanels(cardPanels);
|
||||
window.setTitle(String.format(title, cardPanels.size()));
|
||||
getWindow().setTitle(String.format(title, cardPanels.size()));
|
||||
|
||||
//if window had cards and now doesn't, hide window
|
||||
//(e.g. cast final card from Flashback zone)
|
||||
if (hadCardPanels && cardPanels.size() == 0) {
|
||||
window.setVisible(false);
|
||||
}
|
||||
//pfps - rather suspect, so commented out for now
|
||||
// //if window had cards and now doesn't, hide window
|
||||
// //(e.g. cast final card from Flashback zone)
|
||||
// if (hadCardPanels && cardPanels.size() == 0) {
|
||||
// getWindow().setVisible(false);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doLayout() {
|
||||
if (window.isResizing()) {
|
||||
if (getWindow().isResizing()) {
|
||||
//delay layout slightly to reduce flicker during window resize
|
||||
layoutTimer.restart();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
finishDoLayout();
|
||||
}
|
||||
}
|
||||
|
||||
private final Timer layoutTimer = new Timer(250, new ActionListener() {
|
||||
protected final Timer layoutTimer = new Timer(250, new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent arg0) {
|
||||
layoutTimer.stop();
|
||||
@@ -321,7 +223,7 @@ public class FloatingCardArea extends CardArea {
|
||||
}
|
||||
});
|
||||
|
||||
private void finishDoLayout() {
|
||||
protected void finishDoLayout() {
|
||||
super.doLayout();
|
||||
}
|
||||
|
||||
@@ -331,12 +233,12 @@ public class FloatingCardArea extends CardArea {
|
||||
super.mouseOver(panel, evt);
|
||||
}
|
||||
@Override
|
||||
public final void mouseLeftClicked(final CardPanel panel, final MouseEvent evt) {
|
||||
public void mouseLeftClicked(final CardPanel panel, final MouseEvent evt) {
|
||||
getMatchUI().getGameController().selectCard(panel.getCard(), null, new MouseTriggerEvent(evt));
|
||||
super.mouseLeftClicked(panel, evt);
|
||||
}
|
||||
@Override
|
||||
public final void mouseRightClicked(final CardPanel panel, final MouseEvent evt) {
|
||||
public void mouseRightClicked(final CardPanel panel, final MouseEvent evt) {
|
||||
getMatchUI().getGameController().selectCard(panel.getCard(), null, new MouseTriggerEvent(evt));
|
||||
super.mouseRightClicked(panel, evt);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Nate
|
||||
*
|
||||
* 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.view.arcane;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
|
||||
import java.awt.event.MouseEvent;
|
||||
import javax.swing.ScrollPaneConstants;
|
||||
import javax.swing.WindowConstants;
|
||||
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.game.card.CardView;
|
||||
import forge.game.player.PlayerView;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.properties.ForgePreferences.FPref;
|
||||
import forge.screens.match.CMatchUI;
|
||||
import forge.toolbox.FScrollPane;
|
||||
import forge.toolbox.FMouseAdapter;
|
||||
import forge.toolbox.FSkin;
|
||||
import forge.util.Lang;
|
||||
import forge.util.collect.FCollection;
|
||||
|
||||
public class FloatingZone extends FloatingCardArea {
|
||||
private static final long serialVersionUID = 1927906492186378596L;
|
||||
|
||||
private static final Map<Integer, FloatingZone> floatingAreas = new HashMap<Integer, FloatingZone>();
|
||||
|
||||
private static int getKey(final PlayerView player, final ZoneType zone) {
|
||||
return 40 * player.getId() + zone.hashCode();
|
||||
}
|
||||
public static void showOrHide(final CMatchUI matchUI, final PlayerView player, final ZoneType zone) {
|
||||
final FloatingZone cardArea = _init(matchUI, player, zone);
|
||||
cardArea.showOrHideWindow();
|
||||
}
|
||||
public static void show(final CMatchUI matchUI, final PlayerView player, final ZoneType zone) {
|
||||
final FloatingZone cardArea = _init(matchUI, player, zone);
|
||||
cardArea.showWindow();
|
||||
}
|
||||
public static void hide(final CMatchUI matchUI, final PlayerView player, final ZoneType zone) {
|
||||
final FloatingZone cardArea = _init(matchUI, player, zone);
|
||||
cardArea.hideWindow();
|
||||
}
|
||||
private static FloatingZone _init(final CMatchUI matchUI, final PlayerView player, final ZoneType zone) {
|
||||
final int key = getKey(player, zone);
|
||||
FloatingZone cardArea = floatingAreas.get(key);
|
||||
if (cardArea == null || cardArea.getMatchUI() != matchUI) {
|
||||
cardArea = new FloatingZone(matchUI, player, zone);
|
||||
floatingAreas.put(key, cardArea);
|
||||
} else {
|
||||
cardArea.setPlayer(player); //ensure player is updated if needed
|
||||
}
|
||||
return cardArea;
|
||||
}
|
||||
public static CardPanel getCardPanel(final CMatchUI matchUI, final CardView card) {
|
||||
final FloatingZone window = _init(matchUI, card.getController(), card.getZone());
|
||||
return window.getCardPanel(card.getId());
|
||||
}
|
||||
public static void refresh(final PlayerView player, final ZoneType zone) {
|
||||
FloatingZone cardArea = floatingAreas.get(getKey(player, zone));
|
||||
if (cardArea != null) {
|
||||
cardArea.setPlayer(player); //ensure player is updated if needed
|
||||
cardArea.refresh();
|
||||
}
|
||||
|
||||
//refresh flashback zone when graveyard, library, or exile zones updated
|
||||
switch (zone) {
|
||||
case Graveyard:
|
||||
case Library:
|
||||
case Exile:
|
||||
refresh(player, ZoneType.Flashback);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
public static void closeAll() {
|
||||
for (final FloatingZone cardArea : floatingAreas.values()) {
|
||||
cardArea.window.setVisible(false);
|
||||
}
|
||||
floatingAreas.clear();
|
||||
}
|
||||
public static void refreshAll() {
|
||||
for (final FloatingZone cardArea : floatingAreas.values()) {
|
||||
cardArea.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
private final ZoneType zone;
|
||||
private PlayerView player;
|
||||
|
||||
protected boolean sortedByName = false;
|
||||
protected FCollection<CardView> cardList;
|
||||
|
||||
private final Comparator<CardView> comp = new Comparator<CardView>() {
|
||||
@Override
|
||||
public int compare(CardView lhs, CardView rhs) {
|
||||
if ( !getMatchUI().mayView(lhs) ) {
|
||||
return ( getMatchUI().mayView(rhs) ) ? 1 : 0 ;
|
||||
} else if ( !getMatchUI().mayView(rhs) ) {
|
||||
return -1;
|
||||
} else {
|
||||
return lhs.getName().compareTo(rhs.getName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
protected Iterable<CardView> getCards() {
|
||||
Iterable<CardView> zoneCards = player.getCards(zone);
|
||||
if ( zoneCards != null ) {
|
||||
cardList = new FCollection<CardView>(zoneCards);
|
||||
if ( sortedByName ) {
|
||||
Collections.sort(cardList, comp);
|
||||
}
|
||||
return cardList;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private FloatingZone(final CMatchUI matchUI, final PlayerView player0, final ZoneType zone0) {
|
||||
super(matchUI, new FScrollPane(false, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER));
|
||||
window.add(getScrollPane(), "grow, push");
|
||||
window.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); //pfps so that old content does not reappear?
|
||||
getScrollPane().setViewportView(this);
|
||||
setOpaque(false);
|
||||
switch (zone0) {
|
||||
case Exile:
|
||||
window.setIconImage(FSkin.getImage(FSkinProp.IMG_ZONE_EXILE));
|
||||
break;
|
||||
case Graveyard:
|
||||
window.setIconImage(FSkin.getImage(FSkinProp.IMG_ZONE_GRAVEYARD));
|
||||
break;
|
||||
case Hand:
|
||||
window.setIconImage(FSkin.getImage(FSkinProp.IMG_ZONE_HAND));
|
||||
break;
|
||||
case Library:
|
||||
window.setIconImage(FSkin.getImage(FSkinProp.IMG_ZONE_LIBRARY));
|
||||
break;
|
||||
case Flashback:
|
||||
window.setIconImage(FSkin.getImage(FSkinProp.IMG_ZONE_FLASHBACK));
|
||||
break;
|
||||
default:
|
||||
locPref = null;
|
||||
break;
|
||||
}
|
||||
zone = zone0;
|
||||
setPlayer(player0);
|
||||
setVertical(true);
|
||||
}
|
||||
|
||||
private void toggleSorted() {
|
||||
sortedByName = !sortedByName;
|
||||
setTitle();
|
||||
refresh();
|
||||
// revalidation does not appear to be necessary here
|
||||
getWindow().repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShow() {
|
||||
super.onShow();
|
||||
if (!hasBeenShown) {
|
||||
getWindow().getTitleBar().addMouseListener(new FMouseAdapter() {
|
||||
@Override public final void onRightClick(final MouseEvent e) {
|
||||
toggleSorted();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void setTitle() {
|
||||
title = Lang.getPossessedObject(player.getName(), zone.name()) + " (%d)" +
|
||||
( sortedByName ? " - sorted by name (right click in title to not sort)" : " (right click in title to sort)" ) ;
|
||||
}
|
||||
|
||||
private void setPlayer(PlayerView player0) {
|
||||
if (player == player0) { return; }
|
||||
player = player0;
|
||||
setTitle();
|
||||
|
||||
boolean isAi = player0.isAI();
|
||||
switch (zone) {
|
||||
case Exile:
|
||||
locPref = isAi ? FPref.ZONE_LOC_AI_EXILE : FPref.ZONE_LOC_HUMAN_EXILE;
|
||||
break;
|
||||
case Graveyard:
|
||||
locPref = isAi ? FPref.ZONE_LOC_AI_GRAVEYARD : FPref.ZONE_LOC_HUMAN_GRAVEYARD;
|
||||
break;
|
||||
case Hand:
|
||||
locPref = isAi ? FPref.ZONE_LOC_AI_HAND : FPref.ZONE_LOC_HUMAN_HAND;
|
||||
break;
|
||||
case Library:
|
||||
locPref = isAi ? FPref.ZONE_LOC_AI_LIBRARY : FPref.ZONE_LOC_HUMAN_LIBRARY;
|
||||
break;
|
||||
case Flashback:
|
||||
locPref = isAi ? FPref.ZONE_LOC_AI_FLASHBACK : FPref.ZONE_LOC_HUMAN_FLASHBACK;
|
||||
break;
|
||||
default:
|
||||
locPref = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
*
|
||||
* 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.view.arcane;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import forge.game.card.CardView;
|
||||
import forge.screens.match.CMatchUI;
|
||||
import forge.view.arcane.util.CardPanelMouseAdapter;
|
||||
|
||||
import forge.toolbox.FButton;
|
||||
|
||||
// Show a list of cards in a new window, containing the moveable cards
|
||||
// Allow moves of the moveable cards to top, to bottom, or anywhere
|
||||
// Return a list of cards with the results of the moves
|
||||
// Really should have a difference between visible cards and moveable cards,
|
||||
// but that would require consirable changes to card panels and elsewhere
|
||||
public class ListCardArea extends FloatingCardArea {
|
||||
|
||||
private static ArrayList<CardView> cardList;
|
||||
private static ArrayList<CardView> moveableCards;
|
||||
|
||||
private static ListCardArea storedArea;
|
||||
private static FButton doneButton;
|
||||
private boolean toTop, toBottom, toAnywhere;
|
||||
|
||||
private ListCardArea(final CMatchUI matchUI) {
|
||||
super(matchUI);
|
||||
window.add(getScrollPane(),"grow, push");
|
||||
window.setModal(true);
|
||||
getScrollPane().setViewportView(this);
|
||||
doneButton = new FButton("Done");
|
||||
doneButton.addActionListener(new ActionListener() {
|
||||
@Override public void actionPerformed(ActionEvent e) { window.setVisible(false); }
|
||||
});
|
||||
window.add(doneButton,BorderLayout.SOUTH);
|
||||
setOpaque(false);
|
||||
}
|
||||
|
||||
public static ListCardArea show(final CMatchUI matchUI, final String title0, final Iterable<CardView> cardList0, final Iterable<CardView> moveableCards0, final boolean toTop0, final boolean toBottom0, final boolean toAnywhere0) {
|
||||
if (storedArea==null) {
|
||||
storedArea = new ListCardArea(matchUI);
|
||||
}
|
||||
cardList = new ArrayList<CardView>();
|
||||
for ( CardView cv : cardList0 ) { cardList.add(cv) ; }
|
||||
moveableCards = new ArrayList<CardView>(); // make sure moveable cards are in cardlist
|
||||
for ( CardView card : moveableCards0 ) {
|
||||
if ( cardList.contains(card) ) {
|
||||
moveableCards.add(card);
|
||||
}
|
||||
}
|
||||
storedArea.title = title0;
|
||||
storedArea.toTop = toTop0;
|
||||
storedArea.toBottom = toBottom0;
|
||||
storedArea.toAnywhere = toAnywhere0;
|
||||
storedArea.setDragEnabled(true);
|
||||
storedArea.setVertical(true);
|
||||
storedArea.showWindow();
|
||||
return storedArea;
|
||||
}
|
||||
|
||||
public ListCardArea(final CMatchUI matchUI, final String title0, final List<CardView> cardList0, final List<CardView> moveableCards0, final boolean toTop0, final boolean toBottom0, final boolean toAnywhere0) {
|
||||
super(matchUI);
|
||||
window.add(getScrollPane(),"grow, push");
|
||||
getScrollPane().setViewportView(this);
|
||||
setOpaque(false);
|
||||
doneButton = new FButton("Done");
|
||||
doneButton.addActionListener(new ActionListener() {
|
||||
@Override public void actionPerformed(ActionEvent e) { window.setVisible(false); }
|
||||
});
|
||||
window.add(doneButton,BorderLayout.SOUTH);
|
||||
cardList = new ArrayList<CardView>(cardList0); // this is modified - pfps - is there a better way?
|
||||
moveableCards = new ArrayList<CardView>(moveableCards0);
|
||||
title = title0;
|
||||
toTop = toTop0;
|
||||
toBottom = toBottom0;
|
||||
toAnywhere = toAnywhere0;
|
||||
this.setDragEnabled(true);
|
||||
this.setVertical(true);
|
||||
storedArea = this;
|
||||
}
|
||||
|
||||
public List<CardView> getCards() {
|
||||
return cardList;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showWindow() {
|
||||
onShow();
|
||||
getWindow().setFocusableWindowState(true);
|
||||
getWindow().setVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onShow() {
|
||||
super.onShow();
|
||||
if (!hasBeenShown) {
|
||||
this.addCardPanelMouseListener(new CardPanelMouseAdapter() {
|
||||
@Override
|
||||
public void mouseDragEnd(final CardPanel dragPanel, final MouseEvent evt) {
|
||||
dragEnd(dragPanel);
|
||||
}
|
||||
});
|
||||
this.addKeyListener(new KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(final KeyEvent e) {
|
||||
switch (e.getKeyCode()) {
|
||||
case KeyEvent.VK_ENTER:
|
||||
doneButton.doClick();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// is this a valid place to move the card?
|
||||
private boolean validIndex(final CardView card, final int index) {
|
||||
if (toAnywhere) { return true; }
|
||||
int oldIndex = cardList.indexOf(card);
|
||||
boolean topMove = true;
|
||||
for(int i=0; i<index+(oldIndex<index?1:0); i++) {
|
||||
if (!moveableCards.contains(cardList.get(i))) { topMove=false; break; }
|
||||
}
|
||||
if (toTop && topMove) { return true; }
|
||||
boolean bottomMove = true;
|
||||
for(int i=index+1-(oldIndex>index?1:0); i<cardList.size(); i++) {
|
||||
if (!moveableCards.contains(cardList.get(i))) { bottomMove=false; break; }
|
||||
}
|
||||
if (toBottom && bottomMove) { return true; }
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean cardPanelDraggable(final CardPanel panel) {
|
||||
return moveableCards.contains(panel.getCard());
|
||||
}
|
||||
|
||||
private void dragEnd(final CardPanel dragPanel) {
|
||||
// if drag is not allowed, don't move anything
|
||||
final CardView dragCard = dragPanel.getCard();
|
||||
if (moveableCards.contains(dragCard)) {
|
||||
//update index of dragged card in hand zone to match new index within hand area
|
||||
final int index = getCardPanels().indexOf(dragPanel);
|
||||
if (validIndex(dragCard,index)) {
|
||||
synchronized (cardList) {
|
||||
cardList.remove(dragCard);
|
||||
cardList.add(index, dragCard);
|
||||
}
|
||||
}
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
|
||||
// move to beginning of list if allowable else to beginning of bottom if allowable
|
||||
@Override
|
||||
public final void mouseLeftClicked(final CardPanel panel, final MouseEvent evt) {
|
||||
final CardView clickCard = panel.getCard();
|
||||
if ( moveableCards.contains(clickCard) ) {
|
||||
if ( toTop || toBottom ) {
|
||||
synchronized (cardList) {
|
||||
cardList.remove(clickCard);
|
||||
int position;
|
||||
if ( toTop ) {
|
||||
position = 0 ;
|
||||
} else { // to beginning of bottom: warning, untested
|
||||
for ( position = cardList.size() ;
|
||||
position>0 && moveableCards.contains(cardList.get(position-1)) ;
|
||||
position-- );
|
||||
}
|
||||
cardList.add(position,clickCard);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
super.mouseLeftClicked(panel, evt);
|
||||
}
|
||||
@Override
|
||||
public final void mouseRightClicked(final CardPanel panel, final MouseEvent evt) {
|
||||
final CardView clickCard = panel.getCard();
|
||||
if (moveableCards.contains(clickCard)) {
|
||||
if ( toTop || toBottom ) {
|
||||
synchronized (cardList) {
|
||||
cardList.remove(clickCard);
|
||||
int position;
|
||||
if ( toBottom ) {
|
||||
position = cardList.size() ;
|
||||
} else { // to end of top
|
||||
for ( position = 0 ;
|
||||
position<cardList.size() && moveableCards.contains(cardList.get(position)) ;
|
||||
position++ );
|
||||
}
|
||||
cardList.add(position,clickCard);
|
||||
}
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
super.mouseRightClicked(panel, evt);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -106,7 +106,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
final CardStack stack = allLands.get(i);
|
||||
final CardPanel firstPanel = stack.get(0);
|
||||
if (firstPanel.getCard().getCurrentState().getName().equals(state.getName())) {
|
||||
if (!firstPanel.getAttachedPanels().isEmpty() || firstPanel.getCard().isEnchanted()) {
|
||||
if (!firstPanel.getAttachedPanels().isEmpty() || firstPanel.getCard().hasCardAttachments()) {
|
||||
// Put this land to the left of lands with the same name
|
||||
// and attachments.
|
||||
insertIndex = i;
|
||||
@@ -114,7 +114,7 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
}
|
||||
if (!panel.getAttachedPanels().isEmpty()
|
||||
|| !panel.getCard().hasSameCounters(firstPanel.getCard())
|
||||
|| firstPanel.getCard().isEnchanted() || (stack.size() == this.landStackMax)) {
|
||||
|| firstPanel.getCard().hasCardAttachments() || (stack.size() == this.landStackMax)) {
|
||||
// If this land has attachments or the stack is full,
|
||||
// put it to the right.
|
||||
insertIndex = i + 1;
|
||||
@@ -620,11 +620,11 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
toDelete.removeAll(notToDelete);
|
||||
|
||||
if (toDelete.size() == getCardPanels().size()) {
|
||||
clear();
|
||||
clear(false);
|
||||
}
|
||||
else {
|
||||
for (final CardView card : toDelete) {
|
||||
removeCardPanel(getCardPanel(card.getId()));
|
||||
removeCardPanel(getCardPanel(card.getId()),false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -646,19 +646,21 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
needLayoutRefresh = true;
|
||||
}
|
||||
}
|
||||
if (needLayoutRefresh) {
|
||||
doLayout();
|
||||
}
|
||||
if (needLayoutRefresh) {
|
||||
doLayout();
|
||||
}
|
||||
|
||||
invalidate(); //pfps do the extra invalidate before any scrolling
|
||||
if (!newPanels.isEmpty()) {
|
||||
int i = newPanels.size();
|
||||
for (final CardPanel toPanel : newPanels) {
|
||||
scrollRectToVisible(new Rectangle(toPanel.getCardX(), toPanel.getCardY(), toPanel.getCardWidth(), toPanel.getCardHeight()));
|
||||
if ( --i == 0 ) { // only scroll to last panel to be added
|
||||
scrollRectToVisible(new Rectangle(toPanel.getCardX(), toPanel.getCardY(), toPanel.getCardWidth(), toPanel.getCardHeight()));
|
||||
}
|
||||
Animation.moveCard(toPanel);
|
||||
}
|
||||
}
|
||||
|
||||
invalidate();
|
||||
repaint();
|
||||
}
|
||||
repaint();
|
||||
}
|
||||
|
||||
public boolean updateCard(final CardView card, boolean fromRefresh) {
|
||||
@@ -683,8 +685,8 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
}
|
||||
toPanel.getAttachedPanels().clear();
|
||||
|
||||
if (card.isEnchanted()) {
|
||||
final Iterable<CardView> enchants = card.getEnchantedBy();
|
||||
if (card.hasCardAttachments()) {
|
||||
final Iterable<CardView> enchants = card.getAttachedCards();
|
||||
for (final CardView e : enchants) {
|
||||
final CardPanel cardE = getCardPanel(e.getId());
|
||||
if (cardE != null) {
|
||||
@@ -697,43 +699,9 @@ public class PlayArea extends CardPanelContainer implements CardPanelMouseListen
|
||||
}
|
||||
}
|
||||
|
||||
if (card.isEquipped()) {
|
||||
final Iterable<CardView> equips = card.getEquippedBy();
|
||||
for (final CardView e : equips) {
|
||||
final CardPanel cardE = getCardPanel(e.getId());
|
||||
if (cardE != null) {
|
||||
if (cardE.getAttachedToPanel() != toPanel) {
|
||||
cardE.setAttachedToPanel(toPanel);
|
||||
needLayoutRefresh = true; //ensure layout refreshed if any attachments change
|
||||
}
|
||||
toPanel.getAttachedPanels().add(cardE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (card.isFortified()) {
|
||||
final Iterable<CardView> fortifications = card.getFortifiedBy();
|
||||
for (final CardView f : fortifications) {
|
||||
final CardPanel cardE = getCardPanel(f.getId());
|
||||
if (cardE != null) {
|
||||
if (cardE.getAttachedToPanel() != toPanel) {
|
||||
cardE.setAttachedToPanel(toPanel);
|
||||
needLayoutRefresh = true; //ensure layout refreshed if any attachments change
|
||||
}
|
||||
toPanel.getAttachedPanels().add(cardE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CardPanel attachedToPanel;
|
||||
if (card.getEnchantingCard() != null) {
|
||||
attachedToPanel = getCardPanel(card.getEnchantingCard().getId());
|
||||
}
|
||||
else if (card.getEquipping() != null) {
|
||||
attachedToPanel = getCardPanel(card.getEquipping().getId());
|
||||
}
|
||||
else if (card.getFortifying() != null) {
|
||||
attachedToPanel = getCardPanel(card.getFortifying().getId());
|
||||
if (card.getAttachedTo() != null) {
|
||||
attachedToPanel = getCardPanel(card.getAttachedTo().getId());
|
||||
}
|
||||
else {
|
||||
attachedToPanel = null;
|
||||
|
||||
@@ -8,6 +8,7 @@ import forge.game.Game;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
import forge.game.card.CounterType;
|
||||
import forge.game.keyword.Keyword;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
@@ -35,7 +36,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int score = sim.simulateSpellAbility(outlastSA).value;
|
||||
assertTrue(score > 0);
|
||||
assertTrue(score > 0);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
Card heraldCopy = findCardWithName(simGame, heraldCardName);
|
||||
@@ -65,7 +66,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
addCard("Plains", p);
|
||||
addCard("Plains", p);
|
||||
addCard("Spear of Heliod", p);
|
||||
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
game.getAction().checkStateEffects(true);
|
||||
@@ -79,7 +80,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int score = sim.simulateSpellAbility(outlastSA).value;
|
||||
assertTrue(score > 0);
|
||||
assertTrue(score > 0);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
Card sliverCopy = findCardWithName(simGame, sliverCardName);
|
||||
assertEquals(1, sliverCopy.getAmountOfKeyword("Flanking"));
|
||||
@@ -115,7 +116,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card bear = addCard(bearCardName, p);
|
||||
bear.setSickness(false);
|
||||
Card cloak = addCard("Whispersilk Cloak", p);
|
||||
cloak.equipCard(bear);
|
||||
cloak.attachToEntity(bear);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertEquals(1, bear.getAmountOfKeyword("Unblockable"));
|
||||
@@ -133,7 +134,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card bear = addCard(bearCardName, p);
|
||||
bear.setSickness(false);
|
||||
Card lifelink = addCard("Lifelink", p);
|
||||
lifelink.enchantEntity(bear);
|
||||
lifelink.attachToEntity(bear);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertEquals(1, bear.getAmountOfKeyword("Lifelink"));
|
||||
@@ -143,7 +144,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card bearCopy = findCardWithName(simGame, bearCardName);
|
||||
assertEquals(1, bearCopy.getAmountOfKeyword("Lifelink"));
|
||||
}
|
||||
|
||||
|
||||
public void testEtbTriggers() {
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(1);
|
||||
@@ -162,12 +163,12 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int origScore = sim.getScoreForOrigGame().value;
|
||||
int score = sim.simulateSpellAbility(playMerchantSa).value;
|
||||
assertTrue(String.format("score=%d vs. origScore=%d", score, origScore), score > origScore);
|
||||
assertTrue(String.format("score=%d vs. origScore=%d", score, origScore), score > origScore);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
assertEquals(24, simGame.getPlayers().get(1).getLife());
|
||||
assertEquals(16, simGame.getPlayers().get(0).getLife());
|
||||
}
|
||||
|
||||
|
||||
public void testSimulateUnmorph() {
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(1);
|
||||
@@ -179,16 +180,16 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
assertEquals(20, game.getPlayers().get(0).getLife());
|
||||
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
SpellAbility unmorphSA = findSAWithPrefix(ripper, "Morph—Reveal a black card");
|
||||
SpellAbility unmorphSA = findSAWithPrefix(ripper, "Morph — Reveal a black card");
|
||||
assertNotNull(unmorphSA);
|
||||
sim.simulateSpellAbility(unmorphSA);
|
||||
assertEquals(18, simGame.getPlayers().get(0).getLife());
|
||||
}
|
||||
|
||||
|
||||
public void testFindingOwnCard() {
|
||||
Game game = initAndCreateGame();
|
||||
Player p0 = game.getPlayers().get(0);
|
||||
@@ -199,7 +200,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
addCard("Swamp", p1);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p1);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
|
||||
GameSimulator sim = createSimulator(game, p1);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
@@ -210,7 +211,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
assertEquals(1, simGame.getPlayers().get(0).getCardsIn(ZoneType.Hand).size());
|
||||
assertEquals(0, simGame.getPlayers().get(1).getCardsIn(ZoneType.Hand).size());
|
||||
}
|
||||
|
||||
|
||||
public void testPlaneswalkerAbilities() {
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(1);
|
||||
@@ -241,7 +242,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
minusTwoSim.setActivatingPlayer(simP);
|
||||
assertFalse(minusTwoSim.canPlay());
|
||||
assertEquals(1, minusTwoSim.getActivationsThisTurn());
|
||||
|
||||
|
||||
GameCopier copier = new GameCopier(simGame);
|
||||
Game copy = copier.makeCopy();
|
||||
Player copyP = copy.getPlayers().get(1);
|
||||
@@ -290,12 +291,12 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
addCard("Plains", p);
|
||||
Card soulSummons = addCardToZone("Soul Summons", p, ZoneType.Hand);
|
||||
addCardToZone("Ornithopter", p, ZoneType.Library);
|
||||
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
SpellAbility manifestSA = soulSummons.getSpellAbilities().get(0);
|
||||
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
sim.simulateSpellAbility(manifestSA);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
@@ -328,12 +329,12 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
addCard("Plains", p);
|
||||
Card soulSummons = addCardToZone("Soul Summons", p, ZoneType.Hand);
|
||||
addCardToZone("Plains", p, ZoneType.Library);
|
||||
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
SpellAbility manifestSA = soulSummons.getSpellAbilities().get(0);
|
||||
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
sim.simulateSpellAbility(manifestSA);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
@@ -354,12 +355,12 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
addCard("Plains", p);
|
||||
Card soulSummons = addCardToZone("Soul Summons", p, ZoneType.Hand);
|
||||
addCardToZone("Dryad Arbor", p, ZoneType.Library);
|
||||
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
SpellAbility manifestSA = soulSummons.getSpellAbilities().get(0);
|
||||
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
sim.simulateSpellAbility(manifestSA);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
@@ -401,7 +402,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
assertTrue(sarkhanCopy.isCreature());
|
||||
assertFalse(sarkhanCopy.isPlaneswalker());
|
||||
}
|
||||
|
||||
|
||||
public void testDistributeCountersAbility() {
|
||||
String ajaniCardName = "Ajani, Mentor of Heroes";
|
||||
String ornithoperCardName = "Ornithopter";
|
||||
@@ -430,7 +431,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
assertEquals(3, thopterSim.getCounters(CounterType.P1P1) + bearSim.getCounters(CounterType.P1P1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void testDamagePreventedTrigger() {
|
||||
String ajaniCardName = "Ajani Steadfast";
|
||||
String selflessCardName = "Selfless Squire";
|
||||
@@ -446,7 +447,6 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
ajani.addCounter(CounterType.LOYALTY, 8, p, false);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
|
||||
SpellAbility sa = findSAWithPrefix(ajani, "-7:");
|
||||
assertNotNull(sa);
|
||||
@@ -480,7 +480,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertEquals(3, bear.getNetToughness());
|
||||
|
||||
|
||||
GameCopier copier = new GameCopier(game);
|
||||
Game copy = copier.makeCopy();
|
||||
Card bearCopy = findCardWithName(copy, bearCardName);
|
||||
@@ -498,8 +498,9 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertTrue(depths.hasCounters());
|
||||
|
||||
SpellAbility sa = findSAWithPrefix(thespian, "{2}, {T}: CARDNAME becomes a copy of target land and gains this ability.");
|
||||
|
||||
SpellAbility sa = findSAWithPrefix(thespian,
|
||||
"{2}, {T}: CARDNAME becomes a copy of target land and gains this ability.");
|
||||
assertNotNull(sa);
|
||||
sa.getTargets().add(depths);
|
||||
|
||||
@@ -512,7 +513,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
assertNull(strSimGame, findCardWithName(simGame, "Thespian's Stage"));
|
||||
assertNotNull(strSimGame, findCardWithName(simGame, "Marit Lage"));
|
||||
}
|
||||
|
||||
|
||||
public void testThespianStageSelfCopy() {
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(1);
|
||||
@@ -522,8 +523,9 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
assertTrue(thespian.isLand());
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
SpellAbility sa = findSAWithPrefix(thespian, "{2}, {T}: CARDNAME becomes a copy of target land and gains this ability.");
|
||||
|
||||
SpellAbility sa = findSAWithPrefix(thespian,
|
||||
"{2}, {T}: CARDNAME becomes a copy of target land and gains this ability.");
|
||||
assertNotNull(sa);
|
||||
sa.getTargets().add(thespian);
|
||||
|
||||
@@ -551,7 +553,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int score = sim.simulateSpellAbility(dashSA).value;
|
||||
assertTrue(score > 0);
|
||||
assertTrue(score > 0);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
Card berserker = findCardWithName(simGame, berserkerCardName);
|
||||
@@ -559,7 +561,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
assertEquals(1, berserker.getNetPower());
|
||||
assertEquals(1, berserker.getNetToughness());
|
||||
assertFalse(berserker.isSick());
|
||||
|
||||
|
||||
SpellAbility pumpSA = findSAWithPrefix(berserker, "{R}: CARDNAME gets +1/+0 until end of turn.");
|
||||
assertNotNull(pumpSA);
|
||||
GameSimulator sim2 = createSimulator(simGame, (Player) sim.getGameCopier().find(p));
|
||||
@@ -588,7 +590,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int score = sim.simulateSpellAbility(callTheScionsSA).value;
|
||||
assertTrue(score > 0);
|
||||
assertTrue(score > 0);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
Card scion = findCardWithName(simGame, "Eldrazi Scion");
|
||||
@@ -609,8 +611,10 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
}
|
||||
|
||||
public void testMarkedDamage() {
|
||||
// Marked damage is important, as it's used during the AI declare attackers logic
|
||||
// which affects game state score - since P/T boosts are evaluated differently for
|
||||
// Marked damage is important, as it's used during the AI declare
|
||||
// attackers logic
|
||||
// which affects game state score - since P/T boosts are evaluated
|
||||
// differently for
|
||||
// creatures participating in combat.
|
||||
|
||||
Game game = initAndCreateGame();
|
||||
@@ -623,24 +627,24 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
|
||||
assertEquals(3, giant.getNetPower());
|
||||
assertEquals(3, giant.getNetToughness());
|
||||
assertEquals(0, giant.getDamage());
|
||||
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
shockSA.setTargetCard(giant);
|
||||
sim.simulateSpellAbility(shockSA);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
Card simGiant = findCardWithName(simGame, giantCardName);
|
||||
assertEquals(2, simGiant.getDamage());
|
||||
|
||||
|
||||
GameCopier copier = new GameCopier(simGame);
|
||||
Game copy = copier.makeCopy();
|
||||
Card giantCopy = findCardWithName(copy, giantCardName);
|
||||
assertEquals(2, giantCopy.getDamage());
|
||||
}
|
||||
|
||||
|
||||
public void testLifelinkDamageSpell() {
|
||||
Game game = initAndCreateGame();
|
||||
Player p1 = game.getPlayers().get(0);
|
||||
@@ -661,7 +665,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card pridemate = addCard(pridemateName, p1);
|
||||
Card indestructibility = addCard(indestructibilityName, p1);
|
||||
|
||||
indestructibility.enchantEntity(pridemate);
|
||||
indestructibility.attachToEntity(pridemate);
|
||||
|
||||
Card ignition = addCardToZone(ignitionName, p1, ZoneType.Hand);
|
||||
SpellAbility ignitionSA = ignition.getFirstSpellAbility();
|
||||
@@ -681,6 +685,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
// because it was destroyed
|
||||
assertNull(simBrood);
|
||||
assertNotNull(simPridemate);
|
||||
|
||||
assertEquals(0, simKalitas.getDamage());
|
||||
assertEquals(3, simPridemate.getDamage());
|
||||
@@ -774,7 +779,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card pridemate = addCard(pridemateName, p1);
|
||||
Card indestructibility = addCard(indestructibilityName, p1);
|
||||
|
||||
indestructibility.enchantEntity(pridemate);
|
||||
indestructibility.attachToEntity(pridemate);
|
||||
|
||||
Card ignition = addCardToZone(ignitionName, p1, ZoneType.Hand);
|
||||
SpellAbility ignitionSA = ignition.getFirstSpellAbility();
|
||||
@@ -798,8 +803,9 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
assertNotNull(simBrood);
|
||||
assertEquals(0, simBrood.getDamage());
|
||||
|
||||
//destoryed because of to much redirected damage
|
||||
// destoryed because of to much redirected damage
|
||||
assertNull(simPalisade);
|
||||
assertNotNull(simPridemate);
|
||||
|
||||
assertEquals(0, simKalitas.getDamage());
|
||||
assertEquals(3, simPridemate.getDamage());
|
||||
@@ -846,7 +852,10 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
coneSA.setTargetCard(bearCard); // one damage to bear
|
||||
coneSA.getSubAbility().setTargetCard(giantCard); // two damage to giant
|
||||
coneSA.getSubAbility().getSubAbility().getTargets().add(p2); // three damage to player
|
||||
coneSA.getSubAbility().getSubAbility().getTargets().add(p2); // three
|
||||
// damage
|
||||
// to
|
||||
// player
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p1);
|
||||
game.getAction().checkStateEffects(true);
|
||||
@@ -859,7 +868,8 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card simGiant = findCardWithName(simGame, giantCardName);
|
||||
Card simPridemate = findCardWithName(simGame, pridemateName);
|
||||
|
||||
// spell deals multiple damages to multiple targets, only one cause of lifegain
|
||||
// spell deals multiple damages to multiple targets, only one cause of
|
||||
// lifegain
|
||||
assertNotNull(simPridemate);
|
||||
assertTrue(simPridemate.hasCounters());
|
||||
assertEquals(1, simPridemate.getCounters(CounterType.P1P1));
|
||||
@@ -875,7 +885,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
// 1 + 2 + 3 lifegain
|
||||
assertEquals(26, simGame.getPlayers().get(0).getLife());
|
||||
assertEquals(17, simGame.getPlayers().get(1).getLife());
|
||||
|
||||
|
||||
// second pard with Everlasting Torment
|
||||
addCard(tormentName, p2);
|
||||
|
||||
@@ -912,7 +922,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
assertEquals(20, simGame2.getPlayers().get(0).getLife());
|
||||
assertEquals(17, simGame2.getPlayers().get(1).getLife());
|
||||
|
||||
// third pard with Melira prevents wither
|
||||
// third pard with Melira prevents wither
|
||||
addCard(meliraName, p2);
|
||||
|
||||
GameSimulator sim3 = createSimulator(game, p1);
|
||||
@@ -962,11 +972,11 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
|
||||
assertTrue(lilianaInPlay.isCreature());
|
||||
assertEquals(2, lilianaInPlay.getNetPower());
|
||||
assertEquals(3, lilianaInPlay.getNetToughness());
|
||||
|
||||
|
||||
SpellAbility playLiliana = lilianaInHand.getSpellAbilities().get(0);
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
sim.simulateSpellAbility(playLiliana);
|
||||
@@ -1002,7 +1012,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
Player simP = simGame.getPlayers().get(1);
|
||||
assertEquals(2, simP.getCounters(CounterType.ENERGY));
|
||||
|
||||
|
||||
GameCopier copier = new GameCopier(simGame);
|
||||
Game copy = copier.makeCopy();
|
||||
Player copyP = copy.getPlayers().get(1);
|
||||
@@ -1032,7 +1042,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card darkConfidantCard2 = (Card) sim.getGameCopier().find(darkConfidantCard);
|
||||
SpellAbility playDarkConfidant2 = darkConfidantCard2.getSpellAbilities().get(0);
|
||||
Card deathriteCard2 = (Card) sim.getGameCopier().find(deathriteCard);
|
||||
|
||||
|
||||
GameSimulator sim2 = createSimulator(simGame, simP);
|
||||
sim2.simulateSpellAbility(playDarkConfidant2);
|
||||
Game sim2Game = sim2.getSimulatedGameState();
|
||||
@@ -1054,40 +1064,40 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
public void testEnKor() {
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
|
||||
|
||||
String soulfireName = "Soulfire Grand Master";
|
||||
String pridemateName = "Ajani's Pridemate";
|
||||
|
||||
|
||||
String enKorName = "Spirit en-Kor";
|
||||
String bearName = "Runeclaw Bear";
|
||||
String shockName = "Shock";
|
||||
|
||||
|
||||
addCard("Mountain", p);
|
||||
|
||||
addCard(soulfireName, p);
|
||||
addCard(pridemateName, p);
|
||||
|
||||
Card shockCard = addCardToZone(shockName, p, ZoneType.Hand);
|
||||
|
||||
|
||||
Card enKor = addCard(enKorName, p);
|
||||
|
||||
|
||||
SpellAbility enKorSA = findSAWithPrefix(enKor, "{0}:");
|
||||
|
||||
|
||||
Card bear = addCard(bearName, p);
|
||||
|
||||
|
||||
SpellAbility shockSA = shockCard.getFirstSpellAbility();
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
|
||||
assertEquals(2, enKor.getNetPower());
|
||||
assertEquals(2, enKor.getNetToughness());
|
||||
assertEquals(0, enKor.getDamage());
|
||||
|
||||
|
||||
assertEquals(2, bear.getNetPower());
|
||||
assertEquals(2, bear.getNetToughness());
|
||||
assertEquals(0, bear.getDamage());
|
||||
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
enKorSA.setTargetCard(bear);
|
||||
shockSA.setTargetCard(enKor);
|
||||
@@ -1096,13 +1106,13 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
Card simEnKor = findCardWithName(simGame, enKorName);
|
||||
Card simBear = findCardWithName(simGame, bearName);
|
||||
|
||||
|
||||
assertNotNull(simEnKor);
|
||||
assertEquals(1, simEnKor.getDamage());
|
||||
|
||||
assertNotNull(simBear);
|
||||
assertEquals(1, simBear.getDamage());
|
||||
|
||||
|
||||
Card simPridemate = findCardWithName(simGame, pridemateName);
|
||||
|
||||
// only triggered once
|
||||
@@ -1113,7 +1123,7 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
assertEquals(22, simGame.getPlayers().get(0).getLife());
|
||||
}
|
||||
|
||||
|
||||
public void testRazia() {
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
@@ -1181,14 +1191,14 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
public void testRazia2() {
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
|
||||
|
||||
String soulfireName = "Soulfire Grand Master";
|
||||
String pridemateName = "Ajani's Pridemate";
|
||||
|
||||
|
||||
String raziaName = "Razia, Boros Archangel";
|
||||
String elementalName = "Air Elemental";
|
||||
String shockName = "Shock";
|
||||
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
addCard("Mountain", p);
|
||||
}
|
||||
@@ -1198,13 +1208,13 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
Card shockCard1 = addCardToZone(shockName, p, ZoneType.Hand);
|
||||
Card shockCard2 = addCardToZone(shockName, p, ZoneType.Hand);
|
||||
|
||||
|
||||
Card razia = addCard(raziaName, p);
|
||||
|
||||
|
||||
SpellAbility preventSA = findSAWithPrefix(razia, "{T}:");
|
||||
|
||||
|
||||
Card elemental = addCard(elementalName, p);
|
||||
|
||||
|
||||
SpellAbility shockSA1 = shockCard1.getFirstSpellAbility();
|
||||
SpellAbility shockSA2 = shockCard2.getFirstSpellAbility();
|
||||
|
||||
@@ -1212,11 +1222,11 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
assertEquals(0, razia.getDamage());
|
||||
|
||||
|
||||
assertEquals(4, elemental.getNetPower());
|
||||
assertEquals(4, elemental.getNetToughness());
|
||||
assertEquals(0, elemental.getDamage());
|
||||
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
preventSA.setTargetCard(razia);
|
||||
preventSA.getSubAbility().setTargetCard(elemental);
|
||||
@@ -1228,14 +1238,14 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
Card simRazia = findCardWithName(simGame, raziaName);
|
||||
Card simElemental = findCardWithName(simGame, elementalName);
|
||||
|
||||
|
||||
assertNotNull(simRazia);
|
||||
assertEquals(1, simRazia.getDamage());
|
||||
|
||||
// elemental not destroyed
|
||||
assertNotNull(simElemental);
|
||||
assertEquals(3, simElemental.getDamage());
|
||||
|
||||
|
||||
Card simPridemate = findCardWithName(simGame, pridemateName);
|
||||
|
||||
// only triggered twice
|
||||
@@ -1315,8 +1325,10 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
}
|
||||
|
||||
public void testPlayerXCount() {
|
||||
// If playerXCount is operational, then conditions that count something about the player (e.g.
|
||||
// cards in hand, life total) should work, similar to the Bloodghast "Haste" condition.
|
||||
// If playerXCount is operational, then conditions that count something
|
||||
// about the player (e.g.
|
||||
// cards in hand, life total) should work, similar to the Bloodghast
|
||||
// "Haste" condition.
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
Player opp = game.getPlayers().get(1);
|
||||
@@ -1325,12 +1337,12 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
Card bloodghast = addCardToZone("Bloodghast", p, ZoneType.Battlefield);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
assert(!bloodghast.hasKeyword("Haste"));
|
||||
assert (!bloodghast.hasKeyword("Haste"));
|
||||
|
||||
opp.setLife(5, null);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
assert(bloodghast.hasKeyword("Haste"));
|
||||
assert (bloodghast.hasKeyword("Haste"));
|
||||
}
|
||||
|
||||
public void testDeathsShadow() {
|
||||
@@ -1343,10 +1355,345 @@ public class GameSimulatorTest extends SimulationTestCase {
|
||||
|
||||
p.setLife(1, null);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assert(deathsShadow.getNetPower() == 12);
|
||||
assert (deathsShadow.getNetPower() == 12);
|
||||
|
||||
p.setLife(-1, null);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assert(deathsShadow.getNetPower() == 13); // on negative life, should always be 13/13
|
||||
assert (deathsShadow.getNetPower() == 13); // on negative life, should
|
||||
// always be 13/13
|
||||
}
|
||||
|
||||
public void testBludgeonBrawlLatticeAura() {
|
||||
// Enchantment Aura are with Mycosynth Lattice turned into Artifact Enchantment - Aura Equipment
|
||||
// Creature Auras should stay on
|
||||
String bearCardName = "Runeclaw Bear";
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(1);
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
|
||||
Card bear = addCard(bearCardName, p);
|
||||
bear.setSickness(false);
|
||||
Card lifelink = addCard("Lifelink", p);
|
||||
lifelink.attachToEntity(bear);
|
||||
|
||||
assertTrue(bear.isEnchanted());
|
||||
assertTrue(bear.hasCardAttachment(lifelink));
|
||||
|
||||
// this adds Artifact Type
|
||||
addCardToZone("Mycosynth Lattice", p, ZoneType.Battlefield);
|
||||
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertTrue(bear.isEnchanted());
|
||||
assertFalse(bear.isEquipped());
|
||||
|
||||
assertTrue(lifelink.isArtifact());
|
||||
assertFalse(lifelink.isEquipment());
|
||||
|
||||
// this add Equipment and causes it to fall off
|
||||
addCardToZone("Bludgeon Brawl", p, ZoneType.Battlefield);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertTrue(bear.isEnchanted());
|
||||
assertTrue(bear.isEquipped());
|
||||
|
||||
assertTrue(lifelink.isArtifact());
|
||||
assertTrue(lifelink.isEquipment());
|
||||
|
||||
// still in battlefield
|
||||
assertTrue(lifelink.isInPlay());
|
||||
}
|
||||
|
||||
public void testBludgeonBrawlLatticeCurse() {
|
||||
// Enchantment Aura are with Mycosynth Lattice turned into Artifact Enchantment - Aura Equipment
|
||||
// Curses can only attach Player, but Equipment can only attach to Creature so it does fall off
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
|
||||
final String curseName = "Cruel Reality";
|
||||
|
||||
Card curse = addCard(curseName, p);
|
||||
curse.attachToEntity(p);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertTrue(p.isEnchanted());
|
||||
assertTrue(p.hasCardAttachment(curse));
|
||||
|
||||
// this adds Artifact Type
|
||||
addCardToZone("Mycosynth Lattice", p, ZoneType.Battlefield);
|
||||
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertTrue(p.isEnchanted());
|
||||
assertTrue(curse.isArtifact());
|
||||
|
||||
// this add Equipment and causes it to fall off
|
||||
addCardToZone("Bludgeon Brawl", p, ZoneType.Battlefield);
|
||||
game.getAction().checkStateEffects(true);
|
||||
assertFalse(p.isEnchanted());
|
||||
|
||||
// not in Battlefield anymore
|
||||
assertFalse(curse.isInPlay());
|
||||
assertTrue(curse.isInZone(ZoneType.Graveyard));
|
||||
}
|
||||
|
||||
public void testBludgeonBrawlFortification() {
|
||||
// Bludgeon Brawl makes Fortification into Equipment
|
||||
// that means it can't attach a Land anymore if the Land is no Creature
|
||||
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
|
||||
Card mountain = addCardToZone("Mountain", p, ZoneType.Battlefield);
|
||||
Card fortification = addCardToZone("Darksteel Garrison", p, ZoneType.Battlefield);
|
||||
|
||||
fortification.attachToEntity(mountain);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
assertTrue(fortification.isFortification());
|
||||
assertFalse(fortification.isEquipment());
|
||||
|
||||
assertTrue(mountain.isFortified());
|
||||
assertTrue(mountain.hasCardAttachment(fortification));
|
||||
assertTrue(mountain.hasKeyword(Keyword.INDESTRUCTIBLE));
|
||||
|
||||
// adding Brawl will cause the Fortification into Equipment and it to
|
||||
// fall off
|
||||
addCardToZone("Bludgeon Brawl", p, ZoneType.Battlefield);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
assertFalse(fortification.isFortification());
|
||||
assertTrue(fortification.isEquipment());
|
||||
|
||||
assertFalse(mountain.hasCardAttachment(fortification));
|
||||
assertFalse(mountain.hasKeyword(Keyword.INDESTRUCTIBLE));
|
||||
}
|
||||
|
||||
public void testBludgeonBrawlFortificationDryad() {
|
||||
// Bludgeon Brawl makes Fortification into Equipment
|
||||
// that means it can't attach a Land anymore if the Land is no Creature too
|
||||
// Dryad Arbor is both a Land and a Creature so it stays attached
|
||||
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
|
||||
Card dryad = addCardToZone("Dryad Arbor", p, ZoneType.Battlefield);
|
||||
Card fortification = addCardToZone("Darksteel Garrison", p, ZoneType.Battlefield);
|
||||
|
||||
fortification.attachToEntity(dryad);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
assertTrue(dryad.isFortified());
|
||||
assertFalse(dryad.isEquipped());
|
||||
|
||||
assertTrue(dryad.hasCardAttachment(fortification));
|
||||
assertTrue(dryad.hasKeyword(Keyword.INDESTRUCTIBLE));
|
||||
|
||||
// adding Brawl will cause the Fortification into Equipment
|
||||
// because Dryad Arbor is a Creature it stays attached
|
||||
addCardToZone("Bludgeon Brawl", p, ZoneType.Battlefield);
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
// switched from Fortification to Equipment
|
||||
assertFalse(dryad.isFortified());
|
||||
assertTrue(dryad.isEquipped());
|
||||
|
||||
assertTrue(dryad.hasCardAttachment(fortification));
|
||||
assertTrue(dryad.hasKeyword(Keyword.INDESTRUCTIBLE));
|
||||
}
|
||||
|
||||
|
||||
public void testRiotEnchantment() {
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
|
||||
final String goblinName = "Zhur-Taa Goblin";
|
||||
|
||||
addCard("Rhythm of the Wild", p);
|
||||
|
||||
Card goblin = addCardToZone(goblinName, p, ZoneType.Hand);
|
||||
|
||||
addCard("Mountain", p);
|
||||
addCard("Forest", p);
|
||||
|
||||
SpellAbility goblinSA = goblin.getFirstSpellAbility();
|
||||
assertNotNull(goblinSA);
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int score = sim.simulateSpellAbility(goblinSA).value;
|
||||
assertTrue(score > 0);
|
||||
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
Card simGoblin = findCardWithName(simGame, goblinName);
|
||||
|
||||
assertNotNull(simGoblin);
|
||||
int effects = simGoblin.getCounters(CounterType.P1P1) + simGoblin.getKeywordMagnitude(Keyword.HASTE);
|
||||
assertTrue(effects == 2);
|
||||
}
|
||||
|
||||
public void testTeysaKarlovXathridNecromancer() {
|
||||
// Teysa Karlov and Xathrid Necromancer dying at the same time makes 4 token
|
||||
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
|
||||
addCard("Teysa Karlov", p);
|
||||
addCard("Xathrid Necromancer", p);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
addCardToZone("Plains", p, ZoneType.Battlefield);
|
||||
}
|
||||
|
||||
Card wrathOfGod = addCardToZone("Wrath of God", p, ZoneType.Hand);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
|
||||
SpellAbility wrathSA = wrathOfGod.getFirstSpellAbility();
|
||||
assertNotNull(wrathSA);
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int score = sim.simulateSpellAbility(wrathSA).value;
|
||||
assertTrue(score > 0);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
int numZombies = countCardsWithName(simGame, "Zombie");
|
||||
assertTrue(numZombies == 4);
|
||||
}
|
||||
|
||||
public void testDoubleTeysaKarlovXathridNecromancer() {
|
||||
// Teysa Karlov dieing because of Legendary rule will make Xathrid Necromancer trigger 3 times
|
||||
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
|
||||
addCard("Teysa Karlov", p);
|
||||
addCard("Xathrid Necromancer", p);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
addCard("Plains", p);
|
||||
}
|
||||
addCard("Swamp", p);
|
||||
|
||||
Card second = addCardToZone("Teysa Karlov", p, ZoneType.Hand);
|
||||
|
||||
SpellAbility secondSA = second.getFirstSpellAbility();
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int score = sim.simulateSpellAbility(secondSA).value;
|
||||
assertTrue(score > 0);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
int numZombies = countCardsWithName(simGame, "Zombie");
|
||||
assertTrue(numZombies == 3);
|
||||
}
|
||||
|
||||
|
||||
public void testTeysaKarlovGitrogMonster() {
|
||||
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
|
||||
addCard("Teysa Karlov", p);
|
||||
addCard("The Gitrog Monster", p);
|
||||
addCard("Dryad Arbor", p);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
addCard("Plains", p);
|
||||
addCardToZone("Plains", p, ZoneType.Library);
|
||||
}
|
||||
|
||||
Card armageddon = addCardToZone("Armageddon", p, ZoneType.Hand);
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
|
||||
SpellAbility armageddonSA = armageddon.getFirstSpellAbility();
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int score = sim.simulateSpellAbility(armageddonSA).value;
|
||||
assertTrue(score > 0);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
// Two cards drawn
|
||||
assertTrue(simGame.getPlayers().get(0).getZone(ZoneType.Hand).size() == 2);
|
||||
}
|
||||
|
||||
public void testTeysaKarlovGitrogMonsterGitrogDies() {
|
||||
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
|
||||
Card teysa = addCard("Teysa Karlov", p);
|
||||
addCard("The Gitrog Monster", p);
|
||||
addCard("Dryad Arbor", p);
|
||||
|
||||
String indestructibilityName = "Indestructibility";
|
||||
Card indestructibility = addCard(indestructibilityName, p);
|
||||
|
||||
indestructibility.attachToEntity(teysa);
|
||||
|
||||
// update Indestructible state
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
addCard("Plains", p);
|
||||
addCardToZone("Plains", p, ZoneType.Library);
|
||||
}
|
||||
|
||||
Card armageddon = addCardToZone("Wrath of God", p, ZoneType.Hand);
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
|
||||
SpellAbility armageddonSA = armageddon.getFirstSpellAbility();
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int score = sim.simulateSpellAbility(armageddonSA).value;
|
||||
assertTrue(score > 0);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
// One cards drawn
|
||||
assertTrue(simGame.getPlayers().get(0).getZone(ZoneType.Hand).size() == 1);
|
||||
}
|
||||
|
||||
public void testTeysaKarlovGitrogMonsterTeysaDies() {
|
||||
|
||||
Game game = initAndCreateGame();
|
||||
Player p = game.getPlayers().get(0);
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN1, p);
|
||||
|
||||
addCard("Teysa Karlov", p);
|
||||
Card gitrog = addCard("The Gitrog Monster", p);
|
||||
addCard("Dryad Arbor", p);
|
||||
|
||||
String indestructibilityName = "Indestructibility";
|
||||
Card indestructibility = addCard(indestructibilityName, p);
|
||||
|
||||
indestructibility.attachToEntity(gitrog);
|
||||
|
||||
// update Indestructible state
|
||||
game.getAction().checkStateEffects(true);
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
addCard("Plains", p);
|
||||
addCardToZone("Plains", p, ZoneType.Library);
|
||||
}
|
||||
|
||||
Card armageddon = addCardToZone("Wrath of God", p, ZoneType.Hand);
|
||||
|
||||
game.getPhaseHandler().devModeSet(PhaseType.MAIN2, p);
|
||||
|
||||
SpellAbility armageddonSA = armageddon.getFirstSpellAbility();
|
||||
|
||||
GameSimulator sim = createSimulator(game, p);
|
||||
int score = sim.simulateSpellAbility(armageddonSA).value;
|
||||
assertTrue(score > 0);
|
||||
Game simGame = sim.getSimulatedGameState();
|
||||
|
||||
// One cards drawn
|
||||
assertTrue(simGame.getPlayers().get(0).getZone(ZoneType.Hand).size() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +126,8 @@ public class SimulationTestCase extends TestCase {
|
||||
|
||||
protected Card addCardToZone(String name, Player p, ZoneType zone) {
|
||||
Card c = createCard(name, p);
|
||||
// card need a new Timestamp otherwise Static Abilities might collide
|
||||
c.setTimestamp(p.getGame().getNextTimestamp());
|
||||
p.getZone(zone).add(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
@@ -102,22 +102,16 @@ public class GameWrapper {
|
||||
actualController.getZone( zoneType ).add( actualCard );
|
||||
|
||||
if( card.getTarget() != null ) {
|
||||
Card target = CardSpecificationHandler.INSTANCE.find( game, card.getTarget() );
|
||||
if( actualCard.isEnchantment() ) {
|
||||
if( target.canBeEnchantedBy( actualCard ) ) {
|
||||
actualCard.enchantEntity( target );
|
||||
} else {
|
||||
throw new IllegalStateException( actualCard + " can't enchant " + target );
|
||||
}
|
||||
} else if( actualCard.isEquipment() ) {
|
||||
if( target.canBeEquippedBy( actualCard ) ) {
|
||||
actualCard.equipCard( target );
|
||||
} else {
|
||||
throw new IllegalStateException( actualCard + " can't equip " + target );
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException( "Don't know how to make " + actualCard + " target anything" );
|
||||
}
|
||||
Card target = CardSpecificationHandler.INSTANCE.find( game, card.getTarget() );
|
||||
if (actualCard.isAttachment()) {
|
||||
if (target.canBeAttached(actualCard)) {
|
||||
actualCard.attachToEntity(target);
|
||||
} else {
|
||||
throw new IllegalStateException( actualCard + " can't attach to " + target );
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException( "Don't know how to make " + actualCard + " target anything" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -174,7 +174,13 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends GameEntity> List<T> chooseEntitiesForEffect(FCollectionView<T> optionList, DelayedReveal delayedReveal, SpellAbility sa, String title, Player relatedPlayer) {
|
||||
public <T extends GameEntity> List<T> chooseEntitiesForEffect(FCollectionView<T> optionList, int min, int max, DelayedReveal delayedReveal, SpellAbility sa, String title, Player relatedPlayer) {
|
||||
// this isn't used
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends GameEntity> List<T> chooseFromTwoListsForEffect(FCollectionView<T> optionList1, FCollectionView<T> optionList2, boolean optional, DelayedReveal delayedReveal, SpellAbility sa, String title, Player targetedPlayer) {
|
||||
// this isn't used
|
||||
return null;
|
||||
}
|
||||
@@ -624,7 +630,7 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Card> chooseCardsForZoneChange(ZoneType destination, List<ZoneType> origin, SpellAbility sa, CardCollection fetchList, DelayedReveal delayedReveal, String selectPrompt, Player decider) {
|
||||
public List<Card> chooseCardsForZoneChange(ZoneType destination, List<ZoneType> origin, SpellAbility sa, CardCollection fetchList, int min, int max, DelayedReveal delayedReveal, String selectPrompt, Player decider) {
|
||||
// this isn't used
|
||||
return null;
|
||||
}
|
||||
@@ -678,4 +684,10 @@ public class PlayerControllerForTests extends PlayerController {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean confirmMulliganScry(Player p) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user