From 1ef50cbb95f00dd315444c845425b032af1da134 Mon Sep 17 00:00:00 2001 From: rtm516 Date: Thu, 9 Apr 2020 14:36:32 +0100 Subject: [PATCH] Added automatic en_us download and extraction from JAR --- .../geysermc/connector/utils/LocaleUtils.java | 92 +++++++++++++++---- .../geysermc/connector/utils/WebUtils.java | 13 +++ connector/src/main/resources/mappings | 2 +- 3 files changed, 87 insertions(+), 20 deletions(-) diff --git a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java index 3c6ca19bc..d19c4672e 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/LocaleUtils.java @@ -33,8 +33,13 @@ import lombok.Getter; import org.geysermc.connector.GeyserConnector; import java.io.*; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; import java.time.OffsetDateTime; import java.util.*; +import java.util.zip.ZipFile; public class LocaleUtils { @@ -44,6 +49,8 @@ public class LocaleUtils { private static final String DEFAULT_LOCALE = (GeyserConnector.getInstance().getConfig().getDefaultLocale() != null ? GeyserConnector.getInstance().getConfig().getDefaultLocale() : "en_us"); + private static String smallestURL = ""; + static { // Create the locales folder File localesFolder = new File("locales/"); @@ -51,6 +58,9 @@ public class LocaleUtils { // Download the latest asset list and cache it generateAssetCache(); + if (!DEFAULT_LOCALE.equals("en_us")) { + downloadAndLoadLocale("en_us"); + } downloadAndLoadLocale(DEFAULT_LOCALE); } @@ -70,6 +80,15 @@ public class LocaleUtils { } VersionInfo versionInfo = Toolbox.JSON_MAPPER.readValue(WebUtils.getBody(latestInfoURL), VersionInfo.class); + + int currentSize = Integer.MAX_VALUE; + for (VersionDownload download : versionInfo.getDownloads().values()) { + if (download.getUrl().endsWith(".jar") && download.getSize() < currentSize) { + smallestURL = download.getUrl(); + currentSize = download.getSize(); + } + } + JsonNode assets = Toolbox.JSON_MAPPER.readTree(WebUtils.getBody(versionInfo.getAssetIndex().getUrl())).get("objects"); Iterator> assetIterator = assets.fields(); @@ -106,30 +125,14 @@ public class LocaleUtils { // Create the en_us locale if (locale.equals("en_us")) { - try { - InputStreamReader isReader = new InputStreamReader(Toolbox.getResource("mappings/lang/en_us.json")); - BufferedReader reader = new BufferedReader(isReader); - StringBuffer sb = new StringBuffer(); - String str; - while((str = reader.readLine())!= null){ - sb.append(str); - } - - FileUtils.writeFile(localeFile, sb.toString().toCharArray()); - } catch (Exception e) { - throw new AssertionError("Unable to load en_us locale!", e); - } + downloadEN_US(localeFile); return; } + // Get the hash and download the locale String hash = ASSET_MAP.get("minecraft/lang/" + locale + ".json").getHash(); - - try { - FileUtils.writeFile("locales/" + locale + ".json", WebUtils.getBody("http://resources.download.minecraft.net/" + hash.substring(0, 2) + "/" + hash).toCharArray()); - } catch (Exception e) { - GeyserConnector.getInstance().getLogger().warning("Failed to download locale " + locale + ": " + (!e.getMessage().isEmpty() ? e.getMessage() : e.getStackTrace())); - } + WebUtils.downloadFile("http://resources.download.minecraft.net/" + hash.substring(0, 2) + "/" + hash, "locales/" + locale + ".json"); } private static void loadLocale(String locale) { @@ -168,6 +171,41 @@ public class LocaleUtils { } } + private static void downloadEN_US(File localeFile) { + try { + // Let the user know we are downloading the JAR + GeyserConnector.getInstance().getLogger().info("Downloading Minecraft JAR to extract en_us locale, please wait... (this may take some time depending on the speed of your internet connection)"); + GeyserConnector.getInstance().getLogger().debug("Download URL: " + smallestURL); + + // Download the smallest JAR (client or server) + WebUtils.downloadFile(smallestURL, "tmp_locale.jar"); + + // Load in the JAR as a zip and extract the file + ZipFile localeJar = new ZipFile("tmp_locale.jar"); + InputStream inputStream = localeJar.getInputStream(localeJar.getEntry("assets/minecraft/lang/en_us.json")); + FileOutputStream outputStream = new FileOutputStream(localeFile); + + // Write the file to the locale dir + int data = inputStream.read(); + while(data != -1){ + outputStream.write(data); + data = inputStream.read(); + } + + // Flush all changes to disk and cleanup + outputStream.flush(); + outputStream.close(); + + inputStream.close(); + localeJar.close(); + + // Delete the nolonger needed client/server jar + Files.delete(Paths.get("tmp_locale.jar")); + } catch (Exception e) { + throw new AssertionError("Unable to download and extract en_us locale!", e); + } + } + public static String getLocaleString(String messageText, String locale) { Map localeStrings = LocaleUtils.LOCALE_MAPPINGS.get(locale.toLowerCase()); if (localeStrings == null) @@ -237,6 +275,22 @@ class VersionInfo { @JsonProperty("assetIndex") private AssetIndex assetIndex; + + @JsonProperty("downloads") + private Map downloads; +} + +@JsonIgnoreProperties(ignoreUnknown = true) +@Getter +class VersionDownload { + @JsonProperty("sha1") + private String sha1; + + @JsonProperty("size") + private int size; + + @JsonProperty("url") + private String url; } @JsonIgnoreProperties(ignoreUnknown = true) diff --git a/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java b/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java index 17029fd94..a155f0b95 100644 --- a/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java +++ b/connector/src/main/java/org/geysermc/connector/utils/WebUtils.java @@ -28,12 +28,16 @@ package org.geysermc.connector.utils; import org.geysermc.connector.GeyserConnector; import java.io.BufferedReader; +import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; public class WebUtils { @@ -61,4 +65,13 @@ public class WebUtils { return e.getMessage(); } } + + public static void downloadFile(String reqURL, String fileLocation) { + try { + InputStream in = new URL(reqURL).openStream(); + Files.copy(in, Paths.get(fileLocation), StandardCopyOption.REPLACE_EXISTING); + } catch (Exception e) { + throw new AssertionError("Unable to download and save file: " + fileLocation + " (" + reqURL + ")", e); + } + } } diff --git a/connector/src/main/resources/mappings b/connector/src/main/resources/mappings index c25f11c56..efc9db6b7 160000 --- a/connector/src/main/resources/mappings +++ b/connector/src/main/resources/mappings @@ -1 +1 @@ -Subproject commit c25f11c5653b1db06594218d7a1a31a3bfd68c6c +Subproject commit efc9db6b7d51bdf145230933ac23b321ac1c132d