From 400029524caa087d0541aeca70a23d2c9a271058 Mon Sep 17 00:00:00 2001 From: ev chang Date: Sat, 29 Jun 2024 05:40:08 +0900 Subject: [PATCH] bump gradle, fix mods checker plugin using fmlloadingplugin instead of launchwrapper, make mod detection use last modified instead of arbitrary alphabetical order --- build.gradle.kts | 23 +- gradle.properties | 4 +- root.gradle.kts | 4 +- settings.gradle.kts | 2 +- .../crashpatch/hooks/ModsCheckerPlugin.java | 223 ++++++++++-------- 5 files changed, 140 insertions(+), 116 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index e38fd02..a3b3415 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,7 +12,7 @@ plugins { id("org.polyfrost.defaults.java") id("org.polyfrost.defaults.loom") id("com.github.johnrengelman.shadow") - id("net.kyori.blossom") version "1.3.1" + id("net.kyori.blossom") version "1.3.2" id("signing") java } @@ -23,11 +23,6 @@ val mod_version: String by project val mod_id: String by project val mod_archives_name: String by project -// Sets up the variables for when we preprocess to other Minecraft versions. -preprocess { - vars.put("MODERN", if (project.platform.mcMinor >= 16) 1 else 0) -} - // Replaces the variables in `ExampleMod.java` to the ones specified in `gradle.properties`. blossom { replaceToken("@VER@", mod_version) @@ -57,8 +52,8 @@ loom { if (project.platform.isLegacyForge) { runConfigs { "client" { - programArgs("--tweakClass", "cc.polyfrost.oneconfig.loader.stage0.LaunchWrapperTweaker") - property("fml.coreMods.load", "org.polyfrost.crashpatch.hooks.ModsCheckerPlugin") + programArgs("--tweakClass", "org.polyfrost.crashpatch.hooks.ModsCheckerPlugin") + //property("fml.coreMods.load", "") property("mixin.debug.export", "true") } } @@ -93,14 +88,14 @@ repositories { // Configures the libraries/dependencies for your mod. dependencies { // Adds the OneConfig library, so we can develop with it. - modCompileOnly("cc.polyfrost:oneconfig-$platform:0.2.1-alpha+") + modCompileOnly("cc.polyfrost:oneconfig-$platform:0.2.2-alpha+") - modRuntimeOnly("me.djtheredstoner:DevAuth-${if (platform.isFabric) "fabric" else if (platform.isLegacyForge) "forge-legacy" else "forge-latest"}:1.1.2") - shade("com.github.aternosorg:mclogs-java:3.0.1") + modRuntimeOnly("me.djtheredstoner:DevAuth-${if (platform.isFabric) "fabric" else if (platform.isLegacyForge) "forge-legacy" else "forge-latest"}:1.2.0") + shade("gs.mclo:api:3.0.1") // If we are building for legacy forge, includes the launch wrapper with `shade` as we configured earlier. if (platform.isLegacyForge) { compileOnly("org.spongepowered:mixin:0.7.11-SNAPSHOT") - shade("cc.polyfrost:oneconfig-wrapper-launchwrapper:1.0.0-beta+") + shade("cc.polyfrost:oneconfig-wrapper-launchwrapper:1.0.0-beta17") } } @@ -183,11 +178,9 @@ tasks { manifest.attributes += mapOf( "ModSide" to "CLIENT", // We aren't developing a server-side mod, so this is fine. "ForceLoadAsMod" to true, // We want to load this jar as a mod, so we force Forge to do so. - "FMLCorePluginContainsFMLMod" to "Yes, yes it does", - "FMLCorePlugin" to "org.polyfrost.crashpatch.hooks.ModsCheckerPlugin", "TweakOrder" to "0", // Makes sure that the OneConfig launch wrapper is loaded as soon as possible. "MixinConfigs" to "mixin.${mod_id}.json", // We want to use our mixin configuration, so we specify it here. - "TweakClass" to "cc.polyfrost.oneconfig.loader.stage0.LaunchWrapperTweaker" // Loads the OneConfig launch wrapper. + "TweakClass" to "org.polyfrost.crashpatch.hooks.ModsCheckerPlugin" // Loads the OneConfig launch wrapper. ) } dependsOn(shadowJar) diff --git a/gradle.properties b/gradle.properties index d3671fb..5c335ba 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,10 @@ mod_id=crashpatch mod_name=CrashPatch -mod_version=2.0.0 +mod_version=2.0.1 mod_archives_name=CrashPatch # Gradle Configuration -- DO NOT TOUCH THESE VALUES. -polyfrost.defaults.loom=1 +polyfrost.defaults.loom=3 org.gradle.daemon=true org.gradle.parallel=true org.gradle.configureoncommand=true diff --git a/root.gradle.kts b/root.gradle.kts index 2b3f7b0..0234352 100644 --- a/root.gradle.kts +++ b/root.gradle.kts @@ -1,7 +1,7 @@ plugins { - kotlin("jvm") version "1.8.22" apply false + kotlin("jvm") version "1.9.10" apply false id("org.polyfrost.multi-version.root") - id("com.github.johnrengelman.shadow") version "7.1.2" apply false + id("com.github.johnrengelman.shadow") version "8.1.1" apply false } preprocess { diff --git a/settings.gradle.kts b/settings.gradle.kts index 9692a27..6973a98 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -7,7 +7,7 @@ pluginManagement { maven("https://repo.polyfrost.org/releases") // Adds the Polyfrost maven repository to get Polyfrost Gradle Toolkit } plugins { - val pgtVersion = "0.2.9" // Sets the default versions for Polyfrost Gradle Toolkit + val pgtVersion = "0.6.2" // Sets the default versions for Polyfrost Gradle Toolkit id("org.polyfrost.multi-version.root") version pgtVersion } } diff --git a/src/main/java/org/polyfrost/crashpatch/hooks/ModsCheckerPlugin.java b/src/main/java/org/polyfrost/crashpatch/hooks/ModsCheckerPlugin.java index 114d2e8..bb00501 100644 --- a/src/main/java/org/polyfrost/crashpatch/hooks/ModsCheckerPlugin.java +++ b/src/main/java/org/polyfrost/crashpatch/hooks/ModsCheckerPlugin.java @@ -1,12 +1,19 @@ package org.polyfrost.crashpatch.hooks; +import cc.polyfrost.oneconfig.loader.stage0.LaunchWrapperTweaker; import com.google.common.collect.Lists; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.stream.MalformedJsonException; +import net.minecraft.launchwrapper.ITweaker; +import net.minecraft.launchwrapper.Launch; +import net.minecraft.launchwrapper.LaunchClassLoader; import net.minecraftforge.fml.common.versioning.DefaultArtifactVersion; -import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; +import net.minecraftforge.fml.relauncher.CoreModManager; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; +import org.spongepowered.asm.launch.MixinBootstrap; +import org.spongepowered.asm.launch.MixinTweaker; import javax.swing.*; import java.awt.*; @@ -15,107 +22,156 @@ import java.io.InputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.security.CodeSource; import java.util.List; import java.util.*; import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -public class ModsCheckerPlugin implements IFMLLoadingPlugin { +public class ModsCheckerPlugin extends LaunchWrapperTweaker { private static final JsonParser PARSER = new JsonParser(); public static final HashMap> modsMap = new HashMap<>(); //modid : file, version, name - public ModsCheckerPlugin() { - File modsFolder = new File(getMcDir(), "mods"); - File[] modFolder = modsFolder.listFiles((dir, name) -> name.endsWith(".jar")); - HashMap>> dupeMap = new HashMap<>(); - if (modFolder != null) { - for (File file : modFolder) { - try { - try (ZipFile mod = new ZipFile(file)) { - ZipEntry entry = mod.getEntry("mcmod.info"); - if (entry != null) { - try (InputStream inputStream = mod.getInputStream(entry)) { - byte[] availableBytes = new byte[inputStream.available()]; - inputStream.read(availableBytes, 0, inputStream.available()); - JsonObject modInfo = PARSER.parse(new String(availableBytes)).getAsJsonArray().get(0).getAsJsonObject(); - if (!modInfo.has("modid") || !modInfo.has("version")) { - continue; - } + @Override + public void injectIntoClassLoader(LaunchClassLoader classLoader) { + try { + File modsFolder = new File(getMcDir(), "mods"); + File[] modFolder = modsFolder.listFiles((dir, name) -> name.endsWith(".jar")); + HashMap>> dupeMap = new HashMap<>(); + if (modFolder != null) { + for (File file : modFolder) { + try { + try (ZipFile mod = new ZipFile(file)) { + ZipEntry entry = mod.getEntry("mcmod.info"); + if (entry != null) { + try (InputStream inputStream = mod.getInputStream(entry)) { + byte[] availableBytes = new byte[inputStream.available()]; + inputStream.read(availableBytes, 0, inputStream.available()); + JsonObject modInfo = PARSER.parse(new String(availableBytes)).getAsJsonArray().get(0).getAsJsonObject(); + if (!modInfo.has("modid") || !modInfo.has("version")) { + continue; + } - String modid = modInfo.get("modid").getAsString(); - if (modsMap.containsKey(modid)) { - if (dupeMap.containsKey(modid)) { - dupeMap.get(modid).add(new Triple<>(file, modInfo.get("version").getAsString(), modInfo.has("name") ? modInfo.get("name").getAsString() : modid)); + String modid = modInfo.get("modid").getAsString(); + if (modsMap.containsKey(modid)) { + if (dupeMap.containsKey(modid)) { + dupeMap.get(modid).add(new Triple<>(file, modInfo.get("version").getAsString(), modInfo.has("name") ? modInfo.get("name").getAsString() : modid)); + } else { + dupeMap.put(modid, Lists.newArrayList(modsMap.get(modid), new Triple<>(file, modInfo.get("version").getAsString(), modInfo.has("name") ? modInfo.get("name").getAsString() : modid))); + } } else { - dupeMap.put(modid, Lists.newArrayList(modsMap.get(modid), new Triple<>(file, modInfo.get("version").getAsString(), modInfo.has("name") ? modInfo.get("name").getAsString() : modid))); + modsMap.put(modid, new Triple<>(file, modInfo.get("version").getAsString(), modInfo.has("name") ? modInfo.get("name").getAsString() : modid)); } - } else { - modsMap.put(modid, new Triple<>(file, modInfo.get("version").getAsString(), modInfo.has("name") ? modInfo.get("name").getAsString() : modid)); } } } + } catch (MalformedJsonException | IllegalStateException ignored) { + } catch (Exception e) { + e.printStackTrace(); } - } catch (MalformedJsonException | IllegalStateException ignored) { - } catch (Exception e) { - e.printStackTrace(); } } - } - Iterator>> iterator = dupeMap.values().iterator(); + Iterator>> iterator = dupeMap.values().iterator(); - while (iterator.hasNext()) { - try { - ArrayList> next = iterator.next(); - List> blank = next.stream().sorted((a, b) -> { - if (a != null && b != null) { - try { - int value = new DefaultArtifactVersion(substringBeforeAny(a.second, "-beta", "-alpha", "-pre", "+beta", "+alpha", "+pre")).compareTo(new DefaultArtifactVersion(substringBeforeAny(b.second, "-beta", "-alpha", "-pre", "+beta", "+alpha", "+pre"))); - return -value; - } catch (Exception e) { - e.printStackTrace(); + boolean isSkyClient = new File(getMcDir(), "W-OVERFLOW/CrashPatch/SKYCLIENT").exists() || containsAnyKey(ModsCheckerPlugin.modsMap, "skyclientcosmetics", "scc", "skyclientaddons", "skyblockclientupdater", "skyclientupdater", "skyclientcore"); + while (iterator.hasNext()) { + try { + ArrayList> next = iterator.next(); + List> blank = next.stream().sorted((a, b) -> { + if (a != null && b != null) { try { - String[] array = {a.second, b.second}; - Arrays.sort(array); - return array[0].equals(a.second) ? -1 : Objects.equals(a.second, b.second) ? 0 : 1; - } catch (Exception ex) { - ex.printStackTrace(); - return 0; + int value = new DefaultArtifactVersion(substringBeforeAny(a.second, "-beta", "-alpha", "-pre", "+beta", "+alpha", "+pre")).compareTo(new DefaultArtifactVersion(substringBeforeAny(b.second, "-beta", "-alpha", "-pre", "+beta", "+alpha", "+pre"))); + return -value; + } catch (Exception e) { + e.printStackTrace(); + return Long.compare(a.first.lastModified(), b.first.lastModified()) * -1; } } - } - return 0; - }).collect(Collectors.toList()); - next.clear(); - next.addAll(blank); - ListIterator> otherIterator = next.listIterator(); - int index = 0; - while (otherIterator.hasNext()) { - Triple remove = otherIterator.next(); - ++index; - if (index != 1) { - if (tryDeleting(remove.first)) { - otherIterator.remove(); - } else { - doThatPopupThing(modsFolder, "Duplicate mods have been detected! These mods are...\n" + - getStringOf(dupeMap.values()) + "\nPlease removes these mods from your mod folder, which is opened." + ((new File(getMcDir(), "W-OVERFLOW/CrashPatch/SKYCLIENT").exists() || containsAnyKey(ModsCheckerPlugin.modsMap, "skyclientcosmetics", "scc", "skyclientaddons", "skyblockclientupdater", "skyclientupdater", "skyclientcore")) ? " GO TO https://inv.wtf/skyclient FOR MORE INFORMATION." : "")); + return 0; + }).collect(Collectors.toList()); + next.clear(); + next.addAll(blank); + ListIterator> otherIterator = next.listIterator(); + int index = 0; + while (otherIterator.hasNext()) { + Triple remove = otherIterator.next(); + ++index; + if (index != 1) { + if (tryDeleting(remove.first)) { + otherIterator.remove(); + } else { + doThatPopupThing(modsFolder, "Duplicate mods have been detected! These mods are...\n" + + getStringOf(dupeMap.values()) + "\nPlease removes these mods from your mod folder, which is opened." + (isSkyClient ? " GO TO https://inv.wtf/skyclient FOR MORE INFORMATION." : "")); + } } } + if (next.size() <= 1) { + iterator.remove(); + } + } catch (Exception e) { + e.printStackTrace(); } - if (next.size() <= 1) { - iterator.remove(); - } - } catch (Exception e) { - e.printStackTrace(); } + + + if (!dupeMap.isEmpty()) { + doThatPopupThing(modsFolder, "Duplicate mods have been detected! These mods are...\n" + + getStringOf(dupeMap.values()) + "\nPlease removes these mods from your mod folder, which is opened." + (isSkyClient ? " GO TO https://inv.wtf/skyclient FOR MORE INFORMATION." : "")); + } + } catch (Exception e) { + e.printStackTrace(); } + CodeSource codeSource = this.getClass().getProtectionDomain().getCodeSource(); + if (codeSource != null) { + URL location = codeSource.getLocation(); + try { + File file = new File(location.toURI()); + if (file.isFile()) { + CoreModManager.getIgnoredMods().remove(file.getName()); + CoreModManager.getReparseableCoremods().add(file.getName()); + try { + try { + List tweakClasses = (List) Launch.blackboard.get("TweakClasses"); // tweak classes before other mod trolling + if (tweakClasses.contains("org.spongepowered.asm.launch.MixinTweaker")) { // if there's already a mixin tweaker, we'll just load it like "usual" + new MixinTweaker(); // also we might not need to make a new mixin tweawker all the time but im just making sure + } else if (!Launch.blackboard.containsKey("mixin.initialised")) { // if there isnt, we do our own trolling + List tweaks = (List) Launch.blackboard.get("Tweaks"); + tweaks.add(new MixinTweaker()); + } + } catch (Exception ignored) { + // if it fails i *think* we can just ignore it + } + try { + MixinBootstrap.getPlatform().addContainer(location.toURI()); + } catch (Exception ignore) { + // fuck you essential + try { + Class containerClass = Class.forName("org.spongepowered.asm.launch.platform.container.IContainerHandle"); + Class urlContainerClass = Class.forName("org.spongepowered.asm.launch.platform.container.ContainerHandleURI"); + Object container = urlContainerClass.getConstructor(URI.class).newInstance(location.toURI()); + MixinBootstrap.getPlatform().getClass().getDeclaredMethod("addContainer", containerClass).invoke(MixinBootstrap.getPlatform(), container); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException("OneConfig's Mixin loading failed. Please contact https://polyfrost.cc/discord to resolve this issue!"); + } + } + } catch (Exception ignored) { - if (!dupeMap.isEmpty()) { - doThatPopupThing(modsFolder, "Duplicate mods have been detected! These mods are...\n" + - getStringOf(dupeMap.values()) + "\nPlease removes these mods from your mod folder, which is opened." + ((new File(getMcDir(), "W-OVERFLOW/CrashPatch/SKYCLIENT").exists() || containsAnyKey(ModsCheckerPlugin.modsMap, "skyclientcosmetics", "scc", "skyclientaddons", "skyblockclientupdater", "skyclientupdater", "skyclientcore")) ? " GO TO https://inv.wtf/skyclient FOR MORE INFORMATION." : "")); + } + } + } catch (URISyntaxException ignored) {} + } else { + LogManager.getLogger().warn("No CodeSource, if this is not a development environment we might run into problems!"); + LogManager.getLogger().warn(this.getClass().getProtectionDomain()); } + + super.injectIntoClassLoader(classLoader); } private static void doThatPopupThing(File modsFolder, String message) { @@ -188,31 +244,6 @@ private boolean tryDeleting(File file) { return true; } - @Override - public String[] getASMTransformerClass() { - return new String[0]; - } - - @Override - public String getModContainerClass() { - return null; - } - - @Override - public String getSetupClass() { - return null; - } - - @Override - public void injectData(Map map) { - - } - - @Override - public String getAccessTransformerClass() { - return null; - } - public static class Triple { public A first; public B second;