diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EUpdateBranch.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EUpdateBranch.java new file mode 100644 index 000000000..09da806d5 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/config/EUpdateBranch.java @@ -0,0 +1,7 @@ +package com.seibel.distanthorizons.api.enums.config; + +public enum EUpdateBranch +{ + STABLE, + NIGHTLY +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index 99de6a13f..fb0438dea 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -21,20 +21,16 @@ package com.seibel.distanthorizons.core.config; import com.seibel.distanthorizons.api.enums.config.*; +import com.seibel.distanthorizons.api.enums.config.quickOptions.*; import com.seibel.distanthorizons.api.enums.rendering.*; -import com.seibel.distanthorizons.api.enums.config.quickOptions.EQualityPreset; -import com.seibel.distanthorizons.api.enums.config.quickOptions.EThreadPreset; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode; -import com.seibel.distanthorizons.core.config.eventHandlers.QuickRenderToggleConfigEventHandler; -import com.seibel.distanthorizons.core.config.eventHandlers.RenderCacheConfigEventHandler; -import com.seibel.distanthorizons.core.config.eventHandlers.UnsafeValuesConfigListener; -import com.seibel.distanthorizons.core.config.eventHandlers.WorldCurvatureConfigEventHandler; -import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler; -import com.seibel.distanthorizons.core.config.eventHandlers.presets.RenderQualityPresetConfigEventHandler; +import com.seibel.distanthorizons.core.config.eventHandlers.*; +import com.seibel.distanthorizons.core.config.eventHandlers.presets.*; import com.seibel.distanthorizons.core.config.types.*; -import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance; -import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryPerformance; +import com.seibel.distanthorizons.core.config.types.enums.*; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; import org.apache.logging.log4j.Logger; @@ -997,7 +993,9 @@ public class Config public static class AutoUpdater { public static ConfigEntry enableAutoUpdater = new ConfigEntry.Builder() - .set(!ModInfo.IS_DEV_BUILD) // hide the update notification in dev builds + .set( + !SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class).getInstallationDirectory().getName().equals("run") // Guesses that a dev would use the directory called "run" as their running directory, and clients wont + ) // disable the update notification in dev clients .comment("" + "Automatically check for updates on game launch?") .build(); @@ -1005,10 +1003,16 @@ public class Config public static ConfigEntry enableSilentUpdates = new ConfigEntry.Builder() .set(false) .comment("" - + "Should Distant Horizons silently, automatically download and install new versions? " - + "") + + "Should Distant Horizons silently, automatically download and install new versions?") .build(); + public static ConfigEntry updateBranch = new ConfigEntry.Builder() + .set( + ModInfo.IS_DEV_BUILD? EUpdateBranch.NIGHTLY: EUpdateBranch.STABLE // If it's already a nightly build, then download the nightly build ofc + ) + .comment("" + + " If DH should use the nightly (provided by Gitlab), or stable (provided by Modrinth) build") + .build(); } public static class Logging diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/GitlabGetter.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/GitlabGetter.java index 90a39805f..3ec49a9d4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/GitlabGetter.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/GitlabGetter.java @@ -19,187 +19,133 @@ package com.seibel.distanthorizons.core.jar.installer; +import com.electronwill.nightconfig.core.Config; + import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; +import java.util.*; /** - * Gets the releases available on gitlab and sends out the link. - * Please move over to ModrinthGetter for downloading releases of the mod + * Gets info for nightly builds * * @author coolGi */ -// TODO: Change this to a way to get the nightly builds -@Deprecated public class GitlabGetter { - public static final String GitLabApi = "https://gitlab.com/api/v4/projects/"; - public static final String projectID = "18204078"; -// public static JSONArray projectRelease = new JSONArray(); + /** DH's instance of the Gitlab getter */ + public static GitlabGetter INSTANCE = new GitlabGetter(); - public static List releaseNames = new ArrayList<>(); // This list contains the release ID's - public static List readableReleaseNames = new ArrayList<>(); // This list contains the readable names of the ID's - private static List mcVersionReleases = new ArrayList<>(); // A list of all minecraft releases + public static final String GitlabApi = "https://gitlab.com/api/v4/projects/"; + /** Gitlab project ID (can by gotten by typing `document.getElementById('project_id').value` on your main project's console) */ + public final String projectID; + /** Combines the {@link GitlabGetter#GitlabApi} and {@link GitlabGetter#projectID} into one var (Followed by a "/" at the end) */ + public final String GitProjID; + public ArrayList projectPipelines; + /** Commit sha; Commit info */ + private static final Map commitInfo = new HashMap<>(); + /** Pipeline ID; Pipeline info */ + private static final Map> pipelineInfo = new HashMap<>(); - - public static void init() + /** Uses our projectID to init this */ + public GitlabGetter() { -// try { -// // TODO: Modify the projectRelease to fix 1.6.0a's versions rather than fixing it everytime we want to use projectReleases -// projectRelease = (JSONArray) new JSONParser().parse(WebDownloader.downloadAsString(new URL(GitLabApi+projectID+"/releases"))); -// -// for (int i = 0; i < projectRelease.size(); i++) { -// JSONObject currentRelease = (JSONObject) projectRelease.get(i); -// if (!currentRelease.get("tag_name").toString().contains("-1.6.0a")) { // We have to do this cus 1.6.0a stuffed up some ordering -// releaseNames.add(currentRelease.get("tag_name").toString()); -// if (currentRelease.get("tag_name").toString().startsWith("1.16.4") || currentRelease.get("tag_name").toString().startsWith("1.16.5")) { -// // We want to do this to remove the mc version from the start of the name in 1.5.4 and prior -// readableReleaseNames.add(currentRelease.get("name").toString().replace("1.16.4 ","").replace("1.16.5 ","")); -// } else { -// readableReleaseNames.add(currentRelease.get("name").toString()); -// } -// } else if (!releaseNames.contains("1.6.0a")) { -// releaseNames.add("1.6.0a"); -// readableReleaseNames.add("Alpha 1.6.0"); -// } -// } -// -// // Some tests for getting the release versions -//// System.out.println(getRelease("1.6.3a", "1.18.2")); -//// System.out.println(getRelease("1.16.4-a1.2", null)); // The oldest downloadable version is 1.2 as versions before that didn't include downloads -// -// // Set the mcVersionReleases -// JSONArray minecraftReleases = (JSONArray) ((JSONObject) new JSONParser().parse(WebDownloader.downloadAsString(new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json")))).get("versions"); -// for (int i = 0; i < minecraftReleases.size(); i++) { -// JSONObject jsonObject = (JSONObject) minecraftReleases.get(i); -// if (jsonObject.get("type").toString().equals("release")) -// mcVersionReleases.add(jsonObject.get("id").toString()); -// } -// -// // Some tests to get minecraft versions available in that version of the mod -//// System.out.println(getMcVersionsInRelease("1.6.5a")); -//// System.out.println(getMcVersionsInRelease("1.16.4-a1.2")); -// } catch (Exception e) { e.printStackTrace(); } + this("18204078"); } - /** Gets the compatible minecraft versions a release of the mod works with */ - public static List getMcVersionsInRelease(String version) + public GitlabGetter(String projectID) { - List versions = new ArrayList<>(); -// -// JSONArray releaseArray = getScuffedReleaseArray(version); -// -// -// for (int i = 0; i < releaseArray.size(); i++) { -// String name = ((JSONObject) releaseArray.get(i)).get("name").toString(); -// for (String mcVersion : mcVersionReleases) { -// if (name.contains(mcVersion)) { -// versions.add(mcVersion); -// break; -// } -// } -// } -// -// // Sort it so the newest versions of minecraft are at the top -// Collections.sort(versions); -// Collections.reverse(versions); + this.projectID = projectID; + this.GitProjID = GitlabApi + projectID + "/"; - return versions; + try + { + this.projectPipelines = WebDownloader.parseWebJsonList(this.GitProjID + "pipelines"); + } + catch (Exception e) { e.printStackTrace(); } } - /** Gets the url to the download of a release of the mod */ - public static URL getRelease(String version, String mcVersion) + + public Config getCommitInfo(String commit) { -// JSONArray releaseArray = getScuffedReleaseArray(version); -// -// if (mcVersion != null) { -// for (int i = 0; i < releaseArray.size(); i++) { -// if (((JSONObject) releaseArray.get(i)).get("name").toString().contains(mcVersion)) { // With the way our GitLab releases is set up, the only way to check the mc version is to check if it is in the name -// try { -// return new URL(((JSONObject) releaseArray.get(i)).get("direct_asset_url").toString()); -// } catch (Exception e) { e.printStackTrace(); } -// } -// } -// } else { -// // If version is null it gets the first version available -// try { -// return new URL(((JSONObject) releaseArray.get(0)).get("direct_asset_url").toString()); -// } catch (Exception e) { e.printStackTrace(); } -// } + if (!commitInfo.containsKey(commit)) + { + try + { + commitInfo.put(commit, WebDownloader.parseWebJson(this.GitProjID + "repository/commits/" + commit)); + } + catch (Exception e) + { + e.printStackTrace(); + // Return empty + return Config.inMemory(); + } + } - return null; + return commitInfo.get(commit); } - /** Gets the update log of a release */ - public static String getVersionDescription(String version) + + public ArrayList getPipelineInfo(int pipeline) { -// try { -// if (!version.equals("1.6.0a")) { // We have to do this cus 1.6.0a stuffed up some ordering -// // Do this hack to remove all the mcVer-1.6.0a items from the releaseNames -// int newVer = releaseNames.indexOf(version); -// if (releaseNames.indexOf(version) > releaseNames.size()-14) -// newVer += 2; -// -// return ((JSONObject) projectRelease.get(newVer)).get("description").toString(); -// } else { -// for (int i = 0; i < projectRelease.size(); i++) { -// JSONObject currentRelease = ((JSONObject) new JSONParser().parse(projectRelease.get(i).toString())); -// if (currentRelease.get("tag_name").toString().contains("-1.6.0a")) -// return currentRelease.get("description").toString(); -// } -// } -// } catch (Exception e) { -// e.printStackTrace(); -// } - return null; + if (!pipelineInfo.containsKey(pipeline)) + { + try + { + pipelineInfo.put(pipeline, WebDownloader.parseWebJsonList(this.GitProjID + "pipelines/" + pipeline + "/jobs")); + } + catch (Exception e) + { + e.printStackTrace(); + // Return empty + return new ArrayList<>(); + } + } + + return pipelineInfo.get(pipeline); + } + + /** + * Gets all the Minecraft download links to a pipeline ID + * + * @return Minecraft version; Download URL + */ + public Map getDownloads(int pipelineID) + { + Map downloads = new HashMap<>(); + ArrayList currentPipelineInfo = this.getPipelineInfo(pipelineID); + + try + { + for (Config cfg : currentPipelineInfo) + { + if (!cfg.get("stage").equals("build")) + continue; + downloads.put( + ((String) cfg.get("name")).split("\\[|\\]")[1], // Regex to extract the Minecraft version from the text + new URL(this.GitProjID + "jobs/" + cfg.get("id") + "/artifacts") + ); + } + } + catch (Exception e) { e.printStackTrace(); } + + return downloads; + } + + // Just a small test for this (Should output the nightly for each version that it supports) + public static void main(String[] args) { + GitlabGetter gitlabGetter = new GitlabGetter(); + + System.out.println(gitlabGetter.getDownloads(gitlabGetter.projectPipelines.get(0).get("id"))); + } + + + + /** + * A simple url getter for the latest jar of a version + * @apiNote Not dependent on the instance of this object, will just download the one for the base mod + */ + public static URL getLatestForVersion(String mcVer) + { + try { + return new URL("https://gitlab.com/jeseibel/minecraft-lod-mod/-/jobs/artifacts/main/download?job=build:%20[" + mcVer + "]"); + } catch (Exception e) { e.printStackTrace(); return null; } // This should always be safe (unless you stuff up **badly** somewhere) } - - -// public static JSONArray getScuffedReleaseArray(String version) { -// // Get the asset links of the releases -// JSONArray releaseArray = new JSONArray(); -// -// if (!version.equals("1.6.0a")) { // We have to do this cus 1.6.0a stuffed up some ordering -// try { -// // Do this hack to remove all the mcVer-1.6.0a items from the releaseNames -// int newVer = releaseNames.indexOf(version); -// if (releaseNames.indexOf(version) > releaseNames.size()-14) -// newVer += 2; -// -// releaseArray = ( -// ((JSONArray) -// ((JSONObject) -// ((JSONObject) -// projectRelease.get(newVer) -// ).get("assets") -// ).get("links"))); -// } catch (Exception e) { -// System.out.println("ERROR: Release [" + version + "] is not a valid release. Printing stacktrace..."); -// e.printStackTrace(); -// return null; -// } -// } else { -// try { -// for (int i = 0; i < projectRelease.size(); i++) { -// JSONObject currentRelease = ((JSONObject) new JSONParser().parse(projectRelease.get(i).toString())); -// if (currentRelease.get("tag_name").toString().contains("-1.6.0a")) { -// releaseArray.add( -// ((JSONArray) -// ((JSONObject) -// currentRelease.get("assets") -// ).get("links") -// ).get(0) -// ); -// } -// } -// } catch (Exception e) { -// e.printStackTrace(); -// return null; -// } -// } -// -// return releaseArray; -// } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/ModrinthGetter.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/ModrinthGetter.java index 8d2976a1c..6580e7f4b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/ModrinthGetter.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/ModrinthGetter.java @@ -30,36 +30,24 @@ import java.util.*; * * @author coolGi */ -// TODO: Fix stuff in here (check how to do stuff with `[{jsonStuff},{jsonStuff}]` which needs to be remade with nightconfig's json public class ModrinthGetter { public static final String ModrinthAPI = "https://api.modrinth.com/v2/project/"; public static final String projectID = "distanthorizons"; + /** Functions should only be accessed once this is true */ public static boolean initted = false; public static ArrayList projectRelease; public static Map idToJson = new HashMap<>(); public static List releaseID = new ArrayList<>(); // This list contains the release ID's public static List mcVersions = new ArrayList<>(); // List of available Minecraft versions in the mod - /** - * Arg 1 = Release ID; - * Arg 2 = Readable name - */ + /** Release ID; Readable name */ public static Map releaseNames = new HashMap<>(); // This list contains the readable names of the ID's to the - /** - * Arg 1 = Minecraft version; - * Arg 2 = Compatible project ID's for that - */ + /** Minecraft version; Compatible project ID's for that */ public static Map> mcVerToReleaseID = new HashMap<>(); - /** - * Arg 1 = ID; - * Arg 2 = Download URL - */ + /** ID; Download URL */ public static Map downloadUrl = new HashMap<>(); // Get the download url - /** - * Arg 1 = ID; - * Arg 2 = Changelog - */ + /** ID; Changelog */ public static Map changeLogs = new HashMap<>(); @@ -68,7 +56,7 @@ public class ModrinthGetter try { initted = false; - projectRelease = JsonFormat.fancyInstance().createParser().parse("{\"E\":" + WebDownloader.downloadAsString(new URL(ModrinthAPI + projectID + "/version")) + "}").get("E"); + projectRelease = WebDownloader.parseWebJsonList(ModrinthAPI + projectID + "/version"); for (Config currentRelease : projectRelease) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/WebDownloader.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/WebDownloader.java index 3194ec9cf..7a2184648 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/WebDownloader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/installer/WebDownloader.java @@ -19,16 +19,20 @@ package com.seibel.distanthorizons.core.jar.installer; +import com.electronwill.nightconfig.core.Config; +import com.electronwill.nightconfig.json.JsonFormat; + import javax.net.ssl.HttpsURLConnection; import java.io.*; import java.net.URL; import java.net.URLConnection; import java.security.DigestInputStream; import java.security.MessageDigest; +import java.util.ArrayList; /** - * Does something similar to wget/curl. - * It allows you to download a file from a link + * Does something similar to wget/curl.
+ * It allows you to download a file from a link, and other useful web utils * * @author coolGi */ @@ -38,7 +42,7 @@ public class WebDownloader { try { - final URL url = new URL("https://www.google.com"); // Google will probably be online forever so we use that to check network connection + final URL url = new URL("https://example.com"); // example.com will always be online as long as a DNS server exists, so attempt to ping it to check for internet connectivity final URLConnection conn = url.openConnection(); conn.connect(); conn.getInputStream().close(); @@ -109,7 +113,28 @@ public class WebDownloader - // Stolen from https://mkyong.com/java/how-to-generate-a-file-checksum-value-in-java/ but added some comments + public static Config parseWebJson(String url) throws Exception + { + return parseWebJson(new URL(url)); + } + public static Config parseWebJson(URL url) throws Exception + { + return JsonFormat.minimalInstance().createParser().parse(WebDownloader.downloadAsString(url)); + } + + public static ArrayList parseWebJsonList(String url) throws Exception + { + return parseWebJsonList(new URL(url)); + } + public static ArrayList parseWebJsonList(URL url) throws Exception + { + // Is there a better way of doing this? + return JsonFormat.minimalInstance().createParser().parse("{\"E\":" + WebDownloader.downloadAsString(url) + "}").get("E"); + } + + + + // Taken from https://mkyong.com/java/how-to-generate-a-file-checksum-value-in-java/ but added some comments /** * @param filepath Path to the file * @param md The checksum. Can be gotten by "MessageDigest.getInstance("SHA-256")" and can replace string with something like SHA, MD2, MD5, SHA-256, SHA-384... diff --git a/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java b/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java index 615690a6a..4fb8eed67 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/jar/updater/SelfUpdater.java @@ -19,7 +19,10 @@ package com.seibel.distanthorizons.core.jar.updater; +import com.seibel.distanthorizons.api.enums.config.EUpdateBranch; import com.seibel.distanthorizons.core.jar.JarUtils; +import com.seibel.distanthorizons.core.jar.ModGitInfo; +import com.seibel.distanthorizons.core.jar.installer.GitlabGetter; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; @@ -31,10 +34,14 @@ import org.apache.logging.log4j.Logger; import javax.swing.*; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.security.MessageDigest; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; /** * Used to update the mod automatically @@ -47,8 +54,13 @@ public class SelfUpdater /** As we cannot delete(or replace) the jar while the mod is running, we just have this to delete it once the game closes */ public static boolean deleteOldOnClose = false; + + private static String currentJarSha = ""; + private static String mcVersion = SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion(); + public static File newFileLocation; + /** * Should be called on the game starting. * (After the config has been initialised) @@ -58,21 +70,36 @@ public class SelfUpdater public static boolean onStart() { LOGGER.info("Checking for DH update"); - // Some init stuff - // We use sha1 to check the version as our versioning system is different to the one on modrinth - if (!ModrinthGetter.init()) - return false; - String jarSha = ""; + try { - jarSha = JarUtils.getFileChecksum(MessageDigest.getInstance("SHA"), JarUtils.jarFile); + currentJarSha = JarUtils.getFileChecksum(MessageDigest.getInstance("SHA"), JarUtils.jarFile); } catch (Exception e) { e.printStackTrace(); return false; } - String mcVersion = SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion(); + + boolean returnValue = false; + switch (Config.Client.Advanced.AutoUpdater.updateBranch.get()) + { + case STABLE: + returnValue = onStableStart(); + break; + case NIGHTLY: + returnValue = onNightlyStart(); + break; + }; + return returnValue; + } + + public static boolean onStableStart() + { + // Some init stuff + // We use sha1 to check the version as our versioning system is different to the one on modrinth + if (!ModrinthGetter.init()) + return false; if (!ModrinthGetter.mcVersions.contains(mcVersion)) { LOGGER.warn("Minecraft version ["+ mcVersion +"] is not findable on Modrinth, only findable versions are ["+ ModrinthGetter.mcVersions.toString() +"]"); @@ -80,14 +107,14 @@ public class SelfUpdater } // Check the sha's of both our stuff - if (jarSha.equals(ModrinthGetter.getLatestShaForVersion(mcVersion))) + if (currentJarSha.equals(ModrinthGetter.getLatestShaForVersion(mcVersion))) return false; LOGGER.info("New version (" + ModrinthGetter.getLatestNameForVersion(mcVersion) + ") of " + ModInfo.READABLE_NAME + " is available"); + newFileLocation = JarUtils.jarFile.getParentFile().toPath().resolve("update").resolve(ModInfo.NAME + "-" + ModrinthGetter.getLatestNameForVersion(mcVersion) + ".jar").toFile(); if (Config.Client.Advanced.AutoUpdater.enableSilentUpdates.get()) { - newFileLocation = JarUtils.jarFile.getParentFile().toPath().resolve("update").resolve(ModInfo.NAME + "-" + ModrinthGetter.getLatestNameForVersion(mcVersion) + ".jar").toFile(); // Auto-update mod updateMod(mcVersion, newFileLocation); return false; @@ -95,6 +122,35 @@ public class SelfUpdater return true; } + public static boolean onNightlyStart() + { + if (GitlabGetter.INSTANCE.projectPipelines.size() == 0) + return false; + com.electronwill.nightconfig.core.Config pipeline = GitlabGetter.INSTANCE.projectPipelines.get(0); + + if (!GitlabGetter.INSTANCE.getDownloads(pipeline.get("id")).containsKey(mcVersion)) + { + LOGGER.warn("Minecraft version ["+ mcVersion +"] is not findable on Gitlab, findable versions are ["+ GitlabGetter.INSTANCE.getDownloads(pipeline.get("id")).keySet().toArray().toString() +"]"); + return false; + } + + String latestCommit = pipeline.get("sha"); + + if (ModGitInfo.Git_Main_Commit.equals(latestCommit)) // If we are already on the latest commit, then dont update + return false; + + + LOGGER.info("New version (" + latestCommit + ") of " + ModInfo.READABLE_NAME + " is available"); + newFileLocation = JarUtils.jarFile.getParentFile().toPath().resolve("update").resolve(ModInfo.NAME + "-" + latestCommit + ".jar").toFile(); + if (Config.Client.Advanced.AutoUpdater.enableSilentUpdates.get()) + { + // Auto-update mod + updateMod(mcVersion, newFileLocation); + return false; + } + return true; + } + /** * Should be called when the game is closed. * This is ued to delete the previous file if it is required at the end. @@ -128,13 +184,27 @@ public class SelfUpdater public static boolean updateMod() { String mcVer = SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion(); - newFileLocation = JarUtils.jarFile.getParentFile().toPath().resolve("update").resolve(ModInfo.NAME + "-" + ModrinthGetter.getLatestNameForVersion(mcVer) + ".jar").toFile(); return updateMod( mcVer, newFileLocation ); } public static boolean updateMod(String minecraftVersion, File file) + { + boolean returnValue = false; + switch (Config.Client.Advanced.AutoUpdater.updateBranch.get()) + { + case STABLE: + returnValue = updateStableMod(minecraftVersion, file); + break; + case NIGHTLY: + returnValue = updateNightlyMod(minecraftVersion, file); + break; + }; + return returnValue; + } + + public static boolean updateStableMod(String minecraftVersion, File file) { try { @@ -167,4 +237,56 @@ public class SelfUpdater } } + public static boolean updateNightlyMod(String minecraftVersion, File file) + { + if (GitlabGetter.INSTANCE.projectPipelines.size() == 0) + return false; + + try + { + LOGGER.info("Attempting to auto update " + ModInfo.READABLE_NAME); + + Files.createDirectories(file.getParentFile().toPath()); + + File mergedZip = file.getParentFile().toPath().resolve("merged.zip").toFile(); + + WebDownloader.downloadAsFile(GitlabGetter.INSTANCE.getDownloads(GitlabGetter.INSTANCE.projectPipelines.get(0).get("id")).get(minecraftVersion), mergedZip); + + ZipInputStream zis = new ZipInputStream(new FileInputStream(mergedZip)); + ZipEntry zipEntry = zis.getNextEntry(); + while (zipEntry != null) + { + if (!zipEntry.isDirectory() && zipEntry.getName().contains("Merged")) // Look until the merged jar is found + { + // write file content + FileOutputStream fos = new FileOutputStream(file); + byte[] buffer = new byte[1024]; + + int len; + while ((len = zis.read(buffer)) > 0) { + fos.write(buffer, 0, len); + } + fos.close(); + + deleteOldOnClose = true; + + LOGGER.info(ModInfo.READABLE_NAME + " successfully updated. It will apply on game's relaunch"); + new Thread(() -> { + System.setProperty("java.awt.headless", "false"); // Required to make it work + JOptionPane.showMessageDialog(null, ModInfo.READABLE_NAME + " updated, this will be applied on game restart.", ModInfo.READABLE_NAME, JOptionPane.INFORMATION_MESSAGE); + }).start(); + return true; + } + + zipEntry = zis.getNextEntry(); + } + return false; + } + catch (Exception e) + { + LOGGER.warn("Failed to update " + ModInfo.READABLE_NAME + " to version " + GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha")); + e.printStackTrace(); + return false; + } + } } diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index 0a3a84fda..deaab2f5d 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -462,6 +462,10 @@ "Enable Silent Updates", "distanthorizons.config.client.advanced.autoUpdater.enableSilentUpdates.@tooltip": "Automatically updates the mod when an update is available", + "distanthorizons.config.client.advanced.autoUpdater.updateBranch": + "Update Branch", + "distanthorizons.config.client.advanced.autoUpdater.updateBranch.@tooltip": + "Where to download the latest update from.\n\nStable: Stable builds from Modrinth\nNightly: Nightly builds from Gitlab", @@ -824,6 +828,10 @@ "distanthorizons.config.enum.ELodShading.OLD_LIGHTING": "Old Lighting", "distanthorizons.config.enum.ELodShading.NONE": - "None" - + "None", + + "distanthorizons.config.enum.EUpdateBranch.STABLE": + "Stable", + "distanthorizons.config.enum.EUpdateBranch.NIGHTLY": + "Nightly" }