mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
Merge branch 'desktop-autoupdate' into 'master'
check for updates button See merge request core-developers/forge!2537
This commit is contained in:
@@ -23,6 +23,13 @@ public enum CSubmenuDownloaders implements ICDoc {
|
|||||||
VSubmenuDownloaders.SINGLETON_INSTANCE.showLicensing();
|
VSubmenuDownloaders.SINGLETON_INSTANCE.showLicensing();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
private final UiCommand cmdCheckForUpdates = new UiCommand() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
new AutoUpdater(false).attemptToUpdate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private final UiCommand cmdPicDownload = new UiCommand() {
|
private final UiCommand cmdPicDownload = new UiCommand() {
|
||||||
@Override public void run() {
|
@Override public void run() {
|
||||||
new GuiDownloader(new GuiDownloadPicturesLQ()).show();
|
new GuiDownloader(new GuiDownloadPicturesLQ()).show();
|
||||||
@@ -84,6 +91,7 @@ public enum CSubmenuDownloaders implements ICDoc {
|
|||||||
@Override
|
@Override
|
||||||
public void initialize() {
|
public void initialize() {
|
||||||
final VSubmenuDownloaders view = VSubmenuDownloaders.SINGLETON_INSTANCE;
|
final VSubmenuDownloaders view = VSubmenuDownloaders.SINGLETON_INSTANCE;
|
||||||
|
view.setCheckForUpdatesCommand(cmdCheckForUpdates);
|
||||||
view.setDownloadPicsCommand(cmdPicDownload);
|
view.setDownloadPicsCommand(cmdPicDownload);
|
||||||
view.setDownloadPicsHQCommand(cmdPicDownloadHQ);
|
view.setDownloadPicsHQCommand(cmdPicDownloadHQ);
|
||||||
view.setDownloadSetPicsCommand(cmdSetDownload);
|
view.setDownloadSetPicsCommand(cmdSetDownload);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package forge.screens.home.settings;
|
|||||||
import forge.*;
|
import forge.*;
|
||||||
import forge.ai.AiProfileUtil;
|
import forge.ai.AiProfileUtil;
|
||||||
import forge.control.FControl.CloseAction;
|
import forge.control.FControl.CloseAction;
|
||||||
|
import forge.download.AutoUpdater;
|
||||||
import forge.game.GameLogEntryType;
|
import forge.game.GameLogEntryType;
|
||||||
import forge.gui.framework.FScreen;
|
import forge.gui.framework.FScreen;
|
||||||
import forge.gui.framework.ICDoc;
|
import forge.gui.framework.ICDoc;
|
||||||
@@ -225,6 +226,7 @@ public enum CSubmenuPreferences implements ICDoc {
|
|||||||
initializeGameLogVerbosityComboBox();
|
initializeGameLogVerbosityComboBox();
|
||||||
initializeCloseActionComboBox();
|
initializeCloseActionComboBox();
|
||||||
initializeDefaultFontSizeComboBox();
|
initializeDefaultFontSizeComboBox();
|
||||||
|
initializeAutoUpdaterComboBox();
|
||||||
initializeMulliganRuleComboBox();
|
initializeMulliganRuleComboBox();
|
||||||
initializeAiProfilesComboBox();
|
initializeAiProfilesComboBox();
|
||||||
initializeStackAdditionsComboBox();
|
initializeStackAdditionsComboBox();
|
||||||
@@ -378,6 +380,16 @@ public enum CSubmenuPreferences implements ICDoc {
|
|||||||
panel.setComboBox(comboBox, selectedItem);
|
panel.setComboBox(comboBox, selectedItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initializeAutoUpdaterComboBox() {
|
||||||
|
// TODO: Ideally we would filter out update paths based on the type of Forge people have
|
||||||
|
final String[] updatePaths = AutoUpdater.updateChannels;
|
||||||
|
final FPref updatePreference = FPref.AUTO_UPDATE;
|
||||||
|
final FComboBoxPanel<String> panel = this.view.getCbpAutoUpdater();
|
||||||
|
final FComboBox<String> comboBox = createComboBox(updatePaths, updatePreference);
|
||||||
|
final String selectedItem = this.prefs.getPref(updatePreference);
|
||||||
|
panel.setComboBox(comboBox, selectedItem);
|
||||||
|
}
|
||||||
|
|
||||||
private void initializeMulliganRuleComboBox() {
|
private void initializeMulliganRuleComboBox() {
|
||||||
final String [] choices = MulliganDefs.getMulliganRuleNames();
|
final String [] choices = MulliganDefs.getMulliganRuleNames();
|
||||||
final FPref userSetting = FPref.MULLIGAN_RULE;
|
final FPref userSetting = FPref.MULLIGAN_RULE;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
private final JPanel pnlContent = new JPanel(new MigLayout("insets 0, gap 0, wrap, ay center"));
|
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 FScrollPane scrContent = new FScrollPane(pnlContent, false);
|
||||||
|
|
||||||
|
private final FLabel btnCheckForUpdates = _makeButton(localizer.getMessage("btnCheckForUpdates"));
|
||||||
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 btnDownloadPicsHQ = _makeButton(localizer.getMessage("btnDownloadPicsHQ"));
|
||||||
@@ -80,6 +81,9 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
|
|
||||||
if (javaRecentEnough()) {
|
if (javaRecentEnough()) {
|
||||||
|
|
||||||
|
pnlContent.add(btnCheckForUpdates, constraintsBTN);
|
||||||
|
pnlContent.add(_makeLabel(localizer.getMessage("lblCheckForUpdates")), constraintsLBL);
|
||||||
|
|
||||||
pnlContent.add(btnDownloadPics, constraintsBTN);
|
pnlContent.add(btnDownloadPics, constraintsBTN);
|
||||||
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPics")), constraintsLBL);
|
pnlContent.add(_makeLabel(localizer.getMessage("lblDownloadPics")), constraintsLBL);
|
||||||
|
|
||||||
@@ -162,6 +166,7 @@ public enum VSubmenuDownloaders implements IVSubmenu<CSubmenuDownloaders> {
|
|||||||
return EMenuGroup.SETTINGS;
|
return EMenuGroup.SETTINGS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setCheckForUpdatesCommand(UiCommand command) { btnCheckForUpdates.setCommand(command); }
|
||||||
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 setDownloadPicsHQCommand(UiCommand command) { btnDownloadPicsHQ.setCommand(command); }
|
||||||
public void setDownloadSetPicsCommand(UiCommand command) { btnDownloadSetPics.setCommand(command); }
|
public void setDownloadSetPicsCommand(UiCommand command) { btnDownloadSetPics.setCommand(command); }
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ import java.awt.event.FocusAdapter;
|
|||||||
import java.awt.event.FocusEvent;
|
import java.awt.event.FocusEvent;
|
||||||
import java.awt.event.KeyAdapter;
|
import java.awt.event.KeyAdapter;
|
||||||
import java.awt.event.KeyEvent;
|
import java.awt.event.KeyEvent;
|
||||||
import java.util.*;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,6 +123,7 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
|||||||
private final FComboBoxPanel<String> cbpCounterDisplayLocation =new FComboBoxPanel<>(localizer.getMessage("cbpCounterDisplayLocation")+":");
|
private final FComboBoxPanel<String> cbpCounterDisplayLocation =new FComboBoxPanel<>(localizer.getMessage("cbpCounterDisplayLocation")+":");
|
||||||
private final FComboBoxPanel<String> cbpGraveyardOrdering = new FComboBoxPanel<>(localizer.getMessage("cbpGraveyardOrdering")+":");
|
private final FComboBoxPanel<String> cbpGraveyardOrdering = new FComboBoxPanel<>(localizer.getMessage("cbpGraveyardOrdering")+":");
|
||||||
private final FComboBoxPanel<String> cbpDefaultLanguage = new FComboBoxPanel<>(localizer.getMessage("cbpSelectLanguage")+":");
|
private final FComboBoxPanel<String> cbpDefaultLanguage = new FComboBoxPanel<>(localizer.getMessage("cbpSelectLanguage")+":");
|
||||||
|
private final FComboBoxPanel<String> cbpAutoUpdater = new FComboBoxPanel<>(localizer.getMessage("cbpAutoUpdater")+":");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor.
|
* Constructor.
|
||||||
@@ -157,6 +158,10 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
|||||||
pnlPrefs.add(new SectionLabel(localizer.getMessage("GeneralConfiguration")), sectionConstraints);
|
pnlPrefs.add(new SectionLabel(localizer.getMessage("GeneralConfiguration")), sectionConstraints);
|
||||||
|
|
||||||
// language
|
// language
|
||||||
|
|
||||||
|
pnlPrefs.add(cbpAutoUpdater, comboBoxConstraints);
|
||||||
|
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlAutoUpdater")), descriptionConstraints);
|
||||||
|
|
||||||
pnlPrefs.add(cbpDefaultLanguage, comboBoxConstraints);
|
pnlPrefs.add(cbpDefaultLanguage, comboBoxConstraints);
|
||||||
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlSelectLanguage")), descriptionConstraints);
|
pnlPrefs.add(new NoteLabel(localizer.getMessage("nlSelectLanguage")), descriptionConstraints);
|
||||||
|
|
||||||
@@ -531,6 +536,10 @@ public enum VSubmenuPreferences implements IVSubmenu<CSubmenuPreferences> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final FComboBoxPanel<String> getCbpAutoUpdater() {
|
||||||
|
return cbpAutoUpdater;
|
||||||
|
}
|
||||||
|
|
||||||
/** @return {@link javax.swing.JCheckBox} */
|
/** @return {@link javax.swing.JCheckBox} */
|
||||||
public final JCheckBox getCbCompactMainMenu() {
|
public final JCheckBox getCbCompactMainMenu() {
|
||||||
return cbCompactMainMenu;
|
return cbCompactMainMenu;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public final class Main {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
System.out.println("Unknown mode.\nKnown mode is 'sim' ");
|
System.out.println("Unknown mode.\nKnown mode is 'sim', 'parse' ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ btnResetJavaFutureCompatibilityWarnings=Reset Java Compatibility Warnings
|
|||||||
btnClearImageCache=Clear Image Cache
|
btnClearImageCache=Clear Image Cache
|
||||||
btnTokenPreviewer=Token Previewer
|
btnTokenPreviewer=Token Previewer
|
||||||
btnCopyToClipboard=Copy to Clipboard
|
btnCopyToClipboard=Copy to Clipboard
|
||||||
|
cbpAutoUpdater=Auto updater
|
||||||
|
nlAutoUpdater=Select the release channel to use for updating Forge
|
||||||
cbpSelectLanguage=Language
|
cbpSelectLanguage=Language
|
||||||
nlSelectLanguage=Select Language (Excluded Game part. Still a work in progress) (RESTART REQUIRED)
|
nlSelectLanguage=Select Language (Excluded Game part. Still a work in progress) (RESTART REQUIRED)
|
||||||
cbRemoveSmall=Remove Small Creatures
|
cbRemoveSmall=Remove Small Creatures
|
||||||
@@ -180,6 +182,7 @@ KeyboardShortcuts=Keyboard Shortcuts
|
|||||||
#VSubmenuAchievements.java
|
#VSubmenuAchievements.java
|
||||||
lblAchievements=Achievements
|
lblAchievements=Achievements
|
||||||
#VSubmenuDownloaders.java
|
#VSubmenuDownloaders.java
|
||||||
|
btnCheckForUpdates=Check for Updates
|
||||||
btnDownloadSetPics=Download LQ Set Pictures
|
btnDownloadSetPics=Download LQ Set Pictures
|
||||||
btnDownloadPicsHQ=Download HQ Card Pictures (Very Slow!)
|
btnDownloadPicsHQ=Download HQ Card Pictures (Very Slow!)
|
||||||
btnDownloadPics=Download LQ Card Pictures
|
btnDownloadPics=Download LQ Card Pictures
|
||||||
@@ -192,6 +195,7 @@ btnImportPictures=Import Data
|
|||||||
btnHowToPlay=How To Play
|
btnHowToPlay=How To Play
|
||||||
btnDownloadPrices=Download Card Prices
|
btnDownloadPrices=Download Card Prices
|
||||||
btnLicensing=License Details
|
btnLicensing=License Details
|
||||||
|
lblCheckForUpdates=Check Forge server to see if there's a more recent release
|
||||||
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.
|
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)
|
||||||
|
|||||||
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");
|
String zipFilename = download("temp.zip");
|
||||||
if (zipFilename == null) { return; }
|
if (zipFilename == null) { return; }
|
||||||
|
|
||||||
//if assets.zip downloaded successfully, unzip into destination folder
|
extract(zipFilename);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String download(final String filename) {
|
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 {
|
protected void copyInputStream(final InputStream in, final String outPath) throws IOException {
|
||||||
final byte[] buffer = new byte[1024];
|
final byte[] buffer = new byte[1024];
|
||||||
int len;
|
int len;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import forge.card.CardType;
|
|||||||
import forge.deck.CardArchetypeLDAGenerator;
|
import forge.deck.CardArchetypeLDAGenerator;
|
||||||
import forge.deck.CardRelationMatrixGenerator;
|
import forge.deck.CardRelationMatrixGenerator;
|
||||||
import forge.deck.io.DeckPreferences;
|
import forge.deck.io.DeckPreferences;
|
||||||
|
import forge.download.AutoUpdater;
|
||||||
import forge.game.GameFormat;
|
import forge.game.GameFormat;
|
||||||
import forge.game.GameType;
|
import forge.game.GameType;
|
||||||
import forge.game.card.CardUtil;
|
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);
|
Localizer.getInstance().initialize(FModel.getPreferences().getPref(FPref.UI_LANGUAGE), ForgeConstants.LANG_DIR);
|
||||||
|
|
||||||
//load card database
|
|
||||||
final ProgressObserver progressBarBridge = (progressBar == null) ?
|
final ProgressObserver progressBarBridge = (progressBar == null) ?
|
||||||
ProgressObserver.emptyObserver : new ProgressObserver() {
|
ProgressObserver.emptyObserver : new ProgressObserver() {
|
||||||
@Override
|
@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,
|
final CardStorageReader reader = new CardStorageReader(ForgeConstants.CARD_DATA_DIR, progressBarBridge,
|
||||||
FModel.getPreferences().getPrefBoolean(FPref.LOAD_CARD_SCRIPTS_LAZILY));
|
FModel.getPreferences().getPrefBoolean(FPref.LOAD_CARD_SCRIPTS_LAZILY));
|
||||||
final CardStorageReader tokenReader = new CardStorageReader(ForgeConstants.TOKEN_DATA_DIR, progressBarBridge,
|
final CardStorageReader tokenReader = new CardStorageReader(ForgeConstants.TOKEN_DATA_DIR, progressBarBridge,
|
||||||
@@ -221,8 +226,6 @@ public final class FModel {
|
|||||||
achievements.put(GameType.PlanarConquest, new PlanarConquestAchievements());
|
achievements.put(GameType.PlanarConquest, new PlanarConquestAchievements());
|
||||||
achievements.put(GameType.Puzzle, new PuzzleAchievements());
|
achievements.put(GameType.Puzzle, new PuzzleAchievements());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//preload AI profiles
|
//preload AI profiles
|
||||||
AiProfileUtil.loadAllProfiles(ForgeConstants.AI_PROFILE_DIR);
|
AiProfileUtil.loadAllProfiles(ForgeConstants.AI_PROFILE_DIR);
|
||||||
|
|
||||||
|
|||||||
@@ -153,6 +153,7 @@ public class ForgePreferences extends PreferencesStore<ForgePreferences.FPref> {
|
|||||||
//TODO This should be removed after the update that requires Java 8.
|
//TODO This should be removed after the update that requires Java 8.
|
||||||
DISABLE_DISPLAY_JAVA_8_UPDATE_WARNING("false"),
|
DISABLE_DISPLAY_JAVA_8_UPDATE_WARNING("false"),
|
||||||
|
|
||||||
|
AUTO_UPDATE("none"),
|
||||||
USE_SENTRY("false"), // this controls whether automated bug reporting is done or not
|
USE_SENTRY("false"), // this controls whether automated bug reporting is done or not
|
||||||
|
|
||||||
MATCH_HOT_SEAT_MODE("false"), //this only applies to mobile game
|
MATCH_HOT_SEAT_MODE("false"), //this only applies to mobile game
|
||||||
|
|||||||
Reference in New Issue
Block a user