mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 18:58:00 +00:00
Merge branch 'master' into ui-card-translation
This commit is contained in:
@@ -52,7 +52,7 @@ public class ChooseCardEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
CardCollectionView choices = game.getCardsIn(choiceZone);
|
CardCollectionView choices = game.getCardsIn(choiceZone);
|
||||||
if (sa.hasParam("Choices")) {
|
if (sa.hasParam("Choices")) {
|
||||||
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, host);
|
choices = CardLists.getValidCards(choices, sa.getParam("Choices"), activator, host, sa);
|
||||||
}
|
}
|
||||||
if (sa.hasParam("TargetControls")) {
|
if (sa.hasParam("TargetControls")) {
|
||||||
choices = CardLists.filterControlledBy(choices, tgtPlayers.get(0));
|
choices = CardLists.filterControlledBy(choices, tgtPlayers.get(0));
|
||||||
|
|||||||
@@ -2697,6 +2697,13 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final Player getController() {
|
public final Player getController() {
|
||||||
|
if ((currentZone == null) || ((currentZone.getZoneType() != ZoneType.Battlefield) && (currentZone.getZoneType() != ZoneType.Stack))){
|
||||||
|
//only permanents and spells have controllers [108.4],
|
||||||
|
//so a card really only has a controller while it's on the stack or battlefield.
|
||||||
|
//everywhere else, just use the owner [108.4a].
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
Entry<Long, Player> lastEntry = tempControllers.lastEntry();
|
Entry<Long, Player> lastEntry = tempControllers.lastEntry();
|
||||||
if (lastEntry != null) {
|
if (lastEntry != null) {
|
||||||
final long lastTimestamp = lastEntry.getKey();
|
final long lastTimestamp = lastEntry.getKey();
|
||||||
|
|||||||
@@ -3508,7 +3508,7 @@ public class CardFactoryUtil {
|
|||||||
String abExile = "DB$ ChangeZone | Defined$ Self | Origin$ Stack | Destination$ Exile";
|
String abExile = "DB$ ChangeZone | Defined$ Self | Origin$ Stack | Destination$ Exile";
|
||||||
String delTrig = "DB$ DelayedTrigger | Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You " +
|
String delTrig = "DB$ DelayedTrigger | Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You " +
|
||||||
" | OptionalDecider$ You | RememberObjects$ Self | TriggerDescription$"
|
" | OptionalDecider$ You | RememberObjects$ Self | TriggerDescription$"
|
||||||
+ " At the beginning of your next upkeep, you may cast " + card.toString() + " without paying it's manacost.";
|
+ " At the beginning of your next upkeep, you may cast " + card.toString() + " without paying its mana cost.";
|
||||||
// TODO add check for still in exile
|
// TODO add check for still in exile
|
||||||
String abPlay = "DB$ Play | Defined$ Self | WithoutManaCost$ True | Optional$ True";
|
String abPlay = "DB$ Play | Defined$ Self | WithoutManaCost$ True | Optional$ True";
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ public enum CSubmenuDownloaders implements ICDoc {
|
|||||||
new GuiDownloader(new GuiDownloadPicturesLQ()).show();
|
new GuiDownloader(new GuiDownloadPicturesLQ()).show();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
private final UiCommand cmdPicDownloadHQ = new UiCommand() {
|
||||||
|
@Override public void run() {
|
||||||
|
new GuiDownloader(new GuiDownloadPicturesHQ()).show();
|
||||||
|
}
|
||||||
|
};
|
||||||
private final UiCommand cmdSetDownload = new UiCommand() {
|
private final UiCommand cmdSetDownload = new UiCommand() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
new GuiDownloader(new GuiDownloadSetPicturesLQ()).show();
|
new GuiDownloader(new GuiDownloadSetPicturesLQ()).show();
|
||||||
@@ -80,6 +85,7 @@ public enum CSubmenuDownloaders implements ICDoc {
|
|||||||
public void initialize() {
|
public void initialize() {
|
||||||
final VSubmenuDownloaders view = VSubmenuDownloaders.SINGLETON_INSTANCE;
|
final VSubmenuDownloaders view = VSubmenuDownloaders.SINGLETON_INSTANCE;
|
||||||
view.setDownloadPicsCommand(cmdPicDownload);
|
view.setDownloadPicsCommand(cmdPicDownload);
|
||||||
|
view.setDownloadPicsHQCommand(cmdPicDownloadHQ);
|
||||||
view.setDownloadSetPicsCommand(cmdSetDownload);
|
view.setDownloadSetPicsCommand(cmdSetDownload);
|
||||||
view.setDownloadQuestImagesCommand(cmdQuestImages);
|
view.setDownloadQuestImagesCommand(cmdQuestImages);
|
||||||
view.setDownloadAchievementImagesCommand(cmdAchievementImages);
|
view.setDownloadAchievementImagesCommand(cmdAchievementImages);
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
|
|
||||||
private final FLabel btnDownloadSetPics = _makeButton(localizer.getMessage("btnDownloadSetPics"));
|
private final FLabel btnDownloadSetPics = _makeButton(localizer.getMessage("btnDownloadSetPics"));
|
||||||
private final FLabel btnDownloadPics = _makeButton(localizer.getMessage("btnDownloadPics"));
|
private final FLabel btnDownloadPics = _makeButton(localizer.getMessage("btnDownloadPics"));
|
||||||
|
private final FLabel btnDownloadPicsHQ = _makeButton(localizer.getMessage("btnDownloadPicsHQ"));
|
||||||
private final FLabel btnDownloadQuestImages = _makeButton(localizer.getMessage("btnDownloadQuestImages"));
|
private final FLabel btnDownloadQuestImages = _makeButton(localizer.getMessage("btnDownloadQuestImages"));
|
||||||
private final FLabel btnDownloadAchievementImages = _makeButton(localizer.getMessage("btnDownloadAchievementImages"));
|
private final FLabel btnDownloadAchievementImages = _makeButton(localizer.getMessage("btnDownloadAchievementImages"));
|
||||||
private final FLabel btnReportBug = _makeButton(localizer.getMessage("btnReportBug"));
|
private final FLabel btnReportBug = _makeButton(localizer.getMessage("btnReportBug"));
|
||||||
@@ -82,6 +83,9 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
pnlContent.add(btnDownloadPics, constraintsBTN);
|
pnlContent.add(btnDownloadPics, constraintsBTN);
|
||||||
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPics")), constraintsLBL);
|
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPics")), constraintsLBL);
|
||||||
|
|
||||||
|
pnlContent.add(btnDownloadPicsHQ, constraintsBTN);
|
||||||
|
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPicsHQ")), constraintsLBL);
|
||||||
|
|
||||||
pnlContent.add(btnDownloadSetPics, constraintsBTN);
|
pnlContent.add(btnDownloadSetPics, constraintsBTN);
|
||||||
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadSetPics")), constraintsLBL);
|
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadSetPics")), constraintsLBL);
|
||||||
|
|
||||||
@@ -159,6 +163,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setDownloadPicsCommand(UiCommand command) { btnDownloadPics.setCommand(command); }
|
public void setDownloadPicsCommand(UiCommand command) { btnDownloadPics.setCommand(command); }
|
||||||
|
public void setDownloadPicsHQCommand(UiCommand command) { btnDownloadPicsHQ.setCommand(command); }
|
||||||
public void setDownloadSetPicsCommand(UiCommand command) { btnDownloadSetPics.setCommand(command); }
|
public void setDownloadSetPicsCommand(UiCommand command) { btnDownloadSetPics.setCommand(command); }
|
||||||
public void setDownloadQuestImagesCommand(UiCommand command) { btnDownloadQuestImages.setCommand(command); }
|
public void setDownloadQuestImagesCommand(UiCommand command) { btnDownloadQuestImages.setCommand(command); }
|
||||||
public void setDownloadAchievementImagesCommand(UiCommand command) { btnDownloadAchievementImages.setCommand(command); }
|
public void setDownloadAchievementImagesCommand(UiCommand command) { btnDownloadAchievementImages.setCommand(command); }
|
||||||
|
|||||||
42
forge-gui-mobile/src/forge/assets/FLanguage.java
Normal file
42
forge-gui-mobile/src/forge/assets/FLanguage.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package forge.assets;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.properties.ForgeConstants;
|
||||||
|
import forge.properties.ForgePreferences;
|
||||||
|
import forge.properties.ForgePreferences.FPref;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class FLanguage {
|
||||||
|
|
||||||
|
public static void changeLanguage(final String languageName) {
|
||||||
|
final ForgePreferences prefs = FModel.getPreferences();
|
||||||
|
if (languageName.equals(prefs.getPref(FPref.UI_LANGUAGE))) { return; }
|
||||||
|
|
||||||
|
//save language preference
|
||||||
|
prefs.setPref(FPref.UI_LANGUAGE, languageName);
|
||||||
|
prefs.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the languages.
|
||||||
|
*
|
||||||
|
* @return the languages
|
||||||
|
*/
|
||||||
|
public static Iterable<String> getAllLanguages() {
|
||||||
|
final List<String> allLanguages = new ArrayList<String>();
|
||||||
|
|
||||||
|
final FileHandle dir = Gdx.files.absolute(ForgeConstants.LANG_DIR);
|
||||||
|
for (FileHandle languageFile : dir.list()) {
|
||||||
|
String languageName = languageFile.name();
|
||||||
|
if (!languageName.endsWith(".properties")) { continue; }
|
||||||
|
allLanguages.add(languageName.replace(".properties", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
return allLanguages;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ import forge.Graphics;
|
|||||||
import forge.MulliganDefs;
|
import forge.MulliganDefs;
|
||||||
import forge.StaticData;
|
import forge.StaticData;
|
||||||
import forge.ai.AiProfileUtil;
|
import forge.ai.AiProfileUtil;
|
||||||
|
import forge.assets.FLanguage;
|
||||||
import forge.assets.FSkin;
|
import forge.assets.FSkin;
|
||||||
import forge.assets.FSkinColor;
|
import forge.assets.FSkinColor;
|
||||||
import forge.assets.FSkinFont;
|
import forge.assets.FSkinFont;
|
||||||
@@ -48,6 +49,14 @@ public class SettingsPage extends TabPage<SettingsScreen> {
|
|||||||
lstSettings.addGroup("Sound Options");
|
lstSettings.addGroup("Sound Options");
|
||||||
|
|
||||||
//General Settings
|
//General Settings
|
||||||
|
lstSettings.addItem(new CustomSelectSetting(FPref.UI_LANGUAGE, "Language",
|
||||||
|
"Select Language (Excluded Game part. Still a work in progress) (RESTART REQUIRED)",
|
||||||
|
FLanguage.getAllLanguages()) {
|
||||||
|
@Override
|
||||||
|
public void valueChanged(String newValue) {
|
||||||
|
FLanguage.changeLanguage(newValue);
|
||||||
|
}
|
||||||
|
}, 0);
|
||||||
lstSettings.addItem(new CustomSelectSetting(FPref.UI_SKIN, "Theme",
|
lstSettings.addItem(new CustomSelectSetting(FPref.UI_SKIN, "Theme",
|
||||||
"Sets the theme that determines how display components are skinned.",
|
"Sets the theme that determines how display components are skinned.",
|
||||||
FSkin.getAllSkins()) {
|
FSkin.getAllSkins()) {
|
||||||
|
|||||||
16
forge-gui/res/editions/Signature Spellbook Gideon.txt
Normal file
16
forge-gui/res/editions/Signature Spellbook Gideon.txt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[metadata]
|
||||||
|
Code=SS2
|
||||||
|
Date=2019-06-28
|
||||||
|
Name=Signature Spellbook: Gideon
|
||||||
|
MciCode=ss2
|
||||||
|
Type=Reprint
|
||||||
|
|
||||||
|
[cards]
|
||||||
|
1 M Gideon Jura
|
||||||
|
2 R Martyr's Bond
|
||||||
|
3 R Path to Exile
|
||||||
|
4 R Rest in Peace
|
||||||
|
5 R Shielded by Faith
|
||||||
|
6 R True Conviction
|
||||||
|
7 R Worship
|
||||||
|
8 R Blackblade Reforged
|
||||||
@@ -179,6 +179,7 @@ Achievements=Erfolge
|
|||||||
# VSubmenuDownloaders.java
|
# VSubmenuDownloaders.java
|
||||||
btnDownloadSetPics=Bilder(LQ) Sets herunterladen
|
btnDownloadSetPics=Bilder(LQ) Sets herunterladen
|
||||||
btnDownloadPics=Bilder(LQ) Karten herunterladen
|
btnDownloadPics=Bilder(LQ) Karten herunterladen
|
||||||
|
btnDownloadPicsHQ=Bilder(HQ) Karten herunterladen (Sehr langsam!)
|
||||||
btnDownloadQuestImages=Bilder für Quests herunterladen
|
btnDownloadQuestImages=Bilder für Quests herunterladen
|
||||||
btnDownloadAchievementImages=Bilder für Erfolge herunterladen
|
btnDownloadAchievementImages=Bilder für Erfolge herunterladen
|
||||||
btnReportBug=Einen Fehler melden
|
btnReportBug=Einen Fehler melden
|
||||||
@@ -189,6 +190,7 @@ btnHowToPlay=Wie man spielt
|
|||||||
btnDownloadPrices=Kartenpreise herunterladen
|
btnDownloadPrices=Kartenpreise herunterladen
|
||||||
btnLicensing=Lizenzhinweis
|
btnLicensing=Lizenzhinweis
|
||||||
lblDownloadPics=Lädt ein Standardbild pro Karte.
|
lblDownloadPics=Lädt ein Standardbild pro Karte.
|
||||||
|
lblDownloadPicsHQ=Lädt ein Standardbild (HQ) pro Karte.
|
||||||
lblDownloadSetPics=Lädt alle Bilder pro Karte. Eines für jedes Set, in welchem die Karte auftauchte.
|
lblDownloadSetPics=Lädt alle Bilder pro Karte. Eines für jedes Set, in welchem die Karte auftauchte.
|
||||||
lblDownloadQuestImages=Lädt die Bilder für den Quest-Modus.
|
lblDownloadQuestImages=Lädt die Bilder für den Quest-Modus.
|
||||||
lblDownloadAchievementImages=Lädt die Bilder zu den möglichen Erfolgen. Verschönert die Trophäensammlung.
|
lblDownloadAchievementImages=Lädt die Bilder zu den möglichen Erfolgen. Verschönert die Trophäensammlung.
|
||||||
@@ -317,7 +319,7 @@ lblIsGoingFirst=beginnt.
|
|||||||
lblYouAreGoing=Du startest
|
lblYouAreGoing=Du startest
|
||||||
lblMulligan=Mulligan
|
lblMulligan=Mulligan
|
||||||
lblDoYouWantToKeepYourHand=Starthand behalten?
|
lblDoYouWantToKeepYourHand=Starthand behalten?
|
||||||
lblReturnForLondon=Lege %n Karten unter die Bibliothek
|
lblReturnForLondon=Lege %d Karten unter die Bibliothek
|
||||||
lblOk=OK
|
lblOk=OK
|
||||||
lblReset=Zurück
|
lblReset=Zurück
|
||||||
lblAuto=Auto
|
lblAuto=Auto
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ KeyboardShortcuts=Keyboard Shortcuts
|
|||||||
Achievements=Achievements
|
Achievements=Achievements
|
||||||
# VSubmenuDownloaders.java
|
# VSubmenuDownloaders.java
|
||||||
btnDownloadSetPics=Download LQ Set Pictures
|
btnDownloadSetPics=Download LQ Set Pictures
|
||||||
|
btnDownloadPicsHQ=Download HQ Card Pictures (Very Slow!)
|
||||||
btnDownloadPics=Download LQ Card Pictures
|
btnDownloadPics=Download LQ Card Pictures
|
||||||
btnDownloadQuestImages=Download Quest Images
|
btnDownloadQuestImages=Download Quest Images
|
||||||
btnDownloadAchievementImages=Download Achievement Images
|
btnDownloadAchievementImages=Download Achievement Images
|
||||||
@@ -189,6 +190,7 @@ btnHowToPlay=How To Play
|
|||||||
btnDownloadPrices=Download Card Prices
|
btnDownloadPrices=Download Card Prices
|
||||||
btnLicensing=License Details
|
btnLicensing=License Details
|
||||||
lblDownloadPics=Download default card picture for each card.
|
lblDownloadPics=Download default card picture for each card.
|
||||||
|
lblDownloadPicsHQ=Download default card HQ picture for each card.
|
||||||
lblDownloadSetPics=Download all pictures of each card (one for each set the card appeared in)
|
lblDownloadSetPics=Download all pictures of each card (one for each set the card appeared in)
|
||||||
lblDownloadQuestImages=Download tokens and icons used in Quest mode.
|
lblDownloadQuestImages=Download tokens and icons used in Quest mode.
|
||||||
lblDownloadAchievementImages=Download achievement images to really make your trophies stand out.
|
lblDownloadAchievementImages=Download achievement images to really make your trophies stand out.
|
||||||
@@ -317,7 +319,7 @@ lblIsGoingFirst=is going first
|
|||||||
lblYouAreGoing=you are going
|
lblYouAreGoing=you are going
|
||||||
lblMulligan=Mulligan
|
lblMulligan=Mulligan
|
||||||
lblDoYouWantToKeepYourHand=Do you want to keep your hand?
|
lblDoYouWantToKeepYourHand=Do you want to keep your hand?
|
||||||
lblReturnForLondon=Return %n card(s) to bottom of library
|
lblReturnForLondon=Return %d card(s) to the bottom of your library
|
||||||
lblOk=Ok
|
lblOk=Ok
|
||||||
lblReset=Reset
|
lblReset=Reset
|
||||||
lblAuto=Auto
|
lblAuto=Auto
|
||||||
|
|||||||
@@ -179,6 +179,7 @@ Achievements=Logros
|
|||||||
# VSubmenuDownloaders.java
|
# VSubmenuDownloaders.java
|
||||||
btnDownloadSetPics=Descargar todos los Sets de Cartas
|
btnDownloadSetPics=Descargar todos los Sets de Cartas
|
||||||
btnDownloadPics=Descargar todas las Cartas
|
btnDownloadPics=Descargar todas las Cartas
|
||||||
|
btnDownloadPicsHQ=Descargar todas las Cartas en calidad alta (Muy lento!)
|
||||||
btnDownloadQuestImages=Descargar Imágenes del modo Quest
|
btnDownloadQuestImages=Descargar Imágenes del modo Quest
|
||||||
btnDownloadAchievementImages=Descagar Imágenes de los Logros
|
btnDownloadAchievementImages=Descagar Imágenes de los Logros
|
||||||
btnReportBug=Reportar un error
|
btnReportBug=Reportar un error
|
||||||
@@ -189,6 +190,7 @@ btnHowToPlay=Cómo jugar (Inglés)
|
|||||||
btnDownloadPrices=Descargar los precios de las cartas
|
btnDownloadPrices=Descargar los precios de las cartas
|
||||||
btnLicensing=Detalles de la licencia
|
btnLicensing=Detalles de la licencia
|
||||||
lblDownloadPics=Descargar la imagen de la carta por defecto para cada carta.
|
lblDownloadPics=Descargar la imagen de la carta por defecto para cada carta.
|
||||||
|
lblDownloadPicsHQ=Descargar la imagen en calidad alta de la carta por defecto para cada carta.
|
||||||
lblDownloadSetPics=Descargue todas las imágenes de cada carta (una por cada set donde apareció la carta)
|
lblDownloadSetPics=Descargue todas las imágenes de cada carta (una por cada set donde apareció la carta)
|
||||||
lblDownloadQuestImages=Descarga fichas e íconos utilizados en el modo Quest.
|
lblDownloadQuestImages=Descarga fichas e íconos utilizados en el modo Quest.
|
||||||
lblDownloadAchievementImages=Descarga imágenes de logros para que tus trofeos realmente destaquen.
|
lblDownloadAchievementImages=Descarga imágenes de logros para que tus trofeos realmente destaquen.
|
||||||
@@ -317,7 +319,7 @@ lblIsGoingFirst=va primero
|
|||||||
lblYouAreGoing=vas
|
lblYouAreGoing=vas
|
||||||
lblMulligan=Mulligan
|
lblMulligan=Mulligan
|
||||||
lblDoYouWantToKeepYourHand=¿Quieres quedarte tu mano?
|
lblDoYouWantToKeepYourHand=¿Quieres quedarte tu mano?
|
||||||
lblReturnForLondon=Return %n card(s) to bottom of library
|
lblReturnForLondon=Return %d card(s) to the bottom of your library
|
||||||
lblOk=Ok
|
lblOk=Ok
|
||||||
lblReset=Reset
|
lblReset=Reset
|
||||||
lblAuto=Auto
|
lblAuto=Auto
|
||||||
|
|||||||
16
forge-gui/res/puzzle/PS_M203.pzl
Normal file
16
forge-gui/res/puzzle/PS_M203.pzl
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[metadata]
|
||||||
|
Name:Possibility Storm - Magic Core Set 2020 #03
|
||||||
|
URL:http://www.possibilitystorm.com/wp-content/uploads/2019/07/122.m203.jpg
|
||||||
|
Goal:Win
|
||||||
|
Turns:1
|
||||||
|
Difficulty:Mythic
|
||||||
|
Description:Win this turn. Assume your opponent has no mana available.
|
||||||
|
[state]
|
||||||
|
humanlife=20
|
||||||
|
ailife=12
|
||||||
|
turn=1
|
||||||
|
activeplayer=human
|
||||||
|
activephase=MAIN1
|
||||||
|
humanhand=Shatter;Teferi's Time Twist;Role Reversal;Trumpet Blast
|
||||||
|
humanbattlefield=Viashino Pyromancer;Retributive Wand;Captain's Hook;Saheeli, Sublime Artificer|Counters:LOYALTY=3;Island;Island;Mountain;Mountain
|
||||||
|
aibattlefield=Pardic Wanderer
|
||||||
@@ -0,0 +1,356 @@
|
|||||||
|
/*
|
||||||
|
* Forge: Play Magic: the Gathering.
|
||||||
|
* Copyright (C) 2011 Forge Team
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package forge.download;
|
||||||
|
|
||||||
|
import forge.item.PaperCard;
|
||||||
|
import forge.model.FModel;
|
||||||
|
import forge.properties.ForgeConstants;
|
||||||
|
import forge.util.ImageUtil;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class GuiDownloadPicturesHQ extends GuiDownloadService {
|
||||||
|
final Map<String, String> downloads = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
|
||||||
|
Set<String> existingSets;
|
||||||
|
ArrayList<String> existingImages;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTitle() {
|
||||||
|
return "Download HQ Card Pictures";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected final Map<String, String> getNeededFiles() {
|
||||||
|
File f = new File(ForgeConstants.CACHE_CARD_PICS_DIR);
|
||||||
|
existingImages = new ArrayList<String>(Arrays.asList(f.list()));
|
||||||
|
existingSets = retrieveManifestDirectory();
|
||||||
|
|
||||||
|
for (final PaperCard c : FModel.getMagicDb().getCommonCards().getAllCards()) {
|
||||||
|
addDLObject(c, false);
|
||||||
|
if (ImageUtil.hasBackFacePicture(c)) {
|
||||||
|
addDLObject(c, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final PaperCard c : FModel.getMagicDb().getVariantCards().getAllCards()) {
|
||||||
|
addDLObject(c, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add missing tokens to the list of things to download.
|
||||||
|
addMissingItems(downloads, ForgeConstants.IMAGE_LIST_TOKENS_FILE, ForgeConstants.CACHE_TOKEN_PICS_DIR);
|
||||||
|
|
||||||
|
return downloads;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addDLObject(final PaperCard c, final boolean backFace) {
|
||||||
|
final String imageKey = ImageUtil.getImageKey(c, backFace, false);
|
||||||
|
final String destPath = ForgeConstants.CACHE_CARD_PICS_DIR + imageKey + ".jpg";
|
||||||
|
|
||||||
|
if (existingImages.contains(imageKey + ".jpg")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (downloads.containsKey(destPath)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String setCode = c.getEdition();
|
||||||
|
String cardname = imageKey.replace(".full", "");
|
||||||
|
|
||||||
|
switch(setCode) {
|
||||||
|
case "CFX": setCode="CON"; break;
|
||||||
|
case "COM": setCode="CMD"; break;
|
||||||
|
case "FVE": setCode="V09"; break;
|
||||||
|
case "FVL": setCode="V11"; break;
|
||||||
|
case "FVR": setCode="V10"; break;
|
||||||
|
case "MED": setCode="ME1"; break;
|
||||||
|
case "MPS_AKH": setCode="AKH"; break;
|
||||||
|
case "MPS_KLD": setCode="MPS"; break;
|
||||||
|
case "MPS_RNA": setCode="MED"; break;
|
||||||
|
case "PDS": setCode="H09"; break;
|
||||||
|
case "PO2": setCode="P02"; break;
|
||||||
|
case "UGF": setCode="UGIN"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
setCode = getManualCode(cardname, setCode);
|
||||||
|
|
||||||
|
cardname = cardname.replace(" ", "+");
|
||||||
|
cardname = cardname.replace("'", "");
|
||||||
|
String scryfallurl = ForgeConstants.URL_PIC_SCRYFALL_DOWNLOAD + "named?fuzzy=" + cardname;
|
||||||
|
if(!setCode.equals("???")) scryfallurl += "&set=" + setCode.toLowerCase();
|
||||||
|
scryfallurl += "&format=image";
|
||||||
|
|
||||||
|
downloads.put(destPath, scryfallurl);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getManualCode(String cardname, String originalSetCode) {
|
||||||
|
String setCode=originalSetCode;
|
||||||
|
|
||||||
|
switch(cardname) {
|
||||||
|
case "Daretti, Ingenious Iconoclast":
|
||||||
|
case "Elspeth, Knight-Errant":
|
||||||
|
case "Garruk, Apex Predator":
|
||||||
|
case "Jace, the Mind Sculptor":
|
||||||
|
case "Liliana, the Last Hope":
|
||||||
|
case "Nahiri, the Harbinger":
|
||||||
|
case "Nicol Bolas, Planeswalker":
|
||||||
|
case "Sarkhan Unbroken":
|
||||||
|
case "Teferi, Hero of Dominaria":
|
||||||
|
case "Tezzeret, Agent of Bolas":
|
||||||
|
case "Tezzeret the Seeker":
|
||||||
|
case "Ugin, the Spirit Dragon": setCode="MED"; break;
|
||||||
|
|
||||||
|
case "Attrition":
|
||||||
|
case "Boil":
|
||||||
|
case "Capsize":
|
||||||
|
case "Counterbalance":
|
||||||
|
case "Daze":
|
||||||
|
case "Desolation Angel":
|
||||||
|
case "Divert":
|
||||||
|
case "Forbid":
|
||||||
|
case "Force of Will":
|
||||||
|
case "Loyal Retainers":
|
||||||
|
case "Mind Twist":
|
||||||
|
case "No Mercy":
|
||||||
|
case "Opposition":
|
||||||
|
case "Shatterstorm":
|
||||||
|
case "Slaughter Pact":
|
||||||
|
case "Stifle":
|
||||||
|
case "Sunder":
|
||||||
|
case "Worship":
|
||||||
|
case "Wrath of God": setCode="MP2"; break;
|
||||||
|
|
||||||
|
case "Behold the Power of Destruction":
|
||||||
|
case "Choose Your Champion":
|
||||||
|
case "Dance, Pathetic Marionette":
|
||||||
|
case "Embrace My Diabolical Vision":
|
||||||
|
case "Every Hope Shall Vanish":
|
||||||
|
case "Every Last Vestige Shall Rot":
|
||||||
|
case "Evil Comes to Fruition":
|
||||||
|
case "Feed the Machine":
|
||||||
|
case "I Bask in Your Silent Awe":
|
||||||
|
case "I Call on the Ancient Magics":
|
||||||
|
case "I Delight in Your Convulsions":
|
||||||
|
case "I Know All, I See All":
|
||||||
|
case "Ignite the Cloneforge!":
|
||||||
|
case "Into the Earthen Maw":
|
||||||
|
case "Introductions Are in Order":
|
||||||
|
case "Know Naught but Fire":
|
||||||
|
case "Look Skyward and Despair":
|
||||||
|
case "May Civilization Collapse":
|
||||||
|
case "Mortal Flesh Is Weak":
|
||||||
|
case "My Crushing Masterstroke":
|
||||||
|
case "My Genius Knows No Bounds":
|
||||||
|
case "My Undead Horde Awakens":
|
||||||
|
case "My Wish Is Your Command":
|
||||||
|
case "Nature Demands an Offering":
|
||||||
|
case "Nature Shields Its Own":
|
||||||
|
case "Nothing Can Stop Me Now":
|
||||||
|
case "Only Blood Ends Your Nightmares":
|
||||||
|
case "Realms Befitting My Majesty":
|
||||||
|
case "Roots of All Evil":
|
||||||
|
case "Rotted Ones, Lay Siege":
|
||||||
|
case "Surrender Your Thoughts":
|
||||||
|
case "The Dead Shall Serve":
|
||||||
|
case "The Fate of the Flammable":
|
||||||
|
case "The Iron Guardian Stirs":
|
||||||
|
case "The Pieces Are Coming Together":
|
||||||
|
case "The Very Soil Shall Shake":
|
||||||
|
case "Tooth, Claw, and Tail":
|
||||||
|
case "Which of You Burns Brightest":
|
||||||
|
case "Your Fate Is Thrice Sealed":
|
||||||
|
case "Your Puny Minds Cannot Fathom":
|
||||||
|
case "Your Will Is Not Your Own": setCode="OARC"; break;
|
||||||
|
|
||||||
|
case "Because I Have Willed It":
|
||||||
|
case "Behold My Grandeur":
|
||||||
|
case "Bow to My Command":
|
||||||
|
case "Choose Your Demise":
|
||||||
|
case "Delight in the Hunt":
|
||||||
|
case "Every Dream a Nightmare":
|
||||||
|
case "For Each of You, a Gift":
|
||||||
|
case "Know Evil":
|
||||||
|
case "Make Yourself Useful":
|
||||||
|
case "My Forces Are Innumerable":
|
||||||
|
case "My Laughter Echoes":
|
||||||
|
case "No One Will Hear Your Cries":
|
||||||
|
case "Pay Tribute to Me":
|
||||||
|
case "Power Without Equal":
|
||||||
|
case "The Mighty Will Fall":
|
||||||
|
case "There Is No Refuge":
|
||||||
|
case "This World Belongs to Me":
|
||||||
|
case "What's Yours Is Now Mine":
|
||||||
|
case "When Will You Learn": setCode="OE01"; break;
|
||||||
|
|
||||||
|
case "Bloodhill Bastion":
|
||||||
|
case "Celestine Reef":
|
||||||
|
case "Chaotic Aether":
|
||||||
|
case "Choke":
|
||||||
|
case "Cliffside Market":
|
||||||
|
case "Edge of Malacol":
|
||||||
|
case "Eloren Wilds":
|
||||||
|
case "Feeding Grounds":
|
||||||
|
case "Fields of Summer":
|
||||||
|
case "Furnace Layer":
|
||||||
|
case "Glimmervoid Basin":
|
||||||
|
case "Grand Ossuary":
|
||||||
|
case "Grove of the Dreampods":
|
||||||
|
case "Hedron Fields of Agadeem":
|
||||||
|
case "Horizon Boughs":
|
||||||
|
case "Immersturm":
|
||||||
|
case "Interplanar Tunnel":
|
||||||
|
case "Isle of Vesuva":
|
||||||
|
case "Izzet Steam Maze":
|
||||||
|
case "Kharasha Foothills":
|
||||||
|
case "Kilnspire District":
|
||||||
|
case "Lair of the Ashen Idol":
|
||||||
|
case "Lethe Lake":
|
||||||
|
case "Mirrored Depths":
|
||||||
|
case "Morphic Tide":
|
||||||
|
case "Mount Keralia":
|
||||||
|
case "Mutual Epiphany":
|
||||||
|
case "Norn's Dominion":
|
||||||
|
case "Onakke Catacomb":
|
||||||
|
case "Orochi Colony":
|
||||||
|
case "Panopticon":
|
||||||
|
case "Planewide Disaster":
|
||||||
|
case "Pools of Becoming":
|
||||||
|
case "Quicksilver Sea":
|
||||||
|
case "Reality Shaping":
|
||||||
|
case "Sanctum of Serra":
|
||||||
|
case "Sea of Sand":
|
||||||
|
case "Selesnya Loft Gardens":
|
||||||
|
case "Skybreen":
|
||||||
|
case "Spatial Merging":
|
||||||
|
case "Stairs to Infinity":
|
||||||
|
case "Stronghold Furnace":
|
||||||
|
case "Talon Gates":
|
||||||
|
case "Tember City":
|
||||||
|
case "Windriddle Palaces":
|
||||||
|
case "The Aether Flues":
|
||||||
|
case "The Dark Barony":
|
||||||
|
case "The Eon Fog":
|
||||||
|
case "The Fourth Sphere":
|
||||||
|
case "The Great Forest":
|
||||||
|
case "The Hippodrome":
|
||||||
|
case "The Maelstrom":
|
||||||
|
case "The Zephyr Maze":
|
||||||
|
case "Time Distortion":
|
||||||
|
case "Trail of the Mage-Rings":
|
||||||
|
case "Truga Jungle":
|
||||||
|
case "Turri Island":
|
||||||
|
case "Undercity Reaches": setCode="OPCA"; break;
|
||||||
|
|
||||||
|
case "Drench the Soil in Their Blood":
|
||||||
|
case "Imprison This Insolent Wretch":
|
||||||
|
case "Perhaps You've Met My Cohort":
|
||||||
|
case "Plots That Span Centuries":
|
||||||
|
case "Your Inescapable Doom": setCode="PARC"; break;
|
||||||
|
|
||||||
|
case "Stoneforge Mystic": setCode="PGPX"; break;
|
||||||
|
|
||||||
|
case "Birds of Paradise Avatar1":
|
||||||
|
case "Bosh, Iron Golem Avatar":
|
||||||
|
case "Braids, Conjurer Adept Avatar":
|
||||||
|
case "Chronatog Avatar":
|
||||||
|
case "Dakkon Blackblade Avatar":
|
||||||
|
case "Dauntless Escort Avatar":
|
||||||
|
case "Diamond Faerie Avatar":
|
||||||
|
case "Eight-and-a-Half-Tails Avatar":
|
||||||
|
case "Enigma Sphinx Avatar":
|
||||||
|
case "Eladamri, Lord of Leaves Avatar":
|
||||||
|
case "Elvish Champion Avatar":
|
||||||
|
case "Erhnam Djinn Avatar1":
|
||||||
|
case "Etched Oracle Avatar":
|
||||||
|
case "Fallen Angel Avatar":
|
||||||
|
case "Figure of Destiny Avatar":
|
||||||
|
case "Flametongue Kavu Avatar":
|
||||||
|
case "Frenetic Efreet Avatar":
|
||||||
|
case "Goblin Warchief Avatar1":
|
||||||
|
case "Grinning Demon Avatar1":
|
||||||
|
case "Haakon, Stromgald Scourge Avatar":
|
||||||
|
case "Heartwood Storyteller Avatar":
|
||||||
|
case "Hell's Caretaker Avatar":
|
||||||
|
case "Hermit Druid Avatar":
|
||||||
|
case "Higure, the Still Wind Avatar":
|
||||||
|
case "Ink-Eyes, Servant of Oni Avatar":
|
||||||
|
case "Jaya Ballard Avatar":
|
||||||
|
case "Jhoira of the Ghitu Avatar":
|
||||||
|
case "Karona, False God Avatar":
|
||||||
|
case "Kresh the Bloodbraided Avatar":
|
||||||
|
case "Loxodon Hierarch Avatar":
|
||||||
|
case "Lyzolda, the Blood Witch Avatar":
|
||||||
|
case "Malfegor Avatar":
|
||||||
|
case "Maralen of the Mornsong Avatar":
|
||||||
|
case "Maro Avatar":
|
||||||
|
case "Master of the Wild Hunt Avatar":
|
||||||
|
case "Mayael the Anima Avatar":
|
||||||
|
case "Mirri the Cursed Avatar":
|
||||||
|
case "Mirror Entity Avatar":
|
||||||
|
case "Momir Vig, Simic Visionary Avatar":
|
||||||
|
case "Morinfen Avatar":
|
||||||
|
case "Murderous Redcap Avatar":
|
||||||
|
case "Necropotence Avatar":
|
||||||
|
case "Nekrataal Avatar":
|
||||||
|
case "Oni of Wild Places Avatar":
|
||||||
|
case "Orcish Squatters Avatar":
|
||||||
|
case "Peacekeeper Avatar":
|
||||||
|
case "Phage the Untouchable Avatar":
|
||||||
|
case "Platinum Angel Avatar1":
|
||||||
|
case "Prodigal Sorcerer Avatar1":
|
||||||
|
case "Raksha Golden Cub Avatar":
|
||||||
|
case "Reaper King Avatar":
|
||||||
|
case "Rith, the Awakener Avatar1":
|
||||||
|
case "Royal Assassin Avatar1":
|
||||||
|
case "Rumbling Slum Avatar":
|
||||||
|
case "Sakashima the Impostor Avatar":
|
||||||
|
case "Serra Angel Avatar1":
|
||||||
|
case "Seshiro the Anointed Avatar":
|
||||||
|
case "Sisters of Stone Death Avatar":
|
||||||
|
case "Sliver Queen Avatar":
|
||||||
|
case "Squee, Goblin Nabob Avatar":
|
||||||
|
case "Stalking Tiger Avatar":
|
||||||
|
case "Stonehewer Giant Avatar":
|
||||||
|
case "Stuffy Doll Avatar":
|
||||||
|
case "Teysa, Orzhov Scion Avatar":
|
||||||
|
case "Tradewind Rider Avatar1":
|
||||||
|
case "Two-Headed Giant of Foriys Avatar":
|
||||||
|
case "Vampire Nocturnus Avatar":
|
||||||
|
case "Viridian Zealot Avatar": setCode="PMOA"; break;
|
||||||
|
|
||||||
|
case "Nalathni Dragon":
|
||||||
|
case "Sewers of Estark":
|
||||||
|
case "Windseeker Centaur": setCode="PRM"; break;
|
||||||
|
|
||||||
|
case "Lyna":
|
||||||
|
case "Sliver Queen, Brood Mother":
|
||||||
|
case "Takara": setCode="PVAN"; break;
|
||||||
|
|
||||||
|
case "Goblin Hero": setCode="S99"; break;
|
||||||
|
|
||||||
|
case "Pyrostatic Pillar":
|
||||||
|
case "Weathered Wayfarer": setCode="TD0"; break;
|
||||||
|
|
||||||
|
case "Hero's Resolve":
|
||||||
|
case "Python": setCode="6ED"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return setCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,6 +32,7 @@ import java.net.URLDecoder;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@@ -272,7 +273,13 @@ public abstract class GuiDownloadService implements Runnable {
|
|||||||
URL imageUrl = new URL(url);
|
URL imageUrl = new URL(url);
|
||||||
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection(p);
|
HttpURLConnection conn = (HttpURLConnection) imageUrl.openConnection(p);
|
||||||
// don't allow redirections here -- they indicate 'file not found' on the server
|
// don't allow redirections here -- they indicate 'file not found' on the server
|
||||||
|
// only allow redirections to consume Scryfall API
|
||||||
|
if(url.contains("api.scryfall.com")) {
|
||||||
|
conn.setInstanceFollowRedirects(true);
|
||||||
|
TimeUnit.MILLISECONDS.sleep(100);
|
||||||
|
} else {
|
||||||
conn.setInstanceFollowRedirects(false);
|
conn.setInstanceFollowRedirects(false);
|
||||||
|
}
|
||||||
conn.connect();
|
conn.connect();
|
||||||
|
|
||||||
// if file is not found and this is a JPG, give PNG a shot...
|
// if file is not found and this is a JPG, give PNG a shot...
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ public class InputLondonMulligan extends InputSyncronizedBase {
|
|||||||
|
|
||||||
getController().getGui().updateButtons(getOwner(), localizer.getMessage("lblOk"), "", cardsLeft == 0, false, true);
|
getController().getGui().updateButtons(getOwner(), localizer.getMessage("lblOk"), "", cardsLeft == 0, false, true);
|
||||||
|
|
||||||
sb.append(String.format(localizer.getMessage("lblReturnForLondon"), selected.size(), toReturn));
|
sb.append(String.format(localizer.getMessage("lblReturnForLondon"), cardsLeft));
|
||||||
|
|
||||||
showMessage(sb.toString());
|
showMessage(sb.toString());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -284,6 +284,8 @@ public final class ForgeConstants {
|
|||||||
public static final String URL_PIC_DOWNLOAD = URL_CARDFORGE + "/images/cards/";
|
public static final String URL_PIC_DOWNLOAD = URL_CARDFORGE + "/images/cards/";
|
||||||
public static final String URL_TOKEN_DOWNLOAD = URL_CARDFORGE + "/images/tokens/";
|
public static final String URL_TOKEN_DOWNLOAD = URL_CARDFORGE + "/images/tokens/";
|
||||||
public static final String URL_PRICE_DOWNLOAD = URL_CARDFORGE + "/all-prices.txt";
|
public static final String URL_PRICE_DOWNLOAD = URL_CARDFORGE + "/all-prices.txt";
|
||||||
|
private static final String URL_SCRYFALL = "https://api.scryfall.com";
|
||||||
|
public static final String URL_PIC_SCRYFALL_DOWNLOAD = URL_SCRYFALL + "/cards/";
|
||||||
|
|
||||||
// Constants for Display Card Identity game setting
|
// Constants for Display Card Identity game setting
|
||||||
public static final String DISP_CURRENT_COLORS_ALWAYS = "Always";
|
public static final String DISP_CURRENT_COLORS_ALWAYS = "Always";
|
||||||
|
|||||||
Reference in New Issue
Block a user