mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
Merge remote-tracking branch 'upstream/master' into display_localization_cardname
This commit is contained in:
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
cd "`dirname \"$0\"`"
|
||||
java -Xmx1024m -jar $project.build.finalName$
|
||||
@@ -1,3 +0,0 @@
|
||||
#!/bin/sh
|
||||
cd "`dirname \"$0\"`"
|
||||
java -Xmx1024m -jar $project.build.finalName$
|
||||
@@ -48,10 +48,22 @@ public enum FSkinProp {
|
||||
|
||||
//zone images
|
||||
IMG_ZONE_HAND (new int[] {280, 40, 40, 40}, PropType.IMAGE),
|
||||
IMG_HDZONE_HAND (new int[] {2, 136, 128, 128}, PropType.BUTTONS),
|
||||
|
||||
IMG_ZONE_LIBRARY (new int[] {280, 0, 40, 40}, PropType.IMAGE),
|
||||
IMG_HDZONE_LIBRARY (new int[] {132, 136, 128, 128}, PropType.BUTTONS),
|
||||
|
||||
IMG_ZONE_EXILE (new int[] {320, 40, 40, 40}, PropType.IMAGE),
|
||||
IMG_HDZONE_EXILE (new int[] {262, 136, 128, 128}, PropType.BUTTONS),
|
||||
|
||||
IMG_ZONE_FLASHBACK (new int[] {280, 80, 40, 40}, PropType.IMAGE),
|
||||
IMG_HDZONE_FLASHBACK (new int[] {262, 6, 128, 128}, PropType.BUTTONS),
|
||||
|
||||
IMG_ZONE_GRAVEYARD (new int[] {320, 0, 40, 40}, PropType.IMAGE),
|
||||
IMG_HDZONE_GRAVEYARD (new int[] {132, 6, 128, 128}, PropType.BUTTONS),
|
||||
|
||||
IMG_HDZONE_MANAPOOL (new int[] {2, 6, 128, 128}, PropType.BUTTONS),
|
||||
|
||||
IMG_ZONE_POISON (new int[] {320, 80, 40, 40}, PropType.IMAGE),
|
||||
|
||||
//mana images
|
||||
@@ -170,6 +182,15 @@ public enum FSkinProp {
|
||||
ICO_ARCSON (new int[] {320, 800, 80, 80}, PropType.ICON),
|
||||
ICO_ARCSHOVER (new int[] {400, 800, 80, 80}, PropType.ICON),
|
||||
|
||||
//choice-search-misc
|
||||
ICO_HDCHOICE (new int[] {2, 1792, 128, 128}, PropType.BUTTONS),
|
||||
ICO_HDSIDEBOARD (new int[] {132, 1792, 128, 128}, PropType.BUTTONS),
|
||||
ICO_HDPREFERENCE (new int[] {262, 1792, 128, 128}, PropType.BUTTONS),
|
||||
ICO_HDIMPORT (new int[] {2, 1922, 128, 128}, PropType.BUTTONS),
|
||||
ICO_HDEXPORT (new int[] {132, 1922, 128, 128}, PropType.BUTTONS),
|
||||
ICO_BLANK (new int[] {2, 2, 2, 2}, PropType.ICON), //safe coords, lower than 2 will cause crash on desktop
|
||||
IMG_LANDLOGO (new int[] {84, 822, 80, 80}, PropType.MANAICONS),
|
||||
|
||||
//quest icons
|
||||
ICO_QUEST_ZEP (new int[] {0, 480, 80, 80}, PropType.ICON),
|
||||
ICO_QUEST_GEAR (new int[] {80, 480, 80, 80}, PropType.ICON),
|
||||
@@ -192,31 +213,82 @@ public enum FSkinProp {
|
||||
ICO_QUEST_MINUS (new int[] {560, 640, 80, 80}, PropType.ICON),
|
||||
ICO_QUEST_PLUS (new int[] {480, 640, 80, 80}, PropType.ICON),
|
||||
ICO_QUEST_PLUSPLUS (new int[] {480, 720, 80, 80}, PropType.ICON),
|
||||
ICO_QUEST_BIG_ELIXIR (new int[] {0, 880, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_BREW (new int[] {160, 880, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_BM (new int[] {320, 880, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_STAKES (new int[] {480, 880, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_HOUSE (new int[] {0, 1040, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_COIN (new int[] {160, 1040, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_BOOK (new int[] {320, 1040, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_MAP (new int[] {480, 1040, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_ZEP (new int[] {0, 1200, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_CHARM (new int[] {160, 1200, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_BOOTS (new int[] {320, 1200, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_SHIELD (new int[] {480, 1200, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_ARMOR (new int[] {0, 1360, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_AXE (new int[] {160, 1360, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_SWORD (new int[] {320, 1360, 160, 160}, PropType.ICON),
|
||||
ICO_QUEST_BIG_BAG (new int[] {480, 1360, 160, 160}, PropType.ICON),
|
||||
|
||||
//menu icon
|
||||
ICO_MENU_GALAXY (new int[] {0, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_STATS (new int[] {80, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_PUZZLE (new int[] {160, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_GAUNTLET (new int[] {240, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_SEALED (new int[] {320, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_DRAFT (new int[] {400, 1520, 80, 80}, PropType.ICON),
|
||||
ICO_MENU_CONSTRUCTED (new int[] {480, 1520, 80, 80}, PropType.ICON),
|
||||
|
||||
//interface icons
|
||||
ICO_QUESTION (new int[] {560, 800, 32, 32}, PropType.ICON),
|
||||
ICO_INFORMATION (new int[] {592, 800, 32, 32}, PropType.ICON),
|
||||
ICO_WARNING (new int[] {560, 832, 32, 32}, PropType.ICON),
|
||||
ICO_ERROR (new int[] {592, 832, 32, 32}, PropType.ICON),
|
||||
|
||||
ICO_DELETE (new int[] {640, 480, 20, 20}, PropType.ICON),
|
||||
ICO_HDDELETE (new int[] {392, 134, 64, 64}, PropType.BUTTONS),
|
||||
|
||||
ICO_DELETE_OVER (new int[] {660, 480, 20, 20}, PropType.ICON),
|
||||
|
||||
ICO_EDIT (new int[] {640, 500, 20, 20}, PropType.ICON),
|
||||
ICO_HDEDIT (new int[] {392, 200, 64, 64}, PropType.BUTTONS),
|
||||
|
||||
ICO_EDIT_OVER (new int[] {660, 500, 20, 20}, PropType.ICON),
|
||||
|
||||
ICO_OPEN (new int[] {660, 520, 20, 20}, PropType.ICON),
|
||||
ICO_HDOPEN (new int[] {392, 68, 64, 64}, PropType.BUTTONS),
|
||||
|
||||
ICO_MINUS (new int[] {660, 620, 20, 20}, PropType.ICON),
|
||||
ICO_HDMINUS (new int[] {391, 1506, 64, 64}, PropType.BUTTONS),
|
||||
|
||||
ICO_NEW (new int[] {660, 540, 20, 20}, PropType.ICON),
|
||||
|
||||
ICO_PLUS (new int[] {660, 600, 20, 20}, PropType.ICON),
|
||||
ICO_HDPLUS (new int[] {391, 1572, 64, 64}, PropType.BUTTONS),
|
||||
|
||||
ICO_PRINT (new int[] {660, 640, 20, 20}, PropType.ICON),
|
||||
|
||||
ICO_SAVE (new int[] {660, 560, 20, 20}, PropType.ICON),
|
||||
ICO_HDSAVE (new int[] {391, 1704, 64, 64}, PropType.BUTTONS),
|
||||
ICO_SAVEAS (new int[] {660, 580, 20, 20}, PropType.ICON),
|
||||
ICO_HDSAVEAS (new int[] {391, 1638, 64, 64}, PropType.BUTTONS),
|
||||
|
||||
ICO_CLOSE (new int[] {640, 640, 20, 20}, PropType.ICON),
|
||||
ICO_LIST (new int[] {640, 660, 20, 20}, PropType.ICON),
|
||||
ICO_CARD_IMAGE (new int[] {660, 660, 20, 20}, PropType.ICON),
|
||||
|
||||
ICO_FOLDER (new int[] {640, 680, 20, 20}, PropType.ICON),
|
||||
ICO_HDFOLDER (new int[] {392, 2, 64, 64}, PropType.BUTTONS),
|
||||
|
||||
ICO_SEARCH (new int[] {660, 680, 20, 20}, PropType.ICON),
|
||||
ICO_HDSEARCH (new int[] {391, 1374, 64, 64}, PropType.BUTTONS),
|
||||
|
||||
ICO_UNKNOWN (new int[] {0, 720, 80, 80}, PropType.ICON),
|
||||
ICO_LOGO (new int[] {480, 0, 200, 200}, PropType.ICON),
|
||||
|
||||
ICO_FLIPCARD (new int[] {400, 0, 80, 120}, PropType.ICON),
|
||||
ICO_HDFLIPCARD (new int[] {2, 1268, 387, 500}, PropType.BUTTONS),
|
||||
|
||||
ICO_FAVICON (new int[] {0, 640, 80, 80}, PropType.ICON),
|
||||
ICO_LOCK (new int[] {620, 800, 48, 48}, PropType.ICON),
|
||||
|
||||
@@ -229,14 +301,18 @@ public enum FSkinProp {
|
||||
IMG_CUR_TAB (new int[] {644, 764, 32, 32}, PropType.IMAGE),
|
||||
|
||||
//editor images
|
||||
IMG_STAR_OUTINE (new int[] {640, 460, 20, 20}, PropType.IMAGE),
|
||||
IMG_STAR_OUTLINE (new int[] {640, 460, 20, 20}, PropType.IMAGE),
|
||||
IMG_HDSTAR_OUTLINE (new int[] {391, 1308, 64, 64}, PropType.BUTTONS),
|
||||
IMG_STAR_FILLED (new int[] {660, 460, 20, 20}, PropType.IMAGE),
|
||||
IMG_HDSTAR_FILLED (new int[] {391, 1440, 64, 64}, PropType.BUTTONS),
|
||||
|
||||
IMG_ARTIFACT (new int[] {412, 658, 80, 80}, PropType.MANAICONS),
|
||||
IMG_CREATURE (new int[] {2, 740, 80, 80}, PropType.MANAICONS),
|
||||
IMG_ENCHANTMENT (new int[] {84, 740, 80, 80}, PropType.MANAICONS),
|
||||
IMG_INSTANT (new int[] {166, 740, 80, 80}, PropType.MANAICONS),
|
||||
IMG_LAND (new int[] {248, 740, 80, 80}, PropType.MANAICONS),
|
||||
IMG_MULTI (new int[] {80, 720, 40, 40}, PropType.IMAGE),
|
||||
IMG_HDMULTI (new int[] {2, 822, 80, 80}, PropType.MANAICONS),
|
||||
IMG_PLANESWALKER (new int[] {330, 740, 80, 80}, PropType.MANAICONS),
|
||||
IMG_PACK (new int[] {80, 760, 40, 40}, PropType.IMAGE),
|
||||
IMG_SORCERY (new int[] {412, 740, 80, 80}, PropType.MANAICONS),
|
||||
@@ -284,6 +360,28 @@ public enum FSkinProp {
|
||||
IMG_BTN_DISABLED_LEFT (new int[] {80, 200, 40, 40}, PropType.ICON),
|
||||
IMG_BTN_DISABLED_CENTER (new int[] {120, 200, 1, 40}, PropType.ICON),
|
||||
IMG_BTN_DISABLED_RIGHT (new int[] {160, 200, 40, 40}, PropType.ICON),
|
||||
//hd buttons
|
||||
IMG_HDBTN_START_UP (new int[] {2, 2, 588, 312}, PropType.BTNSTART),
|
||||
IMG_HDBTN_START_OVER (new int[] {1183, 2, 588, 312}, PropType.BTNSTART),
|
||||
IMG_HDBTN_START_DOWN (new int[] {593, 2, 588, 312}, PropType.BTNSTART),
|
||||
IMG_HDBTN_UP_LEFT (new int[] {2, 266, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_UP_CENTER (new int[] {162, 266, 1, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_UP_RIGHT (new int[] {322, 266, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_OVER_LEFT (new int[] {2, 433, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_OVER_CENTER (new int[] {162, 433, 1, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_OVER_RIGHT (new int[] {322, 433, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_DOWN_LEFT (new int[] {2, 600, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_DOWN_CENTER (new int[] {162, 600, 1, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_DOWN_RIGHT (new int[] {322, 600, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_FOCUS_LEFT (new int[] {2, 767, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_FOCUS_CENTER (new int[] {162, 767, 1, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_FOCUS_RIGHT (new int[] {322, 767, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_TOGGLE_LEFT (new int[] {2, 934, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_TOGGLE_CENTER (new int[] {162, 934, 1, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_TOGGLE_RIGHT (new int[] {322, 934, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_DISABLED_LEFT (new int[] {2, 1101, 160, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_DISABLED_CENTER (new int[] {162, 1101, 1, 165}, PropType.BUTTONS),
|
||||
IMG_HDBTN_DISABLED_RIGHT (new int[] {322, 1101, 160, 165}, PropType.BUTTONS),
|
||||
|
||||
IMG_FAV1 (new int[] {0, 0, 100, 100}, PropType.FAVICON),
|
||||
IMG_FAV2 (new int[] {100, 0, 100, 100}, PropType.FAVICON),
|
||||
@@ -378,6 +476,8 @@ public enum FSkinProp {
|
||||
TROPHY,
|
||||
ABILITY,
|
||||
BORDERS,
|
||||
BUTTONS,
|
||||
BTNSTART,
|
||||
MANAICONS,
|
||||
PLANAR_CONQUEST,
|
||||
FAVICON
|
||||
|
||||
@@ -156,6 +156,9 @@ public class DeckgenUtil {
|
||||
//}
|
||||
}
|
||||
|
||||
//remove any cards not valid in format
|
||||
selectedCards = Lists.newArrayList(Iterables.filter(selectedCards, format.getFilterPrinted()));
|
||||
|
||||
List<PaperCard> toRemove = new ArrayList<>();
|
||||
|
||||
//randomly remove cards
|
||||
@@ -252,6 +255,9 @@ public class DeckgenUtil {
|
||||
//}
|
||||
}
|
||||
|
||||
//remove any cards not valid in format
|
||||
selectedCards = Lists.newArrayList(Iterables.filter(selectedCards, format.getFilterPrinted()));
|
||||
|
||||
List<PaperCard> toRemove = new ArrayList<>();
|
||||
|
||||
//randomly remove cards
|
||||
|
||||
247
forge-gui/src/main/java/forge/download/AutoUpdater.java
Normal file
247
forge-gui/src/main/java/forge/download/AutoUpdater.java
Normal file
@@ -0,0 +1,247 @@
|
||||
package forge.download;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import forge.GuiBase;
|
||||
import forge.model.FModel;
|
||||
import forge.properties.ForgePreferences;
|
||||
import forge.util.BuildInfo;
|
||||
import forge.util.FileUtil;
|
||||
import forge.util.WaitCallback;
|
||||
import forge.util.gui.SOptionPane;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.*;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class AutoUpdater {
|
||||
private final String SNAPSHOT_VERSION_INDEX = "https://snapshots.cardforge.org/";
|
||||
private final String SNAPSHOT_VERSION_URL = "https://snapshots.cardforge.org/version.txt";
|
||||
private final String SNAPSHOT_PACKAGE = "https://snapshots.cardforge.org/latest/";
|
||||
private final String RELEASE_VERSION_URL = "https://releases.cardforge.org/forge/forge-gui-desktop/version.txt";
|
||||
private final String RELEASE_PACKAGE = "https://releases.cardforge.org/latest/";
|
||||
private final String RELEASE_MAVEN_METADATA = "https://releases.cardforge.org/forge/forge-gui-desktop/maven-metadata.xml";
|
||||
private static final boolean VERSION_FROM_METADATA = true;
|
||||
private static final String TMP_DIR = "tmp/";
|
||||
|
||||
public static String[] updateChannels = new String[]{ "none", "snapshot", "release"};
|
||||
|
||||
private boolean isLoading;
|
||||
private String updateChannel;
|
||||
private String version;
|
||||
private String buildVersion;
|
||||
private String versionUrlString;
|
||||
private String packageUrl;
|
||||
private String packagePath;
|
||||
|
||||
public AutoUpdater(boolean loading) {
|
||||
// What do I need? Preferences? Splashscreen? UI? Skins?
|
||||
isLoading = loading;
|
||||
updateChannel = FModel.getPreferences().getPref(ForgePreferences.FPref.AUTO_UPDATE);
|
||||
buildVersion = BuildInfo.getVersionString();
|
||||
}
|
||||
|
||||
public boolean attemptToUpdate() {
|
||||
if (!verifyUpdateable()) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
if (downloadUpdate()) {
|
||||
extractAndRestart();
|
||||
}
|
||||
} catch(IOException | URISyntaxException e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void extractAndRestart() {
|
||||
extractUpdate();
|
||||
restartForge();
|
||||
}
|
||||
|
||||
private boolean verifyUpdateable() {
|
||||
if (buildVersion.contains("GIT")) {
|
||||
//return false;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
// TODO This doesn't work yet, because FSkin isn't loaded at the time.
|
||||
return false;
|
||||
} else if (updateChannel.equals("none")) {
|
||||
String message = "You haven't set an update channel. Do you want to check a channel now?";
|
||||
List<String> options = ImmutableList.of("Cancel", "release", "snapshot");
|
||||
int option = SOptionPane.showOptionDialog(message, "Manual Check", null, options, 0);
|
||||
if (option == 0) {
|
||||
return false;
|
||||
} else {
|
||||
updateChannel = options.get(option);
|
||||
}
|
||||
}
|
||||
|
||||
if (buildVersion.contains("SNAPSHOT")) {
|
||||
if (!updateChannel.equals("snapshot")) {
|
||||
System.out.println("Snapshot build versions must use snapshot update channel to work");
|
||||
return false;
|
||||
}
|
||||
|
||||
versionUrlString = SNAPSHOT_VERSION_URL;
|
||||
packageUrl = SNAPSHOT_PACKAGE;
|
||||
} else {
|
||||
versionUrlString = RELEASE_VERSION_URL;
|
||||
packageUrl = RELEASE_PACKAGE;
|
||||
}
|
||||
|
||||
// Check the internet connection
|
||||
if (!testNetConnection()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Download appropriate version file
|
||||
return compareBuildWithLatestChannelVersion();
|
||||
}
|
||||
|
||||
private boolean testNetConnection() {
|
||||
try (Socket socket = new Socket()) {
|
||||
InetSocketAddress address = new InetSocketAddress("releases.cardforge.org", 443);
|
||||
socket.connect(address, 1000);
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false; // Either timeout or unreachable or failed DNS lookup.
|
||||
}
|
||||
}
|
||||
|
||||
private boolean compareBuildWithLatestChannelVersion() {
|
||||
try {
|
||||
retrieveVersion();
|
||||
|
||||
if (StringUtils.isEmpty(version) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (buildVersion.equals(version)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
// If version doesn't match, it's assummably newer.
|
||||
return true;
|
||||
}
|
||||
|
||||
private void retrieveVersion() throws MalformedURLException {
|
||||
if (VERSION_FROM_METADATA) {
|
||||
if (updateChannel.equals("release")) {
|
||||
extractVersionFromMavenRelease();
|
||||
} else {
|
||||
extractVersionFromSnapshotIndex();
|
||||
}
|
||||
} else {
|
||||
URL versionUrl = new URL(versionUrlString);
|
||||
version = FileUtil.readFileToString(versionUrl);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractVersionFromSnapshotIndex() throws MalformedURLException {
|
||||
URL metadataUrl = new URL(SNAPSHOT_VERSION_INDEX);
|
||||
String index = FileUtil.readFileToString(metadataUrl);
|
||||
|
||||
System.out.println(index);
|
||||
Pattern p = Pattern.compile(">forge-(.*SNAPSHOT)");
|
||||
Matcher m = p.matcher(index);
|
||||
while(m.find()){
|
||||
version = m.group(1);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractVersionFromMavenRelease() throws MalformedURLException {
|
||||
URL metadataUrl = new URL(RELEASE_MAVEN_METADATA);
|
||||
String xml = FileUtil.readFileToString(metadataUrl);
|
||||
|
||||
Pattern p = Pattern.compile("<release>(.*)</release>");
|
||||
Matcher m = p.matcher(xml);
|
||||
while(m.find()){
|
||||
version = m.group(1);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean downloadUpdate() throws URISyntaxException, IOException {
|
||||
// TODO Change the "auto" to be more auto.
|
||||
if (isLoading) {
|
||||
// We need to preload enough of a Skins to show a dialog and a button if we're in loading
|
||||
// splashScreen.prepareForDialogs();
|
||||
return downloadFromBrowser();
|
||||
}
|
||||
|
||||
String message = "A new version of Forge is available (" + version + ").\n" +
|
||||
"You are currently on version (" + buildVersion + ").\n\n" +
|
||||
"Would you like to update to the new version now?";
|
||||
|
||||
final List<String> options = ImmutableList.of("Update Now", "Update Later");
|
||||
if (SOptionPane.showOptionDialog(message, "New Version Available", null, options, 0) == 0) {
|
||||
return downloadFromForge();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean downloadFromBrowser() throws URISyntaxException, IOException {
|
||||
final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
|
||||
if (desktop != null && desktop.isSupported(Desktop.Action.BROWSE)) {
|
||||
// Linking directly there will auto download, but won't auto-update
|
||||
desktop.browse(new URI(packageUrl));
|
||||
return true;
|
||||
} else {
|
||||
System.out.println("Download latest version: " + packageUrl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean downloadFromForge() {
|
||||
WaitCallback<Boolean> callback = new WaitCallback<Boolean>() {
|
||||
@Override
|
||||
public void run() {
|
||||
GuiBase.getInterface().download(new GuiDownloadZipService("Auto Updater", "Download the new version..", packageUrl, "tmp/", null, null) {
|
||||
@Override
|
||||
public void downloadAndUnzip() {
|
||||
packagePath = download(version + "-upgrade.tar.bz2");
|
||||
if (packagePath != null) {
|
||||
extractAndRestart();
|
||||
}
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
|
||||
SwingUtilities.invokeLater(callback);
|
||||
//
|
||||
return false;
|
||||
}
|
||||
|
||||
private void extractUpdate() {
|
||||
// TODOD Something like https://stackoverflow.com/questions/315618/how-do-i-extract-a-tar-file-in-java
|
||||
final Desktop desktop = Desktop.isDesktopSupported() ? Desktop.getDesktop() : null;
|
||||
if (desktop != null) {
|
||||
try {
|
||||
desktop.open(new File(packagePath).getParentFile());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
System.out.println(packagePath);
|
||||
}
|
||||
}
|
||||
|
||||
private void restartForge() {
|
||||
if (isLoading || SOptionPane.showConfirmDialog("Forge has been downloaded. You should extract the package and restart Forge for the new version.", "Exit now?")) {
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,72 +73,7 @@ public class GuiDownloadZipService extends GuiDownloadService {
|
||||
String zipFilename = download("temp.zip");
|
||||
if (zipFilename == null) { return; }
|
||||
|
||||
//if assets.zip downloaded successfully, unzip into destination folder
|
||||
try {
|
||||
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while unzipping
|
||||
|
||||
if (deleteFolder != null) {
|
||||
final File deleteDir = new File(deleteFolder);
|
||||
if (deleteDir.exists()) {
|
||||
//attempt to delete previous res directory if to be rebuilt
|
||||
progressBar.reset();
|
||||
progressBar.setDescription("Deleting old " + desc + "...");
|
||||
if (deleteFolder.equals(destFolder)) { //move zip file to prevent deleting it
|
||||
final String oldZipFilename = zipFilename;
|
||||
zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip";
|
||||
Files.move(new File(oldZipFilename), new File(zipFilename));
|
||||
}
|
||||
FileUtil.deleteDirectory(deleteDir);
|
||||
}
|
||||
}
|
||||
|
||||
final ZipFile zipFile = new ZipFile(zipFilename);
|
||||
final Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
|
||||
progressBar.reset();
|
||||
progressBar.setPercentMode(true);
|
||||
progressBar.setDescription("Extracting " + desc);
|
||||
progressBar.setMaximum(zipFile.size());
|
||||
|
||||
FileUtil.ensureDirectoryExists(destFolder);
|
||||
|
||||
int count = 0;
|
||||
int failedCount = 0;
|
||||
while (entries.hasMoreElements()) {
|
||||
if (cancel) { break; }
|
||||
|
||||
try {
|
||||
final ZipEntry entry = entries.nextElement();
|
||||
|
||||
final String path = destFolder + File.separator + entry.getName();
|
||||
if (entry.isDirectory()) {
|
||||
new File(path).mkdir();
|
||||
progressBar.setValue(++count);
|
||||
continue;
|
||||
}
|
||||
copyInputStream(zipFile.getInputStream(entry), path);
|
||||
progressBar.setValue(++count);
|
||||
filesExtracted++;
|
||||
}
|
||||
catch (final Exception e) { //don't quit out completely if an entry is not UTF-8
|
||||
progressBar.setValue(++count);
|
||||
failedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (failedCount > 0) {
|
||||
Log.error("Downloading " + desc, failedCount + " " + desc + " could not be extracted");
|
||||
}
|
||||
|
||||
zipFile.close();
|
||||
new File(zipFilename).delete();
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
GuiBase.getInterface().preventSystemSleep(false);
|
||||
}
|
||||
extract(zipFilename);
|
||||
}
|
||||
|
||||
public String download(final String filename) {
|
||||
@@ -211,6 +146,75 @@ public class GuiDownloadZipService extends GuiDownloadService {
|
||||
}
|
||||
}
|
||||
|
||||
public void extract(String zipFilename) {
|
||||
//if assets.zip downloaded successfully, unzip into destination folder
|
||||
try {
|
||||
GuiBase.getInterface().preventSystemSleep(true); //prevent system from going into sleep mode while unzipping
|
||||
|
||||
if (deleteFolder != null) {
|
||||
final File deleteDir = new File(deleteFolder);
|
||||
if (deleteDir.exists()) {
|
||||
//attempt to delete previous res directory if to be rebuilt
|
||||
progressBar.reset();
|
||||
progressBar.setDescription("Deleting old " + desc + "...");
|
||||
if (deleteFolder.equals(destFolder)) { //move zip file to prevent deleting it
|
||||
final String oldZipFilename = zipFilename;
|
||||
zipFilename = deleteDir.getParentFile().getAbsolutePath() + File.separator + "temp.zip";
|
||||
Files.move(new File(oldZipFilename), new File(zipFilename));
|
||||
}
|
||||
FileUtil.deleteDirectory(deleteDir);
|
||||
}
|
||||
}
|
||||
|
||||
final ZipFile zipFile = new ZipFile(zipFilename);
|
||||
final Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
|
||||
progressBar.reset();
|
||||
progressBar.setPercentMode(true);
|
||||
progressBar.setDescription("Extracting " + desc);
|
||||
progressBar.setMaximum(zipFile.size());
|
||||
|
||||
FileUtil.ensureDirectoryExists(destFolder);
|
||||
|
||||
int count = 0;
|
||||
int failedCount = 0;
|
||||
while (entries.hasMoreElements()) {
|
||||
if (cancel) { break; }
|
||||
|
||||
try {
|
||||
final ZipEntry entry = entries.nextElement();
|
||||
|
||||
final String path = destFolder + File.separator + entry.getName();
|
||||
if (entry.isDirectory()) {
|
||||
new File(path).mkdir();
|
||||
progressBar.setValue(++count);
|
||||
continue;
|
||||
}
|
||||
copyInputStream(zipFile.getInputStream(entry), path);
|
||||
progressBar.setValue(++count);
|
||||
filesExtracted++;
|
||||
}
|
||||
catch (final Exception e) { //don't quit out completely if an entry is not UTF-8
|
||||
progressBar.setValue(++count);
|
||||
failedCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if (failedCount > 0) {
|
||||
Log.error("Downloading " + desc, failedCount + " " + desc + " could not be extracted");
|
||||
}
|
||||
|
||||
zipFile.close();
|
||||
new File(zipFilename).delete();
|
||||
}
|
||||
catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
GuiBase.getInterface().preventSystemSleep(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected void copyInputStream(final InputStream in, final String outPath) throws IOException {
|
||||
final byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package forge.itemmanager;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import forge.GuiBase;
|
||||
import forge.assets.FSkinProp;
|
||||
import forge.assets.IHasSkinProp;
|
||||
import forge.card.CardRules;
|
||||
@@ -35,7 +36,8 @@ public final class SItemManagerUtil {
|
||||
RED (FSkinProp.IMG_MANA_R, CardRulesPredicates.Presets.IS_RED, "lblRedcards"),
|
||||
GREEN (FSkinProp.IMG_MANA_G, CardRulesPredicates.Presets.IS_GREEN, "lblGreencards"),
|
||||
COLORLESS (FSkinProp.IMG_MANA_COLORLESS, CardRulesPredicates.Presets.IS_COLORLESS, "lblColorlesscards"),
|
||||
MULTICOLOR (FSkinProp.IMG_MULTI, CardRulesPredicates.Presets.IS_MULTICOLOR, "lblMulticolorcards"),
|
||||
MULTICOLOR (GuiBase.getInterface().isLibgdxPort() ? FSkinProp.IMG_HDMULTI :
|
||||
FSkinProp.IMG_MULTI, CardRulesPredicates.Presets.IS_MULTICOLOR, "lblMulticolorcards"),
|
||||
|
||||
PACK_OR_DECK (FSkinProp.IMG_PACK, null, "lblPackordeck"),
|
||||
LAND (FSkinProp.IMG_LAND, CardRulesPredicates.Presets.IS_LAND, "lblLands"),
|
||||
@@ -60,7 +62,8 @@ public final class SItemManagerUtil {
|
||||
DECK_RED (FSkinProp.IMG_MANA_R, null, "lblReddecks"),
|
||||
DECK_GREEN (FSkinProp.IMG_MANA_G, null, "lblGreendecks"),
|
||||
DECK_COLORLESS (FSkinProp.IMG_MANA_COLORLESS, null, "lblColorlessdecks"),
|
||||
DECK_MULTICOLOR (FSkinProp.IMG_MULTI, null, "lblMulticolordecks"),
|
||||
DECK_MULTICOLOR (GuiBase.getInterface().isLibgdxPort() ? FSkinProp.IMG_HDMULTI :
|
||||
FSkinProp.IMG_MULTI, null, "lblMulticolordecks"),
|
||||
|
||||
FOIL_OLD (FSkinProp.FOIL_11, null, "lblOldstyleFoilcards"),
|
||||
FOIL_NEW (FSkinProp.FOIL_01, null, "lblNewstyleFoilcards"),
|
||||
|
||||
@@ -28,6 +28,7 @@ import forge.card.CardType;
|
||||
import forge.deck.CardArchetypeLDAGenerator;
|
||||
import forge.deck.CardRelationMatrixGenerator;
|
||||
import forge.deck.io.DeckPreferences;
|
||||
import forge.download.AutoUpdater;
|
||||
import forge.game.GameFormat;
|
||||
import forge.game.GameType;
|
||||
import forge.game.card.CardUtil;
|
||||
@@ -117,7 +118,6 @@ public final class FModel {
|
||||
|
||||
Localizer.getInstance().initialize(FModel.getPreferences().getPref(FPref.UI_LANGUAGE), ForgeConstants.LANG_DIR);
|
||||
|
||||
//load card database
|
||||
final ProgressObserver progressBarBridge = (progressBar == null) ?
|
||||
ProgressObserver.emptyObserver : new ProgressObserver() {
|
||||
@Override
|
||||
@@ -143,6 +143,11 @@ public final class FModel {
|
||||
}
|
||||
};
|
||||
|
||||
if (new AutoUpdater(true).attemptToUpdate()) {
|
||||
//
|
||||
}
|
||||
|
||||
//load card database
|
||||
final CardStorageReader reader = new CardStorageReader(ForgeConstants.CARD_DATA_DIR, progressBarBridge,
|
||||
FModel.getPreferences().getPrefBoolean(FPref.LOAD_CARD_SCRIPTS_LAZILY));
|
||||
final CardStorageReader tokenReader = new CardStorageReader(ForgeConstants.TOKEN_DATA_DIR, progressBarBridge,
|
||||
@@ -220,8 +225,6 @@ public final class FModel {
|
||||
achievements.put(GameType.Quest, new QuestAchievements());
|
||||
achievements.put(GameType.PlanarConquest, new PlanarConquestAchievements());
|
||||
achievements.put(GameType.Puzzle, new PuzzleAchievements());
|
||||
|
||||
|
||||
|
||||
//preload AI profiles
|
||||
AiProfileUtil.loadAllProfiles(ForgeConstants.AI_PROFILE_DIR);
|
||||
|
||||
@@ -75,7 +75,7 @@ public enum ProtocolMethod {
|
||||
clearSelectables (Mode.SERVER),
|
||||
refreshField (Mode.SERVER),
|
||||
// TODO case "setPlayerAvatar":
|
||||
openZones (Mode.SERVER, PlayerZoneUpdates.class, Collection/*ZoneType*/.class, Map/*PlayerView,Object*/.class),
|
||||
openZones (Mode.SERVER, PlayerZoneUpdates.class, PlayerView.class, Collection/*ZoneType*/.class, Map/*PlayerView,Object*/.class),
|
||||
restoreOldZones (Mode.SERVER, Void.TYPE, PlayerView.class, PlayerZoneUpdates.class),
|
||||
isUiSetToSkipPhase (Mode.SERVER, Boolean.TYPE, PlayerView.class, PhaseType.class),
|
||||
setRememberedActions(Mode.SERVER, Void.TYPE),
|
||||
|
||||
@@ -105,10 +105,7 @@ public class HumanPlaySpellAbility {
|
||||
if (ability.isSpell() && !ability.isCastFaceDown() && fromState == CardStateName.FaceDown) {
|
||||
c.turnFaceUp();
|
||||
}
|
||||
c.setCastSA(ability);
|
||||
ability.setLastStateBattlefield(game.getLastStateBattlefield());
|
||||
ability.setLastStateGraveyard(game.getLastStateGraveyard());
|
||||
ability.setHostCard(game.getAction().moveToStack(c, null));
|
||||
ability.setHostCard(game.getAction().moveToStack(c, ability));
|
||||
}
|
||||
|
||||
if (!ability.isCopied()) {
|
||||
|
||||
@@ -746,7 +746,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
endTempShowCards();
|
||||
} else {
|
||||
getGui().message(MessageUtil.formatMessage(localizer.getMessage("lblThereNoCardInPlayerZone", "{player's}", zone.getTranslatedName().toLowerCase()),
|
||||
player, owner), fm);
|
||||
getLocalPlayerView(), owner), fm);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1181,7 +1181,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
|
||||
|
||||
@Override
|
||||
public Object vote(final SpellAbility sa, final String prompt, final List<Object> options,
|
||||
final ListMultimap<Object, Player> votes) {
|
||||
final ListMultimap<Object, Player> votes, Player forPlayer) {
|
||||
return getGui().one(prompt, options);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,10 +95,12 @@ public final class ForgeConstants {
|
||||
public static final String SPRITE_TROPHIES_FILE = "sprite_trophies.png";
|
||||
public static final String SPRITE_ABILITY_FILE = "sprite_ability.png";
|
||||
public static final String SPRITE_BORDER_FILE = "sprite_border.png";
|
||||
public static final String SPRITE_BUTTONS_FILE = "sprite_buttons.png";
|
||||
public static final String SPRITE_START_FILE = "sprite_start.png";
|
||||
public static final String SPRITE_MANAICONS_FILE = "sprite_manaicons.png";
|
||||
public static final String SPRITE_AVATARS_FILE = "sprite_avatars.png";
|
||||
public static final String SPRITE_SLEEVES_FILE = "sprite_sleeves.png";
|
||||
public static final String SPRITE_SLEEVES2_FILE = "sprite_sleeves2.png";
|
||||
public static final String SPRITE_SLEEVES2_FILE = "sprite_sleeves2.png";
|
||||
public static final String SPRITE_FAVICONS_FILE = "sprite_favicons.png";
|
||||
public static final String SPRITE_PLANAR_CONQUEST_FILE = "sprite_planar_conquest.png";
|
||||
public static final String FONT_FILE = "font1.ttf";
|
||||
|
||||
@@ -153,6 +153,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
||||
//TODO This should be removed after the update that requires Java 8.
|
||||
DISABLE_DISPLAY_JAVA_8_UPDATE_WARNING("false"),
|
||||
|
||||
AUTO_UPDATE("none"),
|
||||
USE_SENTRY("false"), // this controls whether automated bug reporting is done or not
|
||||
|
||||
MATCH_HOT_SEAT_MODE("false"), //this only applies to mobile game
|
||||
|
||||
@@ -6,6 +6,8 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import forge.FThreads;
|
||||
import forge.ImageKeys;
|
||||
@@ -45,21 +47,28 @@ public abstract class ImageFetcher {
|
||||
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
|
||||
// First try to download the LQ Set URL, then fetch from scryfall
|
||||
StringBuilder setDownload = new StringBuilder(ForgeConstants.URL_PIC_DOWNLOAD);
|
||||
setDownload.append(ImageUtil.getDownloadUrl(paperCard, backFace));
|
||||
downloadUrls.add(setDownload.toString());
|
||||
|
||||
int artIndex = 1;
|
||||
final Pattern pattern = Pattern.compile(
|
||||
"^.:([^|]*\\|){2}(\\d+).*$"
|
||||
);
|
||||
Matcher matcher = pattern.matcher(imageKey);
|
||||
if (matcher.matches()) {
|
||||
artIndex = Integer.parseInt(matcher.group(2));
|
||||
}
|
||||
final StaticData data = StaticData.instance();
|
||||
final int cardNum = data.getCommonCards().getCardCollectorNumber(paperCard.getName(), paperCard.getEdition());
|
||||
if (cardNum != -1) {
|
||||
final String cardNum = data.getCommonCards().getCardCollectorNumber(paperCard.getName(), paperCard.getEdition(), artIndex);
|
||||
if (cardNum != null) {
|
||||
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));
|
||||
downloadUrls.add(String.format("https://img.scryfall.com/cards/normal/en/%s/%s%s.jpg", editionMciCode, cardNum, suffix));
|
||||
}
|
||||
} else if (prefix.equals(ImageKeys.TOKEN_PREFIX)) {
|
||||
if (tokenImages == null) {
|
||||
|
||||
Reference in New Issue
Block a user