add mobile updater, update gdx natives

This commit is contained in:
Anthony Calosa
2024-10-25 11:41:06 +08:00
parent a0c865b4b3
commit 8c085bbd33
20 changed files with 1628 additions and 174 deletions

View File

@@ -1626,7 +1626,7 @@ public class ComputerUtil {
for (final Card c : all) { for (final Card c : all) {
// check if card is at least available to be played // check if card is at least available to be played
// further improvements might consider if AI has options to steal the spell by making it playable first // further improvements might consider if AI has options to steal the spell by making it playable first
if (c.getZone().getPlayer() != null && c.getZone().getPlayer() != defender && c.mayPlay(defender).isEmpty()) { if (c.getZone() != null && c.getZone().getPlayer() != null && c.getZone().getPlayer() != defender && c.mayPlay(defender).isEmpty()) {
continue; continue;
} }
for (final SpellAbility sa : c.getSpellAbilities()) { for (final SpellAbility sa : c.getSpellAbilities()) {

View File

@@ -26,6 +26,9 @@ public class CreatureEvaluator implements Function<Card, Integer> {
return evaluateCreature(c, true, true); return evaluateCreature(c, true, true);
} }
public int evaluateCreature(final Card c, final boolean considerPT, final boolean considerCMC) { public int evaluateCreature(final Card c, final boolean considerPT, final boolean considerCMC) {
//Card shouldn't be null and AI shouldn't crash since this is just score
if (c == null)
return 0;
int value = 80; int value = 80;
if (!c.isToken()) { if (!c.isToken()) {
value += addValue(20, "non-token"); // tokens should be worth less than actual cards value += addValue(20, "non-token"); // tokens should be worth less than actual cards

View File

@@ -34,6 +34,11 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>com.apptasticsoftware</groupId>
<artifactId>rssreader</artifactId>
<version>3.6.0</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -12,11 +12,9 @@ import java.util.Date;
import java.util.List; import java.util.List;
public class RSSReader { public class RSSReader {
public static String getCommitLog(Date buildDateOriginal, SimpleDateFormat dateFormat, Date max) { public static String getCommitLog(Date buildDateOriginal, Date maxDate) {
String message = ""; String message = "";
SimpleDateFormat simpleDate = dateFormat; SimpleDateFormat simpleDate = TextUtil.getSimpleDate();
if (simpleDate == null)
simpleDate = new SimpleDateFormat("E, MMM dd, yyyy - hh:mm:ss a");
try { try {
RssReader reader = new RssReader(); RssReader reader = new RssReader();
URL url = new URL("https://github.com/Card-Forge/forge/commits/master.atom"); URL url = new URL("https://github.com/Card-Forge/forge/commits/master.atom");
@@ -36,7 +34,7 @@ public class RSSReader {
Date feedDate = Date.from(zonedDateTime.toInstant()); Date feedDate = Date.from(zonedDateTime.toInstant());
if (buildDateOriginal != null && feedDate.before(buildDateOriginal)) if (buildDateOriginal != null && feedDate.before(buildDateOriginal))
continue; continue;
if (max != null && feedDate.after(max)) if (maxDate != null && feedDate.after(maxDate))
continue; continue;
logs.append(simpleDate.format(feedDate)).append(" | ").append(StringEscapeUtils.unescapeXml(title).replace("\n", "").replace(" ", "")).append("\n\n"); logs.append(simpleDate.format(feedDate)).append(" | ").append(StringEscapeUtils.unescapeXml(title).replace("\n", "").replace(" ", "")).append("\n\n");
if (c >= 15) if (c >= 15)

View File

@@ -29,6 +29,7 @@ import forge.item.PaperCard;
*/ */
public class TextUtil { public class TextUtil {
private static final StringBuilder changes = new StringBuilder(); private static final StringBuilder changes = new StringBuilder();
private static SimpleDateFormat simpleDate;
static ImmutableSortedMap<Integer,String> romanMap = ImmutableSortedMap.<Integer,String>naturalOrder() static ImmutableSortedMap<Integer,String> romanMap = ImmutableSortedMap.<Integer,String>naturalOrder()
.put(1000, "M").put(900, "CM") .put(1000, "M").put(900, "CM")
@@ -392,6 +393,11 @@ public class TextUtil {
} }
return out.toString(); return out.toString();
} }
public static SimpleDateFormat getSimpleDate() {
if (simpleDate == null)
simpleDate = new SimpleDateFormat("E, MMM dd, yyyy - hh:mm:ss a");
return simpleDate;
}
//format changelog //format changelog
public static String getFormattedChangelog(File changelog, String defaultLog) { public static String getFormattedChangelog(File changelog, String defaultLog) {
if (!changelog.exists()) if (!changelog.exists())
@@ -400,30 +406,9 @@ public class TextUtil {
try { try {
Calendar calendar = Calendar.getInstance(); Calendar calendar = Calendar.getInstance();
SimpleDateFormat original = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat original = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat formatted = new SimpleDateFormat("E, MMM dd, yyyy - hh:mm:ss a"); SimpleDateFormat formatted = getSimpleDate();
String offset = " GMT " + OffsetDateTime.now().getOffset(); String offset = " GMT " + OffsetDateTime.now().getOffset();
List<String> toformat = FileUtil.readAllLines(changelog, false); List<String> toformat = FileUtil.readAllLines(changelog, false);
/*for (String line : toformat) {
if (line.isEmpty() || line.startsWith("#") || line.length() < 4)
continue;
if (line.startsWith("[")) {
String datestring = line.substring(line.lastIndexOf(" *")+1).replace("*", "");
try {
original.setTimeZone(TimeZone.getTimeZone("UTC"));
Date toDate = original.parse(datestring);
calendar.setTime(toDate);
formatted.setTimeZone(TimeZone.getDefault());
changes += "\n(" + formatted.format(calendar.getTime()) + offset + ")\n\n";
} catch (Exception e2) {
changes += "\n(" + datestring + ")\n\n";
}
} else {
if (line.startsWith(" * "))
changes += "\n"+ StringEscapeUtils.unescapeXml(line);
else
changes += StringEscapeUtils.unescapeXml(line);
}
}*/
boolean skip = false; boolean skip = false;
int count = 0; int count = 0;
for (String line : toformat) { for (String line : toformat) {

View File

@@ -0,0 +1,113 @@
package forge.app;
import android.util.Xml;
import org.xmlpull.v1.XmlPullParser;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
public class AtomReader {
private static final String ns = null;
public List<Entry> parse(InputStream in) throws Exception {
try {
XmlPullParser parser = Xml.newPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
parser.setInput(in, "UTF-8");
parser.nextTag();
return readFeed(parser);
} finally {
in.close();
}
}
private List<Entry> readFeed(XmlPullParser parser) throws Exception {
List<Entry> entries = new ArrayList<>();
parser.require(XmlPullParser.START_TAG, ns, "feed");
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
// Starts by looking for the entry tag.
if (name.equals("entry")) {
entries.add(readEntry(parser));
} else {
skip(parser);
}
}
return entries;
}
private void skip(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException();
}
int depth = 1;
while (depth != 0) {
switch (parser.next()) {
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.START_TAG:
depth++;
break;
}
}
}
public static class Entry {
public final String title;
public final String updated;
private Entry(String title, String updated) {
this.title = title;
this.updated = updated;
}
}
private Entry readEntry(XmlPullParser parser) throws Exception {
parser.require(XmlPullParser.START_TAG, ns, "entry");
String title = null;
String updated = null;
while (parser.next() != XmlPullParser.END_TAG) {
if (parser.getEventType() != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("title")) {
title = readTitle(parser);
} else if (name.equals("updated")) {
updated = readUpdated(parser);
} else {
skip(parser);
}
}
return new Entry(title, updated);
}
private String readTitle(XmlPullParser parser) throws Exception {
parser.require(XmlPullParser.START_TAG, ns, "title");
String title = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "title");
return title;
}
private String readUpdated(XmlPullParser parser) throws Exception {
parser.require(XmlPullParser.START_TAG, ns, "updated");
String updated = readText(parser);
parser.require(XmlPullParser.END_TAG, ns, "updated");
return updated;
}
private String readText(XmlPullParser parser) throws Exception {
String result = "";
if (parser.next() == XmlPullParser.TEXT) {
result = parser.getText();
parser.nextTag();
}
return result;
}
}

View File

@@ -0,0 +1,49 @@
package forge.app;
import forge.util.TextUtil;
import org.apache.commons.text.StringEscapeUtils;
import java.io.InputStream;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class GitLogs {
public String getLatest(Date buildDateOriginal, Date maxDate) {
String message = "";
try {
URL url = new URL("https://github.com/Card-Forge/forge/commits/master.atom");
InputStream inputStream = url.openStream();
List<AtomReader.Entry> entries = new AtomReader().parse(inputStream);
StringBuilder logs = new StringBuilder();
SimpleDateFormat simpleDate = TextUtil.getSimpleDate();
SimpleDateFormat atomDate = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss");
int c = 0;
for (AtomReader.Entry entry : entries) {
if (entry.title == null)
continue;
String title = TextUtil.stripNonValidXMLCharacters(entry.title);
if (title.contains("Merge"))
continue;
if (entry.updated == null)
continue;
Date feedDate = atomDate.parse(entry.updated);
if (buildDateOriginal != null && feedDate.before(buildDateOriginal))
continue;
if (maxDate != null && feedDate.after(maxDate))
continue;
logs.append(simpleDate.format(feedDate)).append(" | ").append(StringEscapeUtils.unescapeXml(title).replace("\n", "").replace(" ", "")).append("\n\n");
if (c >= 15)
break;
c++;
}
if (logs.length() > 0)
message += ("\n\nLatest Changes:\n\n" + logs);
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
return message;
}
}

View File

@@ -71,6 +71,7 @@ import java.io.InputStreamReader;
import java.io.OutputStream; import java.io.OutputStream;
import java.text.Normalizer; import java.text.Normalizer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
public class Main extends ForgeAndroidApplication { public class Main extends ForgeAndroidApplication {
private AndroidAdapter Gadapter; private AndroidAdapter Gadapter;
@@ -633,6 +634,11 @@ public class Main extends ForgeAndroidApplication {
return versionString; return versionString;
} }
@Override
public String getLatestChanges(Date buildDateOriginal, Date maxDate) {
return new GitLogs().getLatest(buildDateOriginal, maxDate);
}
@Override @Override
public boolean openFile(String filename) { public boolean openFile(String filename) {
try { try {

View File

@@ -436,11 +436,6 @@
<artifactId>imageio-jpeg</artifactId> <artifactId>imageio-jpeg</artifactId>
<version>3.12.0</version> <version>3.12.0</version>
</dependency> </dependency>
<dependency>
<groupId>com.apptasticsoftware</groupId>
<artifactId>rssreader</artifactId>
<version>3.6.0</version>
</dependency>
</dependencies> </dependencies>
<profiles> <profiles>

View File

@@ -30,7 +30,7 @@ public enum CSubmenuDownloaders implements ICDoc {
SINGLETON_INSTANCE; SINGLETON_INSTANCE;
private final UiCommand cmdLicensing = VSubmenuDownloaders.SINGLETON_INSTANCE::showLicensing; private final UiCommand cmdLicensing = VSubmenuDownloaders.SINGLETON_INSTANCE::showLicensing;
private final UiCommand cmdCheckForUpdates = () -> new AutoUpdater(false).attemptToUpdate(CompletableFuture.supplyAsync(() -> RSSReader.getCommitLog(null, null, null))); private final UiCommand cmdCheckForUpdates = () -> new AutoUpdater(false).attemptToUpdate(CompletableFuture.supplyAsync(() -> RSSReader.getCommitLog(null, null)));
private final UiCommand cmdPicDownload = () -> new GuiDownloader(new GuiDownloadPicturesLQ()).show(); private final UiCommand cmdPicDownload = () -> new GuiDownloader(new GuiDownloadPicturesLQ()).show();
private final UiCommand cmdPicDownloadHQ = () -> new GuiDownloader(new GuiDownloadPicturesHQ()).show(); private final UiCommand cmdPicDownloadHQ = () -> new GuiDownloader(new GuiDownloadPicturesHQ()).show();

View File

@@ -420,7 +420,7 @@ public abstract class FTitleBarBase extends SkinnedMenuBar {
} }
} }
public class UpdaterButton extends TitleBarButton { public class UpdaterButton extends TitleBarButton {
final int MARQUEE_SPEED_DIV = 25; final int MARQUEE_SPEED_DIV = 15;
final int REPAINT_WITHIN_MS = 25; final int REPAINT_WITHIN_MS = 25;
final String displayText = FControl.instance.compareVersion(BuildInfo.getVersionString()); final String displayText = FControl.instance.compareVersion(BuildInfo.getVersionString());
private UpdaterButton() { private UpdaterButton() {
@@ -431,7 +431,7 @@ public abstract class FTitleBarBase extends SkinnedMenuBar {
@Override @Override
protected void onClick() { protected void onClick() {
try { try {
new AutoUpdater(false).attemptToUpdate(CompletableFuture.supplyAsync(() -> RSSReader.getCommitLog(null, null, null))); new AutoUpdater(false).attemptToUpdate(CompletableFuture.supplyAsync(() -> RSSReader.getCommitLog(null, null)));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -4,6 +4,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import org.robovm.apple.foundation.NSAutoreleasePool; import org.robovm.apple.foundation.NSAutoreleasePool;
@@ -78,6 +79,11 @@ public class Main extends IOSApplication.Delegate {
return "0.0"; return "0.0";
} }
@Override
public String getLatestChanges(Date buildDateOriginal, Date maxDate) {
return "";
}
@Override @Override
public boolean openFile(final String filename) { public boolean openFile(final String filename) {
return new IOSFiles().local(filename).exists(); return new IOSFiles().local(filename).exists();

View File

@@ -9,8 +9,6 @@ import com.badlogic.gdx.graphics.glutils.HdpiMode;
import com.badlogic.gdx.utils.SharedLibraryLoader; import com.badlogic.gdx.utils.SharedLibraryLoader;
import forge.Forge; import forge.Forge;
import forge.adventure.util.Config; import forge.adventure.util.Config;
import forge.assets.AssetsDownloader;
import forge.util.FileUtil;
import org.lwjgl.system.Configuration; import org.lwjgl.system.Configuration;
import java.nio.file.Files; import java.nio.file.Files;
@@ -28,16 +26,9 @@ public class GameLauncher {
if (!Files.exists(Paths.get(desktopModeAssetsDir + "res"))) if (!Files.exists(Paths.get(desktopModeAssetsDir + "res")))
desktopModeAssetsDir = "../forge-gui/";//try IDE run desktopModeAssetsDir = "../forge-gui/";//try IDE run
// Assets directory used when the game fully emulates smartphone/tablet mode (desktopMode = false), useful when debugging from IDE String assetsDir = "./";
String assetsDir;
if (!AssetsDownloader.SHARE_DESKTOP_ASSETS) {
assetsDir = "testAssets/";
FileUtil.ensureDirectoryExists(assetsDir);
} else {
assetsDir = "./";
if (!Files.exists(Paths.get(assetsDir + "res"))) if (!Files.exists(Paths.get(assetsDir + "res")))
assetsDir = "../forge-gui/"; assetsDir = "../forge-gui/";
}
// Place the file "switch_orientation.ini" to your assets folder to make the game switch to landscape orientation (unless desktopMode = true) // Place the file "switch_orientation.ini" to your assets folder to make the game switch to landscape orientation (unless desktopMode = true)
String switchOrientationFile = assetsDir + "switch_orientation.ini"; String switchOrientationFile = assetsDir + "switch_orientation.ini";

View File

@@ -2,10 +2,7 @@ package forge.app;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import forge.interfaces.IDeviceAdapter; import forge.interfaces.IDeviceAdapter;
import forge.util.BuildInfo; import forge.util.*;
import forge.util.FileUtil;
import forge.util.OperatingSystem;
import forge.util.RestartUtil;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import javax.imageio.ImageIO; import javax.imageio.ImageIO;
@@ -17,6 +14,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.Optional; import java.util.Optional;
public class Main { public class Main {
@@ -53,10 +51,23 @@ public class Main {
return versionString; return versionString;
} }
@Override
public String getLatestChanges(Date buildDateOriginal, Date max) {
return RSSReader.getCommitLog(buildDateOriginal, max);
}
@Override @Override
public boolean openFile(String filename) { public boolean openFile(String filename) {
try { try {
Desktop.getDesktop().open(new File(filename)); File installer = new File(filename);
if (installer.exists()) {
if (filename.endsWith(".jar")) {
installer.setExecutable(true, false);
Desktop.getDesktop().open(installer);
} else {
Desktop.getDesktop().open(installer.getParentFile());
}
}
return true; return true;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();

Binary file not shown.

View File

@@ -76,7 +76,7 @@ public class Forge implements ApplicationListener {
protected static ClosingScreen closingScreen; protected static ClosingScreen closingScreen;
protected static TransitionScreen transitionScreen; protected static TransitionScreen transitionScreen;
public static KeyInputAdapter keyInputAdapter; public static KeyInputAdapter keyInputAdapter;
private static boolean exited; private static boolean exited, initialized;
public boolean needsUpdate = false; public boolean needsUpdate = false;
public static boolean advStartup = false; public static boolean advStartup = false;
public static boolean safeToClose = true; public static boolean safeToClose = true;
@@ -199,7 +199,8 @@ public class Forge implements ApplicationListener {
} else { } else {
skinName = "default"; //use default skin if preferences file doesn't exist yet skinName = "default"; //use default skin if preferences file doesn't exist yet
} }
FSkin.loadLight(skinName, splashScreen); if (!initialized)
FSkin.loadLight(skinName, getSplashScreen());
textureFiltering = getForgePreferences().getPrefBoolean(FPref.UI_LIBGDX_TEXTURE_FILTERING); textureFiltering = getForgePreferences().getPrefBoolean(FPref.UI_LIBGDX_TEXTURE_FILTERING);
showFPS = getForgePreferences().getPrefBoolean(FPref.UI_SHOW_FPS); showFPS = getForgePreferences().getPrefBoolean(FPref.UI_SHOW_FPS);
@@ -223,40 +224,33 @@ public class Forge implements ApplicationListener {
if (totalDeviceRAM > 5000) //devices with more than 10GB RAM will have 600 Cache size, 400 Cache size for morethan 5GB RAM if (totalDeviceRAM > 5000) //devices with more than 10GB RAM will have 600 Cache size, 400 Cache size for morethan 5GB RAM
cacheSize = totalDeviceRAM > 10000 ? 600 : 400; cacheSize = totalDeviceRAM > 10000 ? 600 : 400;
} }
//init cache if (!initialized) {
ImageCache.initCache(cacheSize); initialized = true;
//load model on background thread (using progress bar to report progress)
FThreads.invokeInBackgroundThread(() -> {
//see if app or assets need updating
AssetsDownloader.checkForUpdates(splashScreen);
if (exited) {
return;
} //don't continue if user chose to exit or couldn't download required assets
Runnable runnable = () -> {
safeToClose = false; safeToClose = false;
ImageKeys.setIsLibGDXPort(GuiBase.getInterface().isLibgdxPort()); ImageKeys.setIsLibGDXPort(GuiBase.getInterface().isLibgdxPort());
FModel.initialize(splashScreen.getProgressBar(), null); FModel.initialize(getSplashScreen().getProgressBar(), null);
splashScreen.getProgressBar().setDescription(getLocalizer().getMessage("lblLoadingFonts")); getSplashScreen().getProgressBar().setDescription(getLocalizer().getMessage("lblLoadingFonts"));
FSkinFont.preloadAll(locale); FSkinFont.preloadAll(locale);
splashScreen.getProgressBar().setDescription(getLocalizer().getMessage("lblLoadingCardTranslations")); getSplashScreen().getProgressBar().setDescription(getLocalizer().getMessage("lblLoadingCardTranslations"));
CardTranslation.preloadTranslation(locale, ForgeConstants.LANG_DIR); CardTranslation.preloadTranslation(locale, ForgeConstants.LANG_DIR);
splashScreen.getProgressBar().setDescription(getLocalizer().getMessage("lblFinishingStartup")); getSplashScreen().getProgressBar().setDescription(getLocalizer().getMessage("lblFinishingStartup"));
//add reminder to preload //add reminder to preload
if (enablePreloadExtendedArt) { if (enablePreloadExtendedArt) {
if (autoCache) if (autoCache)
splashScreen.getProgressBar().setDescription(getLocalizer().getMessage("lblPreloadExtendedArt") + "\nDetected RAM: " + totalDeviceRAM + "MB. Cache size: " + cacheSize); getSplashScreen().getProgressBar().setDescription(getLocalizer().getMessage("lblPreloadExtendedArt") + "\nDetected RAM: " + totalDeviceRAM + "MB. Cache size: " + cacheSize);
else else
splashScreen.getProgressBar().setDescription(getLocalizer().getMessage("lblPreloadExtendedArt")); getSplashScreen().getProgressBar().setDescription(getLocalizer().getMessage("lblPreloadExtendedArt"));
} else { } else {
if (autoCache) if (autoCache)
splashScreen.getProgressBar().setDescription(getLocalizer().getMessage("lblFinishingStartup") + "\nDetected RAM: " + totalDeviceRAM + "MB. Cache size: " + cacheSize); getSplashScreen().getProgressBar().setDescription(getLocalizer().getMessage("lblFinishingStartup") + "\nDetected RAM: " + totalDeviceRAM + "MB. Cache size: " + cacheSize);
else else
splashScreen.getProgressBar().setDescription(getLocalizer().getMessage("lblFinishingStartup")); getSplashScreen().getProgressBar().setDescription(getLocalizer().getMessage("lblFinishingStartup"));
} }
Gdx.app.postRunnable(() -> { Gdx.app.postRunnable(() -> {
@@ -265,7 +259,10 @@ public class Forge implements ApplicationListener {
* get error: No OpenGL context found in the current thread. */ * get error: No OpenGL context found in the current thread. */
preloadExtendedArt(); preloadExtendedArt();
}); });
}); };
//see if app or assets need updating
FThreads.invokeInBackgroundThread(() -> AssetsDownloader.checkForUpdates(exited, runnable));
}
} }
public static boolean hasGamepad() { public static boolean hasGamepad() {
//Classic Mode Various Screen GUI are not yet supported, needs control mapping for each screens //Classic Mode Various Screen GUI are not yet supported, needs control mapping for each screens
@@ -282,6 +279,11 @@ public class Forge implements ApplicationListener {
public static Graphics getGraphics() { public static Graphics getGraphics() {
return graphics; return graphics;
} }
public static SplashScreen getSplashScreen() {
if (splashScreen == null)
splashScreen = new SplashScreen();
return splashScreen;
}
public static Scene getCurrentScene() { public static Scene getCurrentScene() {
return currentScene; return currentScene;
@@ -447,10 +449,10 @@ public class Forge implements ApplicationListener {
String path = "skin/cursor" + name + ".png"; String path = "skin/cursor" + name + ".png";
Pixmap pm = new Pixmap(Config.instance().getFile(path)); Pixmap pm = new Pixmap(Config.instance().getFile(path));
if (name == "0") { if ("0".equals(name)) {
cursorA0 = Gdx.graphics.newCursor(pm, 0, 0); cursorA0 = Gdx.graphics.newCursor(pm, 0, 0);
setGdxCursor(cursorA0); setGdxCursor(cursorA0);
} else if (name == "1") { } else if ("1".equals(name)) {
cursorA1 = Gdx.graphics.newCursor(pm, 0, 0); cursorA1 = Gdx.graphics.newCursor(pm, 0, 0);
setGdxCursor(cursorA1); setGdxCursor(cursorA1);
} else { } else {
@@ -461,20 +463,20 @@ public class Forge implements ApplicationListener {
pm.dispose(); pm.dispose();
return; return;
} }
if (!FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ENABLE_MAGNIFIER) && name != "0") if (!FModel.getPreferences().getPrefBoolean(ForgePreferences.FPref.UI_ENABLE_MAGNIFIER) && !"0".equals(name))
return; //don't change if it's disabled return; //don't change if it's disabled
if (currentScreen != null && !currentScreen.toString().toLowerCase().contains("match") && name != "0") if (currentScreen != null && !currentScreen.toString().toLowerCase().contains("match") && !"0".equals(name))
return; // cursor indicator should be during matches return; // cursor indicator should be during matches
if (textureRegion == null) { if (textureRegion == null) {
return; return;
} }
if (cursor0 != null && name == "0") { if (cursor0 != null && "0".equals(name)) {
setGdxCursor(cursor0); setGdxCursor(cursor0);
return; return;
} else if (cursor1 != null && name == "1") { } else if (cursor1 != null && "1".equals(name)) {
setGdxCursor(cursor1); setGdxCursor(cursor1);
return; return;
} else if (cursor2 != null && name == "2") { } else if (cursor2 != null && "2".equals(name)) {
setGdxCursor(cursor2); setGdxCursor(cursor2);
return; return;
} }
@@ -496,10 +498,10 @@ public class Forge implements ApplicationListener {
textureRegion.getRegionWidth(), // The width of the area from the other Pixmap in pixels textureRegion.getRegionWidth(), // The width of the area from the other Pixmap in pixels
textureRegion.getRegionHeight() // The height of the area from the other Pixmap in pixels textureRegion.getRegionHeight() // The height of the area from the other Pixmap in pixels
); );
if (name == "0") { if ("0".equals(name)) {
cursor0 = Gdx.graphics.newCursor(pm, 0, 0); cursor0 = Gdx.graphics.newCursor(pm, 0, 0);
setGdxCursor(cursor0); setGdxCursor(cursor0);
} else if (name == "1") { } else if ("1".equals(name)) {
cursor1 = Gdx.graphics.newCursor(pm, 0, 0); cursor1 = Gdx.graphics.newCursor(pm, 0, 0);
setGdxCursor(cursor1); setGdxCursor(cursor1);
} else { } else {
@@ -829,8 +831,10 @@ public class Forge implements ApplicationListener {
endKeyInput(); //end key input before switching screens endKeyInput(); //end key input before switching screens
ForgeAnimation.endAll(); //end all active animations before switching screens ForgeAnimation.endAll(); //end all active animations before switching screens
currentScreen = screen0; currentScreen = screen0;
if (currentScreen != null) {
currentScreen.setSize(screenWidth, screenHeight); currentScreen.setSize(screenWidth, screenHeight);
currentScreen.onActivate(); currentScreen.onActivate();
}
} catch (Exception ex) { } catch (Exception ex) {
graphics.end(); graphics.end();
//check if sentry is enabled, if not it will call the gui interface but here we end the graphics so we only send it via sentry.. //check if sentry is enabled, if not it will call the gui interface but here we end the graphics so we only send it via sentry..

View File

@@ -1,15 +1,18 @@
package forge.assets; package forge.assets;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.TimeZone;
import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.files.FileHandle;
import forge.gui.GuiBase; import forge.gui.GuiBase;
import forge.util.TextUtil;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.badlogic.gdx.Application.ApplicationType;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@@ -18,26 +21,27 @@ import forge.gui.FThreads;
import forge.gui.download.GuiDownloadZipService; import forge.gui.download.GuiDownloadZipService;
import forge.gui.util.SOptionPane; import forge.gui.util.SOptionPane;
import forge.localinstance.properties.ForgeConstants; import forge.localinstance.properties.ForgeConstants;
import forge.screens.SplashScreen;
import forge.util.FileUtil; import forge.util.FileUtil;
public class AssetsDownloader { public class AssetsDownloader {
public static final boolean SHARE_DESKTOP_ASSETS = true; //change to false to test downloading separate assets for desktop version
private final static ImmutableList<String> downloadIgnoreExit = ImmutableList.of("Download", "Ignore", "Exit"); private final static ImmutableList<String> downloadIgnoreExit = ImmutableList.of("Download", "Ignore", "Exit");
private final static ImmutableList<String> downloadExit = ImmutableList.of("Download", "Exit"); private final static ImmutableList<String> downloadExit = ImmutableList.of("Download", "Exit");
//if not sharing desktop assets, check whether assets are up to date //if not sharing desktop assets, check whether assets are up to date
public static void checkForUpdates(final SplashScreen splashScreen) { public static void checkForUpdates(boolean exited, Runnable runnable) {
if (Gdx.app.getType() == ApplicationType.Desktop && SHARE_DESKTOP_ASSETS) { return; } if (exited)
return;
final String packageSize = GuiBase.isAndroid() ? "160MB" : "270MB";
final String apkSize = "12MB";
final String versionString = Forge.getDeviceAdapter().getVersionString(); final String versionString = Forge.getDeviceAdapter().getVersionString();
final boolean isSnapshots = versionString.contains("SNAPSHOT"); final boolean isSnapshots = versionString.contains("SNAPSHOT");
final String snapsURL = "https://downloads.cardforge.org/dailysnapshots/"; final String snapsURL = "https://downloads.cardforge.org/dailysnapshots/";
final String releaseURL = "https://releases.cardforge.org/forge/forge-gui-android/"; final String releaseURL = "https://releases.cardforge.org/forge/forge-gui-android/";
final String versionText = isSnapshots ? snapsURL + "version.txt" : releaseURL + "version.txt"; final String versionText = isSnapshots ? snapsURL + "version.txt" : releaseURL + "version.txt";
FileHandle assetsDir = Gdx.files.absolute(ForgeConstants.ASSETS_DIR);
splashScreen.getProgressBar().setDescription("Checking for updates..."); FileHandle resDir = Gdx.files.absolute(ForgeConstants.RES_DIR);
boolean mandatory = false;
Forge.getSplashScreen().getProgressBar().setDescription("Checking for updates...");
String message; String message;
boolean connectedToInternet = Forge.getDeviceAdapter().isConnectedToInternet(); boolean connectedToInternet = Forge.getDeviceAdapter().isConnectedToInternet();
@@ -45,40 +49,96 @@ public class AssetsDownloader {
try { try {
URL versionUrl = new URL(versionText); URL versionUrl = new URL(versionText);
String version = FileUtil.readFileToString(versionUrl); String version = FileUtil.readFileToString(versionUrl);
String filename = "forge-android-" + version + "-signed-aligned.apk"; String filename = "";
String apkURL = isSnapshots ? snapsURL + filename : releaseURL + version + "/" + filename; String installerURL = "";
if (!StringUtils.isEmpty(version) && !versionString.equals(version)) { if (GuiBase.isAndroid()) {
splashScreen.prepareForDialogs(); filename = "forge-android-" + version + "-signed-aligned.apk";
installerURL = isSnapshots ? snapsURL + filename : releaseURL + version + "/" + filename;
} else {
filename = isSnapshots ? "forge-installer-" + version + ".jar" : "forge-gui-desktop-" + version + ".tar.bz2";
String releaseBZ2URL = "https://github.com/Card-Forge/forge/releases/download/forge-" + version + "/";
String snapsBZ2URL = "https://downloads.cardforge.org/dailysnapshots/";
installerURL = isSnapshots ? snapsBZ2URL : releaseBZ2URL;
}
//TODO build version
/*String buildver = "";
SimpleDateFormat DateFor = TextUtil.getSimpleDate();
Calendar calendar = Calendar.getInstance();
Date buildDateOriginal = null;
try {
FileHandle build = Gdx.files.classpath("build.txt");
if (build.exists()) {
SimpleDateFormat original = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
original.setTimeZone(TimeZone.getTimeZone("UTC"));
Date buildDate = original.parse(build.readString());
buildDateOriginal = original.parse(build.readString());
calendar.setTime(buildDate);
DateFor.setTimeZone(TimeZone.getDefault());
buildver = "\nForge Build: " + DateFor.format(calendar.getTime());
}
} catch (Exception e) {
e.printStackTrace();
}*/
if (!StringUtils.isEmpty(version) && !versionString.equals(version) && !versionString.equalsIgnoreCase("GIT")) {
Forge.getSplashScreen().prepareForDialogs();
message = "A new version of Forge is available (" + version + ").\n" + message = "A new version of Forge is available (" + version + ").\n" +
"You are currently on an older version (" + versionString + ").\n\n" + "You are currently on an older version (" + versionString + ").\n\n" +
"Would you like to update to the new version now?"; "Would you like to update to the new version now?";
if (!Forge.getDeviceAdapter().isConnectedToWifi()) { if (!Forge.getDeviceAdapter().isConnectedToWifi()) {
message += " If so, you may want to connect to wifi first. The download is around 12MB."; message += " If so, you may want to connect to wifi first. The download is around " + (GuiBase.isAndroid() ? apkSize : packageSize) + ".";
}
if (!GuiBase.isAndroid()) {
message += Forge.getDeviceAdapter().getLatestChanges(null, null);
} }
if (SOptionPane.showConfirmDialog(message, "New Version Available", "Update Now", "Update Later", true, true)) { if (SOptionPane.showConfirmDialog(message, "New Version Available", "Update Now", "Update Later", true, true)) {
String apkFile = new GuiDownloadZipService("", "update", apkURL, String installer = new GuiDownloadZipService("", "update", installerURL,
Forge.getDeviceAdapter().getDownloadsDir(), null, splashScreen.getProgressBar()).download(filename); Forge.getDeviceAdapter().getDownloadsDir(), null, Forge.getSplashScreen().getProgressBar()).download(filename);
if (apkFile != null) { if (installer != null) {
Forge.getDeviceAdapter().openFile(apkFile); Forge.getDeviceAdapter().openFile(installer);
Forge.isMobileAdventureMode = Forge.advStartup; Forge.isMobileAdventureMode = Forge.advStartup;
Forge.exitAnimation(false); Forge.exitAnimation(false);
return; return;
} }
SOptionPane.showOptionDialog("Could not download update. " + switch (SOptionPane.showOptionDialog("Could not download update. " +
"Press OK to proceed without update.", "Update Failed", null, ImmutableList.of("Ok")); "Press OK to proceed without update.", "Update Failed", null, ImmutableList.of("Ok"))) {
default:
if (!GuiBase.isAndroid()) {
run(runnable);
return;
} }
break;
}
}
} else {
if (!GuiBase.isAndroid())
run(runnable);
} }
} }
catch (Exception e) { catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
if (!GuiBase.isAndroid()) {
run(runnable);
return;
} }
} }
} else {
if (!GuiBase.isAndroid()) {
run(runnable);
return;
}
}
// non android don't have seperate package to check
if (!GuiBase.isAndroid()) {
run(runnable);
return;
}
// Android assets fallback
String build = "";
String log = "";
//see if assets need updating //see if assets need updating
if (GuiBase.isAndroid()) {
FileHandle resDir = Gdx.files.absolute(ForgeConstants.RES_DIR);
FileHandle assetsDir = Gdx.files.absolute(ForgeConstants.ASSETS_DIR);
FileHandle advBG = Gdx.files.absolute(ForgeConstants.DEFAULT_SKINS_DIR).child(ForgeConstants.ADV_TEXTURE_BG_FILE); FileHandle advBG = Gdx.files.absolute(ForgeConstants.DEFAULT_SKINS_DIR).child(ForgeConstants.ADV_TEXTURE_BG_FILE);
if (!advBG.exists()) { if (!advBG.exists()) {
FileHandle deleteVersion = assetsDir.child("version.txt"); FileHandle deleteVersion = assetsDir.child("version.txt");
@@ -88,25 +148,57 @@ public class AssetsDownloader {
if (deleteBuild.exists()) if (deleteBuild.exists())
deleteBuild.delete(); deleteBuild.delete();
} }
}
File versionFile = new File(ForgeConstants.ASSETS_DIR + "version.txt"); FileHandle versionFile = assetsDir.child("version.txt");
if (!versionFile.exists()) { if (!versionFile.exists()) {
try { try {
versionFile.createNewFile(); versionFile.file().createNewFile();
} }
catch (IOException e) { catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
Forge.isMobileAdventureMode = Forge.advStartup;
Forge.exitAnimation(false); //can't continue if this fails Forge.exitAnimation(false); //can't continue if this fails
return; return;
} }
} } else if (versionString.equals(FileUtil.readFileToString(versionFile.file())) && FSkin.getSkinDir() != null) {
else if (versionString.equals(FileUtil.readFileToString(versionFile)) && FSkin.getSkinDir() != null) { run(runnable);
return; //if version matches what had been previously saved and FSkin isn't requesting assets download, no need to download assets return; //if version matches what had been previously saved and FSkin isn't requesting assets download, no need to download assets
} }
splashScreen.prepareForDialogs(); //ensure colors set up for showing message dialogs FileHandle f = Gdx.files.classpath("build.txt");
FileHandle t = resDir.child("build.txt");
if (f.exists() && t.exists()) {
String buildString = f.readString();
String target = t.readString();
try {
Date buildDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(buildString);
Date targetDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(target);
// if res folder has same build date then continue loading assets
if (buildDate.equals(targetDate) && versionString.equals(FileUtil.readFileToString(versionFile.file()))) {
run(runnable);
return;
}
mandatory = true;
//format to local date
SimpleDateFormat original = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
original.setTimeZone(TimeZone.getTimeZone("UTC"));
targetDate = original.parse(target);
Calendar calendar = Calendar.getInstance();
calendar.setTime(targetDate);
SimpleDateFormat simpleDate = TextUtil.getSimpleDate();
simpleDate.setTimeZone(TimeZone.getDefault());
build += "Installed resources date: " + simpleDate.format(calendar.getTime()) + "\n\n";
log = Forge.getDeviceAdapter().getLatestChanges(null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
boolean canIgnoreDownload = FSkin.getAllSkins() != null; //don't allow ignoring download if resource files haven't been previously loaded Forge.getSplashScreen().prepareForDialogs(); //ensure colors set up for showing message dialogs
boolean canIgnoreDownload = resDir.exists() && FSkin.getAllSkins() != null && !FileUtil.readFileToString(versionFile.file()).isEmpty(); //don't allow ignoring download if resource files haven't been previously loaded
if (mandatory && connectedToInternet)
canIgnoreDownload = false;
if (!connectedToInternet) { if (!connectedToInternet) {
message = "Updated resource files cannot be downloaded due to lack of internet connection.\n\n"; message = "Updated resource files cannot be downloaded due to lack of internet connection.\n\n";
@@ -119,6 +211,7 @@ public class AssetsDownloader {
switch (SOptionPane.showOptionDialog(message, "No Internet Connection", null, ImmutableList.of("Ok"))) { switch (SOptionPane.showOptionDialog(message, "No Internet Connection", null, ImmutableList.of("Ok"))) {
default: { default: {
if (!canIgnoreDownload) { if (!canIgnoreDownload) {
Forge.isMobileAdventureMode = Forge.advStartup;
Forge.exitAnimation(false); //exit if can't ignore download Forge.exitAnimation(false); //exit if can't ignore download
} }
} }
@@ -128,7 +221,7 @@ public class AssetsDownloader {
//prompt user whether they wish to download the updated resource files //prompt user whether they wish to download the updated resource files
message = "There are updated resource files to download. " + message = "There are updated resource files to download. " +
"This download is around 50MB, "; "This download is around " + packageSize + ", ";
if (Forge.getDeviceAdapter().isConnectedToWifi()) { if (Forge.getDeviceAdapter().isConnectedToWifi()) {
message += "which shouldn't take long if your wifi connection is good."; message += "which shouldn't take long if your wifi connection is good.";
} }
@@ -145,13 +238,18 @@ public class AssetsDownloader {
options = downloadExit; options = downloadExit;
} }
switch (SOptionPane.showOptionDialog(message, "", null, options)) { switch (SOptionPane.showOptionDialog(message + build + log, "", null, options)) {
case 1: case 1:
if (!canIgnoreDownload) { if (!canIgnoreDownload) {
Forge.isMobileAdventureMode = Forge.advStartup;
Forge.exitAnimation(false); //exit if can't ignore download Forge.exitAnimation(false); //exit if can't ignore download
}
return; return;
} else {
run(runnable);
return;
}
case 2: case 2:
Forge.isMobileAdventureMode = Forge.advStartup;
Forge.exitAnimation(false); Forge.exitAnimation(false);
return; return;
} }
@@ -160,7 +258,7 @@ public class AssetsDownloader {
boolean allowDeletion = Forge.androidVersion < 30 || GuiBase.isUsingAppDirectory(); boolean allowDeletion = Forge.androidVersion < 30 || GuiBase.isUsingAppDirectory();
String assetURL = isSnapshots ? snapsURL + "assets.zip" : releaseURL + versionString + "/" + "assets.zip"; String assetURL = isSnapshots ? snapsURL + "assets.zip" : releaseURL + versionString + "/" + "assets.zip";
new GuiDownloadZipService("", "resource files", assetURL, new GuiDownloadZipService("", "resource files", assetURL,
ForgeConstants.ASSETS_DIR, ForgeConstants.RES_DIR, splashScreen.getProgressBar(), allowDeletion).downloadAndUnzip(); ForgeConstants.ASSETS_DIR, ForgeConstants.RES_DIR, Forge.getSplashScreen().getProgressBar(), allowDeletion).downloadAndUnzip();
if (allowDeletion) if (allowDeletion)
FSkinFont.deleteCachedFiles(); //delete cached font files in case any skin's .ttf file changed FSkinFont.deleteCachedFiles(); //delete cached font files in case any skin's .ttf file changed
@@ -168,18 +266,37 @@ public class AssetsDownloader {
//reload light version of skin after assets updated //reload light version of skin after assets updated
FThreads.invokeInEdtAndWait(() -> { FThreads.invokeInEdtAndWait(() -> {
FSkinFont.updateAll(); //update all fonts used by splash screen FSkinFont.updateAll(); //update all fonts used by splash screen
FSkin.loadLight(FSkin.getName(), splashScreen); FSkin.loadLight(FSkin.getName(), Forge.getSplashScreen());
}); });
//save version string to file once assets finish downloading //save version string to file once assets finish downloading
//so they don't need to be re-downloaded until you upgrade again //so they don't need to be re-downloaded until you upgrade again
FileUtil.writeFile(versionFile, versionString); if (connectedToInternet) {
if (versionFile.exists())
//add restart after assets update FileUtil.writeFile(versionFile.file(), versionString);
String msg = allowDeletion ? "Resource update finished..." : "Forge misses some files for deletion.\nIf you encounter issues, try deleting the Forge/res folder and/or deleting Forge/cache/fonts folder and try to download and update the assets."; }
switch (SOptionPane.showOptionDialog(msg, "", null, ImmutableList.of("Restart"))) { //final check if temp.zip exists then extraction is not complete...
default: FileHandle check = assetsDir.child("temp.zip");
if (check.exists()) {
if (versionFile.exists())
versionFile.delete();
check.delete();
}
// auto restart after update
Forge.isMobileAdventureMode = Forge.advStartup;
Forge.exitAnimation(true); Forge.exitAnimation(true);
} }
private static void run(Runnable toRun) {
if (toRun != null) {
if (!GuiBase.isAndroid()) {
Forge.getSplashScreen().getProgressBar().setDescription("Loading game resources...");
}
FThreads.invokeInBackgroundThread(toRun);
return;
}
if (!GuiBase.isAndroid()) {
Forge.isMobileAdventureMode = Forge.advStartup;
Forge.exitAnimation(false);
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -88,7 +88,7 @@ public class AutoUpdater {
return false; return false;
} else if (updateChannel.equals("none")) { } else if (updateChannel.equals("none")) {
String message = localizer.getMessage("lblYouHaventSetUpdateChannel"); String message = localizer.getMessage("lblYouHaventSetUpdateChannel");
List<String> options = ImmutableList.of(localizer.getMessage("lblCancel"), localizer.getMessage("lblRelease"), localizer.getMessage("lblSnapshot")); List<String> options = ImmutableList.of(localizer.getMessageorUseDefault("lblCancel", "Cancel"), localizer.getMessageorUseDefault("lblRelease", "Release"), localizer.getMessageorUseDefault("lblSnapshot", "Snapshot"));
int option = SOptionPane.showOptionDialog(message, localizer.getMessage("lblManualCheck"), null, options, 0); int option = SOptionPane.showOptionDialog(message, localizer.getMessage("lblManualCheck"), null, options, 0);
if (option < 1) { if (option < 1) {
return false; return false;
@@ -97,14 +97,14 @@ public class AutoUpdater {
} }
if (buildVersion.contains("SNAPSHOT")) { if (buildVersion.contains("SNAPSHOT")) {
if (!updateChannel.equalsIgnoreCase(localizer.getMessage("lblSnapshot"))) { if (!updateChannel.equalsIgnoreCase(localizer.getMessageorUseDefault("lblSnapshot", "Snapshot"))) {
System.out.println("Snapshot build versions must use snapshot update channel to work"); System.out.println("Snapshot build versions must use snapshot update channel to work");
return false; return false;
} }
versionUrlString = SNAPSHOT_VERSION_INDEX + "version.txt"; versionUrlString = SNAPSHOT_VERSION_INDEX + "version.txt";
} else { } else {
if (!updateChannel.equalsIgnoreCase(localizer.getMessage("lblRelease"))) { if (!updateChannel.equalsIgnoreCase(localizer.getMessageorUseDefault("lblRelease", "Release"))) {
System.out.println("Release build versions must use release update channel to work"); System.out.println("Release build versions must use release update channel to work");
return false; return false;
} }
@@ -151,13 +151,13 @@ public class AutoUpdater {
} }
private void retrieveVersion() throws MalformedURLException { private void retrieveVersion() throws MalformedURLException {
if (VERSION_FROM_METADATA && updateChannel.equalsIgnoreCase(localizer.getMessage("lblRelease"))) { if (VERSION_FROM_METADATA && updateChannel.equalsIgnoreCase(localizer.getMessageorUseDefault("lblRelease", "Release"))) {
extractVersionFromMavenRelease(); extractVersionFromMavenRelease();
} else { } else {
URL versionUrl = new URL(versionUrlString); URL versionUrl = new URL(versionUrlString);
version = FileUtil.readFileToString(versionUrl); version = FileUtil.readFileToString(versionUrl);
} }
if (updateChannel.equalsIgnoreCase(localizer.getMessage("lblRelease"))) { if (updateChannel.equalsIgnoreCase(localizer.getMessageorUseDefault("lblRelease", "Release"))) {
packageUrl = RELEASE_VERSION_INDEX + "forge/forge-gui-desktop/" + version + "/forge-gui-desktop-" + version + ".tar.bz2"; packageUrl = RELEASE_VERSION_INDEX + "forge/forge-gui-desktop/" + version + "/forge-gui-desktop-" + version + ".tar.bz2";
} else { } else {
packageUrl = SNAPSHOT_VERSION_INDEX + "forge-installer-" + version + ".jar"; packageUrl = SNAPSHOT_VERSION_INDEX + "forge-installer-" + version + ".jar";

View File

@@ -6,6 +6,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
public interface IDeviceAdapter { public interface IDeviceAdapter {
boolean isConnectedToInternet(); boolean isConnectedToInternet();
@@ -13,6 +14,7 @@ public interface IDeviceAdapter {
boolean isTablet(); boolean isTablet();
String getDownloadsDir(); String getDownloadsDir();
String getVersionString(); String getVersionString();
String getLatestChanges(Date buildDateOriginal, Date maxDate);
boolean openFile(String filename); boolean openFile(String filename);
void setLandscapeMode(boolean landscapeMode); void setLandscapeMode(boolean landscapeMode);
void preventSystemSleep(boolean preventSleep); void preventSystemSleep(boolean preventSleep);