diff --git a/build.gradle b/build.gradle index d22270d..2af18f5 100644 --- a/build.gradle +++ b/build.gradle @@ -29,34 +29,15 @@ processResources { ] } -configurations { - shade - compile.extendsFrom shade -} dependencies { - shade('us.myles:viaversion:2.0.0-19w04a') { - transitive = false - changing = true - } + compile "us.myles:viaversion:2.0.0-19w04a" minecraft "com.mojang:minecraft:19w04a" mappings "net.fabricmc:yarn:19w04a.1" modCompile "net.fabricmc:fabric-loader:0.3.3.101" } -jar { - configurations.shade.each { dep -> - from(project.zipTree(dep)) { - //exclude 'META-INF', 'META-INF/**' - exclude 'us/myles/ViaVersion/SpongePlugin.class' - exclude 'us/viaversion/libs/javassist/**' - exclude 'mcmod.info' - exclude 'plugin.yml' - exclude 'bungee.yml' - } - } -} minecraft { } diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..d8e54c1 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +#Done to increase the memory available to gradle. +org.gradle.jvmargs=-Xmx1G \ No newline at end of file diff --git a/src/main/java/com/github/creeper123123321/viafabric/ViaFabric.java b/src/main/java/com/github/creeper123123321/viafabric/ViaFabric.java index 5932625..9ffd34c 100644 --- a/src/main/java/com/github/creeper123123321/viafabric/ViaFabric.java +++ b/src/main/java/com/github/creeper123123321/viafabric/ViaFabric.java @@ -24,22 +24,36 @@ package com.github.creeper123123321.viafabric; -import com.github.creeper123123321.viafabric.commands.VRCommandHandler; -import com.github.creeper123123321.viafabric.platform.VRInjector; -import com.github.creeper123123321.viafabric.platform.VRLoader; -import com.github.creeper123123321.viafabric.platform.VRPlatform; import com.github.creeper123123321.viafabric.util.JLoggerToLog4j; +import com.github.creeper123123321.viafabric.util.Version; +import com.google.common.io.CharStreams; import com.google.common.util.concurrent.ThreadFactoryBuilder; import io.netty.channel.DefaultEventLoop; import io.netty.channel.EventLoop; import net.fabricmc.api.ClientModInitializer; +import net.fabricmc.loader.FabricLoader; +import net.minecraft.client.MinecraftClient; +import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; -import us.myles.ViaVersion.ViaManager; -import us.myles.ViaVersion.api.Via; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class ViaFabric implements ClientModInitializer { public static final java.util.logging.Logger JLOGGER = new JLoggerToLog4j(LogManager.getLogger("ViaFabric")); @@ -52,13 +66,73 @@ public class ViaFabric implements ClientModInitializer { EVENT_LOOP = new DefaultEventLoop(factory); } + public static String getVersion() { + return FabricLoader.INSTANCE.getModContainers() + .stream() + .filter(container -> container.getInfo().getId().equals("viafabric")) + .findFirst() + .get().getInfo().getVersionString(); + } + @Override public void onInitializeClient() { - Via.init(ViaManager.builder() - .injector(new VRInjector()) - .loader(new VRLoader()) - .commandHandler(new VRCommandHandler()) - .platform(new VRPlatform()).build()); - Via.getManager().init(); + File viaVersionJar = FabricLoader.INSTANCE.getConfigDirectory().toPath().resolve("ViaFabric").resolve("viaversion.jar").toFile(); + String localMd5 = null; + try { + if (viaVersionJar.exists()) { + try (InputStream is = Files.newInputStream(viaVersionJar.toPath())) { + localMd5 = org.apache.commons.codec.digest.DigestUtils.md5Hex(is); + } + } + HttpURLConnection con = (HttpURLConnection) new URL("https://repo.viaversion.com/us/myles/viaversion/").openConnection(); + con.setRequestProperty("User-Agent", "ViaFabric/" + ViaFabric.getVersion()); + String rawOutput = CharStreams.toString(new InputStreamReader(con.getInputStream())); + con.getInputStream().close(); + Pattern urlPattern = Pattern.compile(""); + Matcher matcher = urlPattern.matcher(rawOutput); + List versions = new ArrayList<>(); + while (matcher.find()) { + versions.add(matcher.group(1)); + } + String bestViaVersion = null; + String mcVersion = MinecraftClient.getInstance().getGame().getVersion().getName(); + if (mcVersion.contains("w") || mcVersion.contains("-")) { + bestViaVersion = versions.stream() + .filter(it -> it.endsWith(mcVersion)) + .max(Comparator.comparing(Version::new)) + .orElse(null); + } + if (bestViaVersion == null) { + bestViaVersion = versions.stream() + .filter(it -> it.endsWith("-SNAPSHOT") || it.endsWith("-DEV") || !it.contains("-")) + .max(Comparator.comparing(Version::new)) + .orElse(null); + } + HttpURLConnection md5Con = (HttpURLConnection) new URL( + "https://repo.viaversion.com/us/myles/viaversion/" + bestViaVersion + + "/viaversion-" + bestViaVersion + ".jar.md5").openConnection(); + md5Con.setRequestProperty("User-Agent", "ViaFabric/" + ViaFabric.getVersion()); + String remoteMd5 = CharStreams.toString(new InputStreamReader(md5Con.getInputStream())); + if (!remoteMd5.equals(localMd5)) { + URL url = new URL("https://repo.viaversion.com/us/myles/viaversion/" + bestViaVersion + + "/viaversion-" + bestViaVersion + ".jar"); + ViaFabric.JLOGGER.info("Downloading " + url); + HttpURLConnection jarCon = (HttpURLConnection) url.openConnection(); + jarCon.setRequestProperty("User-Agent", "ViaFabric/" + ViaFabric.getVersion()); + FileUtils.copyInputStreamToFile(jarCon.getInputStream(), viaVersionJar); + } + } catch (IOException e) { + e.printStackTrace(); + } + try { + Method addUrl = ViaFabric.class.getClassLoader().getClass().getMethod("addURL", URL.class); + addUrl.setAccessible(true); + addUrl.invoke(ViaFabric.class.getClassLoader(), viaVersionJar.toURI().toURL()); + Class.forName("com.github.creeper123123321.viafabric.platform.VRViaVersionInitializer") + .getMethod("init") + .invoke(null); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | MalformedURLException | ClassNotFoundException e) { + e.printStackTrace(); + } } } diff --git a/src/main/java/com/github/creeper123123321/viafabric/platform/VRPlatform.java b/src/main/java/com/github/creeper123123321/viafabric/platform/VRPlatform.java index 4c386a1..0436424 100644 --- a/src/main/java/com/github/creeper123123321/viafabric/platform/VRPlatform.java +++ b/src/main/java/com/github/creeper123123321/viafabric/platform/VRPlatform.java @@ -51,7 +51,7 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Logger; public class VRPlatform implements ViaPlatform { - private VRViaConfig config = new VRViaConfig(new File("config/ViaFabric")); + private VRViaConfig config = new VRViaConfig(new File(FabricLoader.INSTANCE.getConfigDirectory(), "ViaFabric")); @Override public Logger getLogger() { @@ -65,16 +65,19 @@ public class VRPlatform implements ViaPlatform { @Override public String getPlatformVersion() { - return FabricLoader.INSTANCE.getModContainers() - .stream() - .filter(container -> container.getInfo().getId().equals("viafabric")) - .findFirst() - .get().getInfo().getVersionString(); // TODO + return ViaFabric.getVersion(); } @Override public String getPluginVersion() { - return VersionInfo.VERSION + "-ViaFabric"; + try { + return VersionInfo.class.getField("VERSION").get(null) + "-ViaFabric"; + } catch (IllegalAccessException e) { + e.printStackTrace(); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + return "?"; } @Override diff --git a/src/main/java/com/github/creeper123123321/viafabric/platform/VRViaVersionInitializer.java b/src/main/java/com/github/creeper123123321/viafabric/platform/VRViaVersionInitializer.java new file mode 100644 index 0000000..fd9f35e --- /dev/null +++ b/src/main/java/com/github/creeper123123321/viafabric/platform/VRViaVersionInitializer.java @@ -0,0 +1,40 @@ +/* + * MIT License + * + * Copyright (c) 2018 creeper123123321 and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.github.creeper123123321.viafabric.platform; + +import com.github.creeper123123321.viafabric.commands.VRCommandHandler; +import us.myles.ViaVersion.ViaManager; +import us.myles.ViaVersion.api.Via; + +public class VRViaVersionInitializer { + public static void init() { + Via.init(ViaManager.builder() + .injector(new VRInjector()) + .loader(new VRLoader()) + .commandHandler(new VRCommandHandler()) + .platform(new VRPlatform()).build()); + Via.getManager().init(); + } +} diff --git a/src/main/java/com/github/creeper123123321/viafabric/util/Version.java b/src/main/java/com/github/creeper123123321/viafabric/util/Version.java new file mode 100644 index 0000000..0f2e553 --- /dev/null +++ b/src/main/java/com/github/creeper123123321/viafabric/util/Version.java @@ -0,0 +1,115 @@ +/* + * MIT License + * + * Copyright (c) 2018 creeper123123321 and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package com.github.creeper123123321.viafabric.util; + +import com.google.common.base.Joiner; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +// Based on ViaVersion's Version +public class Version implements Comparable { + private static final Pattern semVer = Pattern.compile("(?0|[1-9]\\d*)\\.(?0|[1-9]\\d*)(?:\\.(?0|[1-9]\\d*))?(?:-(?[A-z0-9.-]*))?"); + private final int[] parts = new int[3]; + private String tag; + + public Version(String value) { + if (value == null) { + throw new IllegalArgumentException("Version can not be null"); + } else { + Matcher matcher = semVer.matcher(value); + if (!matcher.matches()) { + throw new IllegalArgumentException("Invalid version format"); + } else { + this.parts[0] = Integer.parseInt(matcher.group("a")); + this.parts[1] = Integer.parseInt(matcher.group("b")); + this.parts[2] = matcher.group("c") == null ? 0 : Integer.parseInt(matcher.group("c")); + this.tag = matcher.group("tag") == null ? "" : matcher.group("tag"); + } + } + } + + public static int compare(Version verA, Version verB) { + if (verA == verB) { + return 0; + } else if (verA == null) { + return -1; + } else if (verB == null) { + return 1; + } else { + int max = Math.max(verA.parts.length, verB.parts.length); + + for(int i = 0; i < max; ++i) { + int partA = i < verA.parts.length ? verA.parts[i] : 0; + int partB = i < verB.parts.length ? verB.parts[i] : 0; + if (partA < partB) { + return -1; + } + + if (partA > partB) { + return 1; + } + } + + // ViaFabric + if (verA.tag.isEmpty() && verB.tag.isEmpty()) { + return 0; + } + if (verA.tag.isEmpty()) { + return 1; + } + if (verB.tag.isEmpty()) { + return -1; + } + return verA.tag.compareTo(verB.tag); + } + } + + public static boolean equals(Version verA, Version verB) { + return verA == verB || verA != null && verB != null && compare(verA, verB) == 0; + } + + public String toString() { + String[] split = new String[this.parts.length]; + + for(int i = 0; i < this.parts.length; ++i) { + split[i] = String.valueOf(this.parts[i]); + } + + return Joiner.on(".").join(split) + (this.tag.length() != 0 ? "-" + this.tag : ""); + } + + public int compareTo(Version that) { + return compare(this, that); + } + + public boolean equals(Object that) { + return that instanceof Version && equals(this, (Version)that); + } + + public String getTag() { + return this.tag; + } +} diff --git a/src/main/resources/mixins.viafabric.main.json b/src/main/resources/mixins.viafabric.main.json index 17d1af2..64742d7 100644 --- a/src/main/resources/mixins.viafabric.main.json +++ b/src/main/resources/mixins.viafabric.main.json @@ -6,7 +6,7 @@ ], "client": [ "client.MixinClientConnectionChInit", - "client.MixinMultiplayerGui", + "client.MixinMultiplayerGui" ], "injectors": { "defaultRequire": 1