diff --git a/dependencies.gradle b/dependencies.gradle index 49e56ff..2d91c2b 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -6,5 +6,6 @@ dependencies { transitive = false } compileOnly("com.falsepattern:json:0.4.1") + compileOnly("org.tukaani:xz:1.9") annotationProcessor("org.projectlombok:lombok:1.18.22") } diff --git a/src/main/resources/classes.csv b/mappings/classes.csv similarity index 100% rename from src/main/resources/classes.csv rename to mappings/classes.csv diff --git a/src/main/resources/fields.csv b/mappings/fields.csv similarity index 100% rename from src/main/resources/fields.csv rename to mappings/fields.csv diff --git a/src/main/resources/methods.csv b/mappings/methods.csv similarity index 100% rename from src/main/resources/methods.csv rename to mappings/methods.csv diff --git a/repositories.gradle b/repositories.gradle index d265b7a..a60f5f0 100644 --- a/repositories.gradle +++ b/repositories.gradle @@ -1,10 +1,10 @@ repositories { maven { name = "sponge" - url = "https://sponge.falsepattern.com/" + url = "https://mvn.falsepattern.com/sponge" } maven { - name = "mavenpattern" - url = "https://maven.falsepattern.com/" + name = "mvnpattern" + url = "https://mvn.falsepattern.com/releases/" } } diff --git a/src/main/java/com/falsepattern/lib/dependencies/SemanticVersion.java b/src/main/java/com/falsepattern/lib/dependencies/SemanticVersion.java index 235c0e9..743df51 100644 --- a/src/main/java/com/falsepattern/lib/dependencies/SemanticVersion.java +++ b/src/main/java/com/falsepattern/lib/dependencies/SemanticVersion.java @@ -21,7 +21,6 @@ package com.falsepattern.lib.dependencies; import com.falsepattern.lib.StableAPI; -import lombok.Builder; import lombok.Getter; import lombok.NonNull; import lombok.val; @@ -30,23 +29,17 @@ import java.util.Objects; @StableAPI(since = "0.6.0") public class SemanticVersion extends Version { - @Getter + @Getter(onMethod_ = @StableAPI.Expose) private final int majorVersion; - @Getter + @Getter(onMethod_ = @StableAPI.Expose) private final int minorVersion; - @Getter + @Getter(onMethod_ = @StableAPI.Expose) private final int patchVersion; - @Getter + @Getter(onMethod_ = @StableAPI.Expose) private final String preRelease; - @Getter + @Getter(onMethod_ = @StableAPI.Expose) private final String build; - @StableAPI.Expose - public SemanticVersion(int majorVersion, int minorVersion, int patchVersion, String preRelease) { - this(majorVersion, minorVersion, patchVersion, preRelease, null); - } - - @Builder @StableAPI.Expose public SemanticVersion(int majorVersion, int minorVersion, int patchVersion, String preRelease, String build) { this.majorVersion = majorVersion; @@ -58,11 +51,31 @@ public class SemanticVersion extends Version { this.build = "".equals(build) ? null : build; } + @StableAPI.Expose + public SemanticVersion(int majorVersion, int minorVersion, int patchVersion, String preRelease) { + this(majorVersion, minorVersion, patchVersion, preRelease, null); + } + @StableAPI.Expose public SemanticVersion(int majorVersion, int minorVersion, int patchVersion) { this(majorVersion, minorVersion, patchVersion, null, null); } + @StableAPI.Expose(since = "0.10.0") + public SemanticVersion(int majorVersion, int minorVersion) { + this(majorVersion, minorVersion, -1, null, null); + } + + @StableAPI.Expose(since = "0.10.0") + public SemanticVersion(int majorVersion) { + this(majorVersion, -1, -1, null, null); + } + + @StableAPI.Expose + public static SemanticVersionBuilder builder() { + return new SemanticVersionBuilder(); + } + @Override public int compareTo(@NonNull Version o) { if (o instanceof ComplexVersion) { @@ -98,7 +111,62 @@ public class SemanticVersion extends Version { @Override public String toString() { - return majorVersion + "." + minorVersion + "." + patchVersion + (preRelease == null ? "" : "-" + preRelease) + + return majorVersion + (minorVersion < 0 ? "" : "." + minorVersion) + (patchVersion < 0 ? "" : "." + patchVersion) + (preRelease == null ? "" : "-" + preRelease) + (build == null ? "" : "+" + build); } + + @StableAPI(since = "0.10.0") + public static class SemanticVersionBuilder { + private int majorVersion; + private int minorVersion = -1; + private int patchVersion = -1; + private String preRelease; + private String build; + + @StableAPI.Internal + SemanticVersionBuilder() { + } + + @StableAPI.Expose + public SemanticVersionBuilder majorVersion(int majorVersion) { + this.majorVersion = majorVersion; + return this; + } + + @StableAPI.Expose + public SemanticVersionBuilder minorVersion(int minorVersion) { + this.minorVersion = minorVersion; + return this; + } + + @StableAPI.Expose + public SemanticVersionBuilder patchVersion(int patchVersion) { + this.patchVersion = patchVersion; + return this; + } + + @StableAPI.Expose + public SemanticVersionBuilder preRelease(String preRelease) { + this.preRelease = preRelease; + return this; + } + + @StableAPI.Expose + public SemanticVersionBuilder build(String build) { + this.build = build; + return this; + } + + @StableAPI.Expose + public SemanticVersion build() { + return new SemanticVersion(majorVersion, minorVersion, patchVersion, preRelease, build); + } + + @Override + public String toString() { + return "SemanticVersion.SemanticVersionBuilder(majorVersion=" + this.majorVersion + ", minorVersion=" + + this.minorVersion + ", patchVersion=" + this.patchVersion + ", preRelease=" + this.preRelease + + ", build=" + this.build + ")"; + } + } } diff --git a/src/main/java/com/falsepattern/lib/internal/impl/mixin/UCPImpl.java b/src/main/java/com/falsepattern/lib/internal/impl/mixin/UCPImpl.java new file mode 100644 index 0000000..e078ae3 --- /dev/null +++ b/src/main/java/com/falsepattern/lib/internal/impl/mixin/UCPImpl.java @@ -0,0 +1,66 @@ +package com.falsepattern.lib.internal.impl.mixin; + +import com.falsepattern.lib.mixin.MinecraftURLClassPath; +import lombok.val; + +import net.minecraft.launchwrapper.LaunchClassLoader; +import cpw.mods.fml.common.Loader; +import cpw.mods.fml.common.ModClassLoader; + +import java.io.File; +import java.lang.reflect.Method; +import java.net.URL; + +public final class UCPImpl { + private static final Object ucp; + private static final Method addURL; + private static final boolean GRIMOIRE; + + static { + boolean grimoire = false; + String[] knownGrimoireClassNames = + new String[]{"io.github.crucible.grimoire.Grimoire", "io.github.crucible.grimoire.common.GrimoireCore"}; + for (val className : knownGrimoireClassNames) { + try { + Class.forName(className, false, MinecraftURLClassPath.class.getClassLoader()); + grimoire = true; + break; + } catch (ClassNotFoundException ignored) { + } + } + GRIMOIRE = grimoire; + if (!GRIMOIRE) { + try { + val modClassLoaderField = Loader.class.getDeclaredField("modClassLoader"); + modClassLoaderField.setAccessible(true); + + val loaderInstanceField = Loader.class.getDeclaredField("instance"); + loaderInstanceField.setAccessible(true); + + val mainClassLoaderField = ModClassLoader.class.getDeclaredField("mainClassLoader"); + mainClassLoaderField.setAccessible(true); + + val ucpField = LaunchClassLoader.class.getSuperclass().getDeclaredField("ucp"); + ucpField.setAccessible(true); + + Object loader = loaderInstanceField.get(null); + val modClassLoader = (ModClassLoader) modClassLoaderField.get(loader); + val mainClassLoader = (LaunchClassLoader) mainClassLoaderField.get(modClassLoader); + ucp = ucpField.get(mainClassLoader); + addURL = ucp.getClass().getDeclaredMethod("addURL", URL.class); + } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) { + throw new RuntimeException(e.getMessage()); + } + } else { + ucp = null; + addURL = null; + System.err.println("Grimoire detected, disabling jar loading utility"); + } + } + + public static void addJar(File pathToJar) throws Exception { + if (!GRIMOIRE) { + addURL.invoke(ucp, pathToJar.toURI().toURL()); + } + } +} diff --git a/src/main/java/com/falsepattern/lib/internal/impl/updates/UpdateCheckerImpl.java b/src/main/java/com/falsepattern/lib/internal/impl/updates/UpdateCheckerImpl.java new file mode 100644 index 0000000..6df1ce6 --- /dev/null +++ b/src/main/java/com/falsepattern/lib/internal/impl/updates/UpdateCheckerImpl.java @@ -0,0 +1,168 @@ +package com.falsepattern.lib.internal.impl.updates; + +import com.falsepattern.json.node.JsonNode; +import com.falsepattern.lib.dependencies.DependencyLoader; +import com.falsepattern.lib.dependencies.Library; +import com.falsepattern.lib.dependencies.SemanticVersion; +import com.falsepattern.lib.internal.Internet; +import com.falsepattern.lib.internal.Tags; +import com.falsepattern.lib.internal.config.LibraryConfig; +import com.falsepattern.lib.text.FormattedText; +import com.falsepattern.lib.updates.ModUpdateInfo; +import com.falsepattern.lib.updates.UpdateCheckException; +import lombok.val; + +import net.minecraft.client.resources.I18n; +import net.minecraft.event.ClickEvent; +import net.minecraft.util.IChatComponent; + +import cpw.mods.fml.common.Loader; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.atomic.AtomicBoolean; + +public final class UpdateCheckerImpl { + private static final AtomicBoolean jsonLibraryLoaded = new AtomicBoolean(false); + + public static List updateListToChatMessages(String initiator, List updates) { + if (updates == null || updates.size() == 0) { + return null; + } + val updateText = new ArrayList( + FormattedText.parse(I18n.format("falsepatternlib.chat.updatesavailable", initiator)).toChatText()); + val mods = Loader.instance().getIndexedModList(); + for (val update : updates) { + val mod = mods.get(update.modID); + updateText.addAll( + FormattedText.parse(I18n.format("falsepatternlib.chat.modname", mod.getName())).toChatText()); + updateText.addAll( + FormattedText.parse(I18n.format("falsepatternlib.chat.currentversion", update.currentVersion)) + .toChatText()); + updateText.addAll( + FormattedText.parse(I18n.format("falsepatternlib.chat.latestversion", update.latestVersion)) + .toChatText()); + if (!update.updateURL.isEmpty()) { + val pre = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurlpre")).toChatText(); + val link = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurl")).toChatText(); + val post = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurlpost")).toChatText(); + pre.get(pre.size() - 1).appendSibling(link.get(0)); + link.get(link.size() - 1).appendSibling(post.get(0)); + for (val l : link) { + l.getChatStyle().setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, update.updateURL)); + } + link.remove(0); + post.remove(0); + updateText.addAll(pre); + updateText.addAll(link); + updateText.addAll(post); + } + } + return updateText; + } + + public static CompletableFuture> fetchUpdatesAsync(String url) { + return CompletableFuture.supplyAsync(() -> { + if (!LibraryConfig.ENABLE_UPDATE_CHECKER) { + throw new CompletionException(new UpdateCheckException("Update checker is disabled in config!")); + } + URL URL; + try { + URL = new URL(url); + } catch (MalformedURLException e) { + throw new CompletionException(new UpdateCheckException("Invalid URL: " + url, e)); + } + if (!jsonLibraryLoaded.get()) { + try { + DependencyLoader.addMavenRepo("https://maven.falsepattern.com/"); + DependencyLoader.loadLibraries(Library.builder() + .loadingModId(Tags.MODID) + .groupId("com.falsepattern") + .artifactId("json") + .minVersion(new SemanticVersion(0, 4, 0)) + .maxVersion(new SemanticVersion(0, Integer.MAX_VALUE, Integer.MAX_VALUE)) + .preferredVersion(new SemanticVersion(0, 4, 1)) + .build()); + } catch (Exception e) { + throw new CompletionException( + new UpdateCheckException("Failed to load json library for update checker!", e)); + } + jsonLibraryLoaded.set(true); + } + val result = new ArrayList(); + JsonNode parsed; + try { + parsed = JsonNode.parse(Internet.download(URL).thenApply(String::new).join()); + } catch (CompletionException e) { + throw new CompletionException(new UpdateCheckException("Failed to download update checker JSON file!", + e.getCause() == null ? e : e.getCause())); + } + List modList; + if (parsed.isList()) { + modList = parsed.getJavaList(); + } else { + modList = Collections.singletonList(parsed); + } + val installedMods = Loader.instance().getIndexedModList(); + for (val node : modList) { + if (!node.isObject()) { + continue; + } + if (!node.containsKey("modid")) { + continue; + } + if (!node.containsKey("latestVersion")) { + continue; + } + val modid = node.getString("modid"); + if (!installedMods.containsKey(modid)) { + continue; + } + val mod = installedMods.get(modid); + val latestVersionsNode = node.get("latestVersion"); + List latestVersions; + if (latestVersionsNode.isString()) { + latestVersions = Collections.singletonList(latestVersionsNode.stringValue()); + } else if (latestVersionsNode.isList()) { + latestVersions = new ArrayList<>(); + for (val version : latestVersionsNode.getJavaList()) { + if (!version.isString()) { + continue; + } + latestVersions.add(version.stringValue()); + } + } else { + continue; + } + val currentVersion = mod.getVersion(); + if (latestVersions.contains(currentVersion)) { + continue; + } + val updateURL = + node.containsKey("updateURL") && node.get("updateURL").isString() ? node.getString("updateURL") + : ""; + result.add(new ModUpdateInfo(modid, currentVersion, latestVersions.get(0), updateURL)); + } + return result; + }); + } + + public static List fetchUpdates(String url) throws UpdateCheckException { + try { + return fetchUpdatesAsync(url).join(); + } catch (CompletionException e) { + try { + throw e.getCause(); + } catch (UpdateCheckException e1) { + throw e1; + } catch (Throwable e1) { + throw new UpdateCheckException("Failed to check for updates!", e1); + } + } + } +} diff --git a/src/main/java/com/falsepattern/lib/mapping/MappingManager.java b/src/main/java/com/falsepattern/lib/mapping/MappingManager.java index 2082b9f..4a2e89c 100644 --- a/src/main/java/com/falsepattern/lib/mapping/MappingManager.java +++ b/src/main/java/com/falsepattern/lib/mapping/MappingManager.java @@ -21,8 +21,10 @@ package com.falsepattern.lib.mapping; import com.falsepattern.lib.StableAPI; +import com.falsepattern.lib.dependencies.DependencyLoader; +import com.falsepattern.lib.dependencies.Library; +import com.falsepattern.lib.dependencies.SemanticVersion; import com.falsepattern.lib.internal.CoreLoadingPlugin; -import com.falsepattern.lib.internal.FalsePatternLib; import com.falsepattern.lib.mapping.storage.Lookup; import com.falsepattern.lib.mapping.types.MappingType; import com.falsepattern.lib.mapping.types.NameType; @@ -32,9 +34,12 @@ import com.falsepattern.lib.mapping.types.UniversalMethod; import com.falsepattern.lib.util.ResourceUtil; import lombok.SneakyThrows; import lombok.val; +import lombok.var; import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.MethodInsnNode; +import org.tukaani.xz.LZMA2Options; +import java.io.DataInputStream; import java.util.HashMap; import java.util.Map; @@ -51,9 +56,26 @@ public class MappingManager { return; } initialized = true; + DependencyLoader.addMavenRepo("https://repo1.maven.org/maven2/"); + DependencyLoader.loadLibraries(Library.builder() + .groupId("org.tukaani") + .artifactId("xz") + .minVersion(SemanticVersion.builder() + .majorVersion(1) + .minorVersion(9) + .patchVersion(-1) + .build()) + .preferredVersion(SemanticVersion.builder() + .majorVersion(1) + .minorVersion(9) + .patchVersion(-1) + .build()) + .build()); + val input = new DataInputStream(new LZMA2Options(6).getInputStream(ResourceUtil.getResourceFromJar("/mappings.lzma2", CoreLoadingPlugin.class))); { - val classMappings = - ResourceUtil.getResourceStringFromJar("/classes.csv", FalsePatternLib.class).split("\n"); + var classBytes = new byte[input.readInt()]; + input.readFully(classBytes); + val classMappings = new String(classBytes).split("\n"); for (int i = 1; i < classMappings.length; i++) { val line = classMappings[i].split(","); val clazz = new UniversalClass(line, stringPool); @@ -62,7 +84,9 @@ public class MappingManager { } } { - val fieldMappings = ResourceUtil.getResourceStringFromJar("/fields.csv", FalsePatternLib.class).split("\n"); + var fieldBytes = new byte[input.readInt()]; + input.readFully(fieldBytes); + var fieldMappings = new String(fieldBytes).split( "\n"); for (int i = 1; i < fieldMappings.length; i++) { val line = fieldMappings[i].split(","); val clazz = internalLookup.get(MappingType.Notch, line[0].substring(0, line[0].lastIndexOf('/'))); @@ -70,8 +94,9 @@ public class MappingManager { } } { - val methodMappings = - ResourceUtil.getResourceStringFromJar("/methods.csv", FalsePatternLib.class).split("\n"); + var methodBytes = new byte[input.readInt()]; + input.readFully(methodBytes); + val methodMappings = new String(methodBytes).split("\n"); for (int i = 1; i < methodMappings.length; i++) { val line = methodMappings[i].split(","); val clazz = internalLookup.get(MappingType.Notch, line[0].substring(0, line[0].lastIndexOf('/'))); diff --git a/src/main/java/com/falsepattern/lib/mixin/MinecraftURLClassPath.java b/src/main/java/com/falsepattern/lib/mixin/MinecraftURLClassPath.java index e6293a8..bb78295 100644 --- a/src/main/java/com/falsepattern/lib/mixin/MinecraftURLClassPath.java +++ b/src/main/java/com/falsepattern/lib/mixin/MinecraftURLClassPath.java @@ -21,17 +21,11 @@ package com.falsepattern.lib.mixin; import com.falsepattern.lib.StableAPI; +import com.falsepattern.lib.internal.impl.mixin.UCPImpl; import lombok.AccessLevel; import lombok.NoArgsConstructor; -import lombok.val; - -import net.minecraft.launchwrapper.LaunchClassLoader; -import cpw.mods.fml.common.Loader; -import cpw.mods.fml.common.ModClassLoader; import java.io.File; -import java.lang.reflect.Method; -import java.net.URL; /** * Backport from spongemixins 1.3 for compat with the curseforge 1.2.0 version. @@ -41,64 +35,8 @@ import java.net.URL; @NoArgsConstructor(access = AccessLevel.PRIVATE) @StableAPI(since = "0.10.0") public final class MinecraftURLClassPath { - /** - * Utility to manipulate the minecraft URL ClassPath - */ - - private static final Object ucp; - private static final Method addURL; - private static final boolean GRIMOIRE; - - static { - boolean grimoire = false; - String[] knownGrimoireClassNames = - new String[]{"io.github.crucible.grimoire.Grimoire", "io.github.crucible.grimoire.common.GrimoireCore"}; - for (val className : knownGrimoireClassNames) { - try { - Class.forName(className, false, MinecraftURLClassPath.class.getClassLoader()); - grimoire = true; - break; - } catch (ClassNotFoundException ignored) { - } - } - GRIMOIRE = grimoire; - if (!GRIMOIRE) { - try { - val modClassLoaderField = Loader.class.getDeclaredField("modClassLoader"); - modClassLoaderField.setAccessible(true); - - val loaderInstanceField = Loader.class.getDeclaredField("instance"); - loaderInstanceField.setAccessible(true); - - val mainClassLoaderField = ModClassLoader.class.getDeclaredField("mainClassLoader"); - mainClassLoaderField.setAccessible(true); - - val ucpField = LaunchClassLoader.class.getSuperclass().getDeclaredField("ucp"); - ucpField.setAccessible(true); - - Object loader = loaderInstanceField.get(null); - val modClassLoader = (ModClassLoader) modClassLoaderField.get(loader); - val mainClassLoader = (LaunchClassLoader) mainClassLoaderField.get(modClassLoader); - ucp = ucpField.get(mainClassLoader); - addURL = ucp.getClass().getDeclaredMethod("addURL", URL.class); - } catch (NoSuchFieldException | IllegalAccessException | NoSuchMethodException e) { - throw new RuntimeException(e.getMessage()); - } - } else { - ucp = null; - addURL = null; - System.err.println("Grimoire detected, disabling jar loading utility"); - } - } - - /** - * Adds a Jar to the Minecraft URL ClassPath - Needed when using mixins on classes outside of Minecraft or other - * coremods - */ @StableAPI.Expose public static void addJar(File pathToJar) throws Exception { - if (!GRIMOIRE) { - addURL.invoke(ucp, pathToJar.toURI().toURL()); - } + UCPImpl.addJar(pathToJar); } } diff --git a/src/main/java/com/falsepattern/lib/updates/UpdateCheckException.java b/src/main/java/com/falsepattern/lib/updates/UpdateCheckException.java index 16b495f..6027f44 100644 --- a/src/main/java/com/falsepattern/lib/updates/UpdateCheckException.java +++ b/src/main/java/com/falsepattern/lib/updates/UpdateCheckException.java @@ -24,22 +24,22 @@ import com.falsepattern.lib.StableAPI; @StableAPI(since = "0.8.3") public class UpdateCheckException extends Exception { - @StableAPI.Expose + @StableAPI.Internal public UpdateCheckException(String message) { super(message); } - @StableAPI.Expose + @StableAPI.Internal public UpdateCheckException(String message, Throwable cause) { super(message, cause); } - @StableAPI.Expose + @StableAPI.Internal public UpdateCheckException(Throwable cause) { super(cause); } - @StableAPI.Expose + @StableAPI.Internal protected UpdateCheckException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } diff --git a/src/main/java/com/falsepattern/lib/updates/UpdateChecker.java b/src/main/java/com/falsepattern/lib/updates/UpdateChecker.java index 079d4a0..a12c1ea 100644 --- a/src/main/java/com/falsepattern/lib/updates/UpdateChecker.java +++ b/src/main/java/com/falsepattern/lib/updates/UpdateChecker.java @@ -20,36 +20,16 @@ */ package com.falsepattern.lib.updates; -import com.falsepattern.json.node.JsonNode; import com.falsepattern.lib.StableAPI; -import com.falsepattern.lib.dependencies.DependencyLoader; -import com.falsepattern.lib.dependencies.Library; -import com.falsepattern.lib.dependencies.SemanticVersion; -import com.falsepattern.lib.internal.Internet; -import com.falsepattern.lib.internal.Tags; -import com.falsepattern.lib.internal.config.LibraryConfig; -import com.falsepattern.lib.text.FormattedText; -import lombok.val; +import com.falsepattern.lib.internal.impl.updates.UpdateCheckerImpl; -import net.minecraft.client.resources.I18n; -import net.minecraft.event.ClickEvent; import net.minecraft.util.IChatComponent; -import cpw.mods.fml.common.Loader; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; -import java.util.concurrent.atomic.AtomicBoolean; @StableAPI(since = "0.8.0") -public class UpdateChecker { - private static final AtomicBoolean jsonLibraryLoaded = new AtomicBoolean(false); - - +public final class UpdateChecker { /** * Checks for updates. The URL should be a JSON file that contains a list of mods, each with a mod ID, one or more * versions, and a URL for the user to check for updates in case the current and latest versions are different. @@ -76,89 +56,7 @@ public class UpdateChecker { */ @StableAPI.Expose public static CompletableFuture> fetchUpdatesAsync(String url) { - return CompletableFuture.supplyAsync(() -> { - if (!LibraryConfig.ENABLE_UPDATE_CHECKER) { - throw new CompletionException(new UpdateCheckException("Update checker is disabled in config!")); - } - URL URL; - try { - URL = new URL(url); - } catch (MalformedURLException e) { - throw new CompletionException(new UpdateCheckException("Invalid URL: " + url, e)); - } - if (!jsonLibraryLoaded.get()) { - try { - DependencyLoader.addMavenRepo("https://maven.falsepattern.com/"); - DependencyLoader.loadLibraries(Library.builder() - .loadingModId(Tags.MODID) - .groupId("com.falsepattern") - .artifactId("json") - .minVersion(new SemanticVersion(0, 4, 0)) - .maxVersion(new SemanticVersion(0, Integer.MAX_VALUE, Integer.MAX_VALUE)) - .preferredVersion(new SemanticVersion(0, 4, 1)) - .build()); - } catch (Exception e) { - throw new CompletionException( - new UpdateCheckException("Failed to load json library for update checker!", e)); - } - jsonLibraryLoaded.set(true); - } - val result = new ArrayList(); - JsonNode parsed; - try { - parsed = JsonNode.parse(Internet.download(URL).thenApply(String::new).join()); - } catch (CompletionException e) { - throw new CompletionException(new UpdateCheckException("Failed to download update checker JSON file!", - e.getCause() == null ? e : e.getCause())); - } - List modList; - if (parsed.isList()) { - modList = parsed.getJavaList(); - } else { - modList = Collections.singletonList(parsed); - } - val installedMods = Loader.instance().getIndexedModList(); - for (val node : modList) { - if (!node.isObject()) { - continue; - } - if (!node.containsKey("modid")) { - continue; - } - if (!node.containsKey("latestVersion")) { - continue; - } - val modid = node.getString("modid"); - if (!installedMods.containsKey(modid)) { - continue; - } - val mod = installedMods.get(modid); - val latestVersionsNode = node.get("latestVersion"); - List latestVersions; - if (latestVersionsNode.isString()) { - latestVersions = Collections.singletonList(latestVersionsNode.stringValue()); - } else if (latestVersionsNode.isList()) { - latestVersions = new ArrayList<>(); - for (val version : latestVersionsNode.getJavaList()) { - if (!version.isString()) { - continue; - } - latestVersions.add(version.stringValue()); - } - } else { - continue; - } - val currentVersion = mod.getVersion(); - if (latestVersions.contains(currentVersion)) { - continue; - } - val updateURL = - node.containsKey("updateURL") && node.get("updateURL").isString() ? node.getString("updateURL") - : ""; - result.add(new ModUpdateInfo(modid, currentVersion, latestVersions.get(0), updateURL)); - } - return result; - }); + return UpdateCheckerImpl.fetchUpdatesAsync(url); } /** @@ -172,17 +70,7 @@ public class UpdateChecker { */ @StableAPI.Expose public static List fetchUpdates(String url) throws UpdateCheckException { - try { - return fetchUpdatesAsync(url).join(); - } catch (CompletionException e) { - try { - throw e.getCause(); - } catch (UpdateCheckException e1) { - throw e1; - } catch (Throwable e1) { - throw new UpdateCheckException("Failed to check for updates!", e1); - } - } + return UpdateCheckerImpl.fetchUpdates(url); } /** @@ -195,38 +83,6 @@ public class UpdateChecker { */ @StableAPI.Expose public static List updateListToChatMessages(String initiator, List updates) { - if (updates == null || updates.size() == 0) { - return null; - } - val updateText = new ArrayList( - FormattedText.parse(I18n.format("falsepatternlib.chat.updatesavailable", initiator)).toChatText()); - val mods = Loader.instance().getIndexedModList(); - for (val update : updates) { - val mod = mods.get(update.modID); - updateText.addAll( - FormattedText.parse(I18n.format("falsepatternlib.chat.modname", mod.getName())).toChatText()); - updateText.addAll( - FormattedText.parse(I18n.format("falsepatternlib.chat.currentversion", update.currentVersion)) - .toChatText()); - updateText.addAll( - FormattedText.parse(I18n.format("falsepatternlib.chat.latestversion", update.latestVersion)) - .toChatText()); - if (!update.updateURL.isEmpty()) { - val pre = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurlpre")).toChatText(); - val link = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurl")).toChatText(); - val post = FormattedText.parse(I18n.format("falsepatternlib.chat.updateurlpost")).toChatText(); - pre.get(pre.size() - 1).appendSibling(link.get(0)); - link.get(link.size() - 1).appendSibling(post.get(0)); - for (val l : link) { - l.getChatStyle().setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, update.updateURL)); - } - link.remove(0); - post.remove(0); - updateText.addAll(pre); - updateText.addAll(link); - updateText.addAll(post); - } - } - return updateText; + return UpdateCheckerImpl.updateListToChatMessages(initiator, updates); } } diff --git a/src/main/resources/mappings.lzma2 b/src/main/resources/mappings.lzma2 new file mode 100644 index 0000000..0de3f11 Binary files /dev/null and b/src/main/resources/mappings.lzma2 differ diff --git a/src/test/java/com/falsepattern/lib/internal/tooling/Compact.java b/src/test/java/com/falsepattern/lib/internal/tooling/Compact.java new file mode 100644 index 0000000..707e812 --- /dev/null +++ b/src/test/java/com/falsepattern/lib/internal/tooling/Compact.java @@ -0,0 +1,28 @@ +package com.falsepattern.lib.internal.tooling; + +import org.tukaani.xz.FinishableOutputStream; +import org.tukaani.xz.FinishableWrapperOutputStream; +import org.tukaani.xz.LZMA2Options; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; + +public class Compact { + public static void main(String[] args) throws IOException { + byte[] file1 = Files.readAllBytes(Paths.get("mappings", "classes.csv")); + byte[] file2 = Files.readAllBytes(Paths.get("mappings", "fields.csv")); + byte[] file3 = Files.readAllBytes(Paths.get("mappings", "methods.csv")); + FinishableOutputStream lzOut = new LZMA2Options(6).getOutputStream(new FinishableWrapperOutputStream(Files.newOutputStream(Paths.get("src", "main", "resources", "mappings.lzma2")))); + DataOutputStream dOut = new DataOutputStream(lzOut); + dOut.writeInt(file1.length); + dOut.write(file1); + dOut.writeInt(file2.length); + dOut.write(file2); + dOut.writeInt(file3.length); + dOut.write(file3); + lzOut.finish(); + lzOut.close(); + } +} diff --git a/src/main/java/com/falsepattern/lib/internal/SRGGen.java b/src/test/java/com/falsepattern/lib/internal/tooling/SRGGen.java similarity index 98% rename from src/main/java/com/falsepattern/lib/internal/SRGGen.java rename to src/test/java/com/falsepattern/lib/internal/tooling/SRGGen.java index d49838f..ccf2e7d 100644 --- a/src/main/java/com/falsepattern/lib/internal/SRGGen.java +++ b/src/test/java/com/falsepattern/lib/internal/tooling/SRGGen.java @@ -18,9 +18,8 @@ * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ -package com.falsepattern.lib.internal; +package com.falsepattern.lib.internal.tooling; -import lombok.Getter; import java.io.IOException; import java.io.OutputStream; @@ -33,8 +32,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -@SuppressWarnings("ALL") -@Getter class SRGGen { private static final Map class_notch_srg = new HashMap<>(); private static final Map class_notch_mcp = new HashMap<>(); @@ -77,6 +74,7 @@ class SRGGen { } } + @SuppressWarnings("UnusedReturnValue") private static boolean crossValidate(Map notch_srg, Map notch_mcp, Map srg_mcp, Map mcp_srg, Map mcp_notch, OutputStream output) throws IOException { for (Map.Entry notch_srg_entry : notch_srg.entrySet()) {