From fad06a58a116439fbf677f5e446f09b2c6e62dea Mon Sep 17 00:00:00 2001 From: Bixilon Date: Thu, 3 Sep 2020 16:45:43 +0200 Subject: [PATCH] Auto download mappings if mappings are not available on disk --- .../minosoft/config/GameConfiguration.java | 3 ++- .../objectLoader/versions/Versions.java | 23 ++++++++++++++++++- .../minosoft/gui/main/ServerListCell.java | 7 +++--- .../minosoft/protocol/network/Connection.java | 12 ++++++---- .../protocol/protocol/ConnectionStates.java | 3 ++- .../java/de/bixilon/minosoft/util/Util.java | 11 +++++++++ src/main/resources/config/game.yml | 3 ++- 7 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/config/GameConfiguration.java b/src/main/java/de/bixilon/minosoft/config/GameConfiguration.java index aaff5420b..fd8b20bea 100644 --- a/src/main/java/de/bixilon/minosoft/config/GameConfiguration.java +++ b/src/main/java/de/bixilon/minosoft/config/GameConfiguration.java @@ -18,7 +18,8 @@ public enum GameConfiguration implements ConfigEnum { GAME_RENDER_DISTANCE("game.render-distance"), NETWORK_FAKE_CLIENT_BRAND("network.fake-client-brand"), GENERAL_LOG_LEVEL("general.log-level"), - CLIENT_TOKEN("account.clientToken"); + CLIENT_TOKEN("account.clientToken"), + MAPPINGS_URL("download.mappings"); final String path; diff --git a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/versions/Versions.java b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/versions/Versions.java index 2c37d82be..8d4c38a3f 100644 --- a/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/versions/Versions.java +++ b/src/main/java/de/bixilon/minosoft/game/datatypes/objectLoader/versions/Versions.java @@ -18,6 +18,8 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import de.bixilon.minosoft.Config; +import de.bixilon.minosoft.Minosoft; +import de.bixilon.minosoft.config.GameConfiguration; import de.bixilon.minosoft.game.datatypes.Mappings; import de.bixilon.minosoft.logging.Log; import de.bixilon.minosoft.protocol.protocol.ConnectionStates; @@ -25,10 +27,13 @@ import de.bixilon.minosoft.protocol.protocol.Packets; import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; import de.bixilon.minosoft.util.Util; +import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import java.util.HashSet; import java.util.Map; +import java.util.zip.ZipException; public class Versions { @@ -132,7 +137,23 @@ public class Versions { Log.verbose(String.format("Loading mappings for version %s...", version)); long startTime = System.currentTimeMillis(); - HashMap files = Util.readTarGzFile(Config.homeDir + String.format("assets/mapping/%s.tar.gz", version.getVersionName())); + String fileName = Config.homeDir + String.format("assets/mapping/%s.tar.gz", version.getVersionName()); + HashMap files; + try { + files = Util.readTarGzFile(fileName); + } catch (FileNotFoundException e) { + long downloadStartTime = System.currentTimeMillis(); + Log.info(String.format("Mappings for %s are not available on disk. Downloading them...", version.getVersionName())); + Util.downloadFile(String.format(Minosoft.getConfig().getString(GameConfiguration.MAPPINGS_URL), version.getVersionName()), fileName); + try { + files = Util.readTarGzFile(fileName); + } catch (ZipException e2) { + // bullshit downloaded, delete file + new File(fileName).delete(); + throw e2; + } + Log.info(String.format("Mappings for %s downloaded successfully in %dms!", version.getVersionName(), (System.currentTimeMillis() - downloadStartTime))); + } for (Map.Entry mappingSet : mappingsHashMap.entrySet()) { JsonObject data = JsonParser.parseString(files.get(mappingSet.getKey() + ".json")).getAsJsonObject().getAsJsonObject("minecraft"); diff --git a/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java b/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java index 34a3818ea..cc899a648 100644 --- a/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java +++ b/src/main/java/de/bixilon/minosoft/gui/main/ServerListCell.java @@ -157,11 +157,10 @@ public class ServerListCell extends ListCell implements Initializable { motd.setText(ping.getMotd().getRawMessage()); if (ping.getFavicon() != null) { icon.setImage(ping.getFavicon()); - if (ping.getBase64EncodedFavicon().equals(server.getBase64Favicon())) { - return; + if (!ping.getBase64EncodedFavicon().equals(server.getBase64Favicon())) { + server.setBase64Favicon(ping.getBase64EncodedFavicon()); + server.saveToConfig(); } - server.setBase64Favicon(ping.getBase64EncodedFavicon()); - server.saveToConfig(); } if (server.getLastPing().getLastConnectionException() != null) { // connection failed because of an error in minosoft, but ping was okay diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java b/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java index af34cac6b..680b5f36f 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java +++ b/src/main/java/de/bixilon/minosoft/protocol/network/Connection.java @@ -38,6 +38,7 @@ import de.bixilon.minosoft.util.DNSUtil; import de.bixilon.minosoft.util.ServerAddress; import org.xbill.DNS.TextParseException; +import java.io.IOException; import java.util.HashSet; import java.util.LinkedList; import java.util.concurrent.LinkedBlockingQueue; @@ -195,6 +196,9 @@ public class Connection { handleCallbacks(null); } break; + case FAILED_NO_RETRY: + handleCallbacks(null); + break; } } @@ -208,11 +212,11 @@ public class Connection { try { Versions.loadVersionMappings(version.getProtocolVersion()); customMapping.setVersion(version); - } catch (Exception e) { + } catch (IOException e) { e.printStackTrace(); Log.fatal(String.format("Could not load mapping for %s. This version seems to be unsupported!", version)); network.lastException = new RuntimeException(String.format("Mappings could not be loaded: %s", e.getLocalizedMessage())); - setConnectionState(ConnectionStates.FAILED); + setConnectionState(ConnectionStates.FAILED_NO_RETRY); } } @@ -301,7 +305,7 @@ public class Connection { } public boolean isConnected() { - return state != ConnectionStates.FAILED && state != ConnectionStates.DISCONNECTING && state != ConnectionStates.DISCONNECTED && state != ConnectionStates.CONNECTING; + return state != ConnectionStates.FAILED && state != ConnectionStates.FAILED_NO_RETRY && state != ConnectionStates.DISCONNECTING && state != ConnectionStates.DISCONNECTED && state != ConnectionStates.CONNECTING; } public PacketSender getSender() { @@ -347,7 +351,7 @@ public class Connection { } public void addPingCallback(PingCallback pingCallback) { - if (getConnectionState() == ConnectionStates.FAILED || lastPing != null) { + if (getConnectionState() == ConnectionStates.FAILED || getConnectionState() == ConnectionStates.FAILED_NO_RETRY || lastPing != null) { // ping done pingCallback.handle(lastPing); return; diff --git a/src/main/java/de/bixilon/minosoft/protocol/protocol/ConnectionStates.java b/src/main/java/de/bixilon/minosoft/protocol/protocol/ConnectionStates.java index a01cfbff0..2aac4be52 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/protocol/ConnectionStates.java +++ b/src/main/java/de/bixilon/minosoft/protocol/protocol/ConnectionStates.java @@ -21,7 +21,8 @@ public enum ConnectionStates { CONNECTING, DISCONNECTING, DISCONNECTED, - FAILED; + FAILED, + FAILED_NO_RETRY; public static ConnectionStates byId(int id) { diff --git a/src/main/java/de/bixilon/minosoft/util/Util.java b/src/main/java/de/bixilon/minosoft/util/Util.java index c14ae7b2b..f1b99389f 100644 --- a/src/main/java/de/bixilon/minosoft/util/Util.java +++ b/src/main/java/de/bixilon/minosoft/util/Util.java @@ -21,6 +21,7 @@ import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; import java.io.*; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -149,4 +150,14 @@ public final class Util { public static JsonObject readJsonFromFile(String fileName) throws IOException { return JsonParser.parseString(readFile(fileName)).getAsJsonObject(); } + + public static void downloadFile(String url, String destination) throws IOException { + BufferedInputStream inputStream = new BufferedInputStream(new URL(url).openStream()); + FileOutputStream fileOutputStream = new FileOutputStream(destination); + byte[] buffer = new byte[1024]; + int length; + while ((length = inputStream.read(buffer, 0, 1024)) != -1) { + fileOutputStream.write(buffer, 0, length); + } + } } diff --git a/src/main/resources/config/game.yml b/src/main/resources/config/game.yml index 1d87a0c57..30940d0e7 100644 --- a/src/main/resources/config/game.yml +++ b/src/main/resources/config/game.yml @@ -14,5 +14,6 @@ network: account: clientToken: "randomGenerated" accounts: - +download: + mappings: "https://gitlab.com/Bixilon/minosoft/-/raw/master/data/mcdata/%s.tar.gz?inline=false" # url for all mappings. Files must be called version.tar.gz (e.g. 1.12.2.tar.gz). In these files must be the blocks.json and the registries.json servers: