aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-03-07 21:55:09 +0100
committerGitHub <noreply@github.com>2024-03-07 21:55:09 +0100
commit5c8c3e81a891da36fa752d5f67886bc02ed504dd (patch)
tree0ada1c40c51a41465703d34c2962cea6d19b78da
parentaf5543f73ffcf16cf520b7cf854a18c7e70f4237 (diff)
downloadNotEnoughUpdates-5c8c3e81a891da36fa752d5f67886bc02ed504dd.tar.gz
NotEnoughUpdates-5c8c3e81a891da36fa752d5f67886bc02ed504dd.tar.bz2
NotEnoughUpdates-5c8c3e81a891da36fa752d5f67886bc02ed504dd.zip
Fix wrong mod loader warning on modern versions of minecraft (#1030)
-rw-r--r--build.gradle.kts16
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java1
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/loader/ClassLoaderExtUtil.java37
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/loader/JARLoadingTweaker.java132
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java139
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/loader/MixinLoadingTweaker.java47
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/loader/NEUDelegatingTweaker.java3
-rw-r--r--src/main/resources/META-INF/mods.toml2
8 files changed, 269 insertions, 108 deletions
diff --git a/build.gradle.kts b/build.gradle.kts
index 3ed5d4e4..9c859169 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -105,6 +105,10 @@ val kotlinDependencies: Configuration by configurations.creating {
configurations.implementation.get().extendsFrom(this)
}
+val mixinRTDependencies: Configuration by configurations.creating {
+ configurations.implementation.get().extendsFrom(this)
+}
+
val oneconfigQuarantineSourceSet: SourceSet = sourceSets.create("oneconfig") {
java {
srcDir(layout.projectDirectory.dir("src/main/oneconfig"))
@@ -148,7 +152,7 @@ dependencies {
shadowImplementation("com.mojang:brigadier:1.0.18")
- shadowImplementation("org.spongepowered:mixin:0.7.11-SNAPSHOT") {
+ mixinRTDependencies("org.spongepowered:mixin:0.7.11-SNAPSHOT") {
isTransitive = false // Dependencies of mixin are already bundled by minecraft
}
annotationProcessor("net.fabricmc:sponge-mixin:0.11.4+mixin.0.8.5")
@@ -224,10 +228,16 @@ tasks.remapSourcesJar {
// Use Zip instead of Jar as to not include META-INF
val kotlinDependencyCollectionJar by tasks.creating(Zip::class) {
archiveFileName.set("kotlin-libraries-wrapped.jar")
- destinationDirectory.set(project.layout.buildDirectory.dir("kotlinwrapper"))
+ destinationDirectory.set(project.layout.buildDirectory.dir("wrapperjars"))
from(kotlinDependencies)
into("neu-kotlin-libraries-wrapped")
}
+val mixinDependencyCollectionJar by tasks.creating(Zip::class) {
+ archiveFileName.set("mixin-libraries-wrapped.jar")
+ destinationDirectory.set(project.layout.buildDirectory.dir("wrapperjars"))
+ from(mixinRTDependencies)
+ into("neu-mixin-libraries-wrapped")
+}
tasks.register("includeBackupRepo") {
doLast {
@@ -257,7 +267,9 @@ tasks.shadowJar {
}
from(oneconfigQuarantineSourceSet.output)
from(kotlinDependencyCollectionJar)
+ from(mixinDependencyCollectionJar)
dependsOn(kotlinDependencyCollectionJar)
+ dependsOn(mixinDependencyCollectionJar)
fun relocate(name: String) = relocate(name, "io.github.moulberry.notenoughupdates.deps.$name")
relocate("com.mojang.brigadier")
relocate("io.github.moulberry.moulconfig")
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java
index 1ae5199a..bedbc87b 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/envcheck/EnvironmentScan.java
@@ -78,6 +78,7 @@ public class EnvironmentScan {
public static void showErrorMessage(String... messages) {
String message = String.join("\n", messages);
+ System.setProperty("java.awt.headless", "false");
JOptionPane.showMessageDialog(
null, message, "NotEnoughUpdates - Problematic System Configuration", JOptionPane.ERROR_MESSAGE
);
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/loader/ClassLoaderExtUtil.java b/src/main/java/io/github/moulberry/notenoughupdates/loader/ClassLoaderExtUtil.java
new file mode 100644
index 00000000..4c410b3d
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/loader/ClassLoaderExtUtil.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.loader;
+
+import net.minecraft.launchwrapper.LaunchClassLoader;
+
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+class ClassLoaderExtUtil {
+ public static void addClassSourceTwice(LaunchClassLoader classLoader, URL url) throws Exception {
+ classLoader.addURL(url);
+ ClassLoader classLoaderYetAgain = classLoader.getClass().getClassLoader();
+ Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
+ addURL.setAccessible(true);
+ addURL.invoke(classLoaderYetAgain, url);
+ }
+
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/loader/JARLoadingTweaker.java b/src/main/java/io/github/moulberry/notenoughupdates/loader/JARLoadingTweaker.java
new file mode 100644
index 00000000..abd4712b
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/loader/JARLoadingTweaker.java
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2024 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.loader;
+
+import lombok.SneakyThrows;
+import net.minecraft.launchwrapper.ITweaker;
+import net.minecraft.launchwrapper.Launch;
+import net.minecraft.launchwrapper.LaunchClassLoader;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+/**
+ * Tweaker used to load library JARs conditionally. See the subclasses for concrete implementations.
+ */
+public abstract class JARLoadingTweaker implements ITweaker {
+
+ /**
+ * @return a path pointing to a folder filled with JAR files
+ */
+ protected abstract Path getFilesToLoad();
+
+ protected abstract String getTestClass();
+
+ @SneakyThrows
+ protected @Nullable Path getShadowedElement(String path) {
+ URI uri = Objects.requireNonNull(getClass().getResource(path)).toURI();
+ if ("jar".equals(uri.getScheme())) {
+ FileSystem fs = FileSystems.newFileSystem(uri, Collections.emptyMap());
+ closeFileSystemLater(fs);
+ return fs.getPath(path);
+ } else {
+ return Paths.get(uri);
+ }
+ }
+
+ private List<FileSystem> toClose = new ArrayList<>();
+
+ protected void closeFileSystemLater(FileSystem fileSystem) {
+ toClose.add(fileSystem);
+ }
+
+ @Override
+ public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
+
+ }
+
+ protected void performLoading(LaunchClassLoader classLoader) {
+ try {
+ if (Launch.blackboard.get("fml.deobfuscatedEnvironment") == Boolean.TRUE) {
+ System.out.println("Skipping JAR loading in development environment.");
+ return;
+ }
+
+ Path p = getFilesToLoad();
+
+ System.out.println("Loading a JAR from " + p.toAbsolutePath());
+ Path tempDirectory = Files.createTempDirectory("notenoughupdates-extracted-" + getClass().getSimpleName());
+ System.out.println("Using temporary directory " + tempDirectory + " to store extracted jars.");
+ tempDirectory.toFile().deleteOnExit();
+ try (Stream<Path> libraries = Files.walk(p, 1)) {
+ libraries.filter(it -> it.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".jar"))
+ .forEach(it -> {
+ try {
+ Path extractedPath = tempDirectory.resolve(it.getFileName().toString());
+ extractedPath.toFile().deleteOnExit();
+ Files.copy(it, extractedPath);
+ ClassLoaderExtUtil.addClassSourceTwice(classLoader, extractedPath.toUri().toURL());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+ classLoader.loadClass(getTestClass());
+ System.out.println("Could successfully load a class from loaded library.");
+ } catch (Throwable e) {
+ System.err.println("Failed to load a JAR into NEU. This is most likely a bad thing.");
+ e.printStackTrace();
+ } finally {
+ Iterator<FileSystem> iterator = toClose.iterator();
+ while (iterator.hasNext())
+ try {
+ iterator.next().close();
+ } catch (Throwable e) {
+ e.printStackTrace();
+ } finally {
+ iterator.remove();
+ }
+ }
+
+ }
+
+ @Override
+ public String getLaunchTarget() {
+ return null;
+ }
+
+ @Override
+ public String[] getLaunchArguments() {
+ return new String[0];
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java b/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java
index 2647fe34..0ce682dd 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/loader/KotlinLoadingTweaker.java
@@ -19,25 +19,11 @@
package io.github.moulberry.notenoughupdates.loader;
-import net.minecraft.launchwrapper.ITweaker;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
-import java.io.File;
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
import java.nio.file.Path;
-import java.nio.file.Paths;
import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.stream.Stream;
/**
* <h3>TO OTHER MOD AUTHORS THAT WANT TO BUNDLE KOTLIN AND ARE RUNNING INTO CONFLICTS WITH NEU:</h3>
@@ -75,7 +61,7 @@ import java.util.stream.Stream;
* so we have to make due with our crude hack.
* </p>
*/
-public class KotlinLoadingTweaker implements ITweaker {
+public class KotlinLoadingTweaker extends JARLoadingTweaker {
/**
* Full version format: [1, 7, 20] (1.7.20)
@@ -84,8 +70,41 @@ public class KotlinLoadingTweaker implements ITweaker {
public static final int[] BUNDLED_KOTLIN_VERSION = new int[]{1, 8, 21};
@Override
- public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
+ protected Path getFilesToLoad() {
+ if ("1".equals(System.getProperty("neu.relinquishkotlin"))) {
+ System.out.println("NEU is forced to relinquish Kotlin by user configuration.");
+ return null;
+ }
+ if (Launch.blackboard.get("fml.deobfuscatedEnvironment") == Boolean.TRUE) {
+ System.out.println("Skipping NEU Kotlin loading in development environment.");
+ return null;
+ }
+ Object relinquishAlways = Launch.blackboard.get("neu.relinquishkotlin.always");
+ if (relinquishAlways == Boolean.TRUE) {
+ System.err.println(
+ "NEU is forced to blanket relinquish loading Kotlin. This is probably a bad judgement call by another developer.");
+ return null;
+ }
+ Object relinquishIfBelow = Launch.blackboard.get("neu.relinquishkotlin.ifbelow");
+ if ((relinquishIfBelow instanceof int[])) {
+ int[] requiredVersion = (int[]) relinquishIfBelow;
+ if (!areWeBundlingAKotlinVersionHigherThan(requiredVersion)) {
+ System.err.println(
+ "NEU is relinquishing loading Kotlin because a higher version is requested. This may lead to errors if the advertised Kotlin version is not found. (" +
+ Arrays.toString(requiredVersion) + " required, " + Arrays.toString(BUNDLED_KOTLIN_VERSION) +
+ " available)");
+ return null;
+ }
+ }
+ System.out.println("Attempting to load Kotlin from NEU wrapped libraries.");
+
+ return getShadowedElement("/neu-kotlin-libraries-wrapped");
+ }
+
+ @Override
+ protected String getTestClass() {
+ return "kotlin.KotlinVersion";
}
public boolean areWeBundlingAKotlinVersionHigherThan(int[] x) {
@@ -101,92 +120,6 @@ public class KotlinLoadingTweaker implements ITweaker {
@Override
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
- FileSystem fs = null;
- try {
- if ("1".equals(System.getProperty("neu.relinquishkotlin"))) {
- System.out.println("NEU is forced to relinquish Kotlin by user configuration.");
- return;
- }
- if (Launch.blackboard.get("fml.deobfuscatedEnvironment") == Boolean.TRUE) {
- System.out.println("Skipping NEU Kotlin loading in development environment.");
- return;
- }
- Object relinquishAlways = Launch.blackboard.get("neu.relinquishkotlin.always");
- if (relinquishAlways == Boolean.TRUE) {
- System.err.println(
- "NEU is forced to blanket relinquish loading Kotlin. This is probably a bad judgement call by another developer.");
- return;
- }
- Object relinquishIfBelow = Launch.blackboard.get("neu.relinquishkotlin.ifbelow");
- if ((relinquishIfBelow instanceof int[])) {
- int[] requiredVersion = (int[]) relinquishIfBelow;
- if (!areWeBundlingAKotlinVersionHigherThan(requiredVersion)) {
- System.err.println(
- "NEU is relinquishing loading Kotlin because a higher version is requested. This may lead to errors if the advertised Kotlin version is not found. (" +
- Arrays.toString(requiredVersion) + " required, " + Arrays.toString(BUNDLED_KOTLIN_VERSION) + " available)");
- return;
- }
- }
-
- System.out.println("Attempting to load Kotlin from NEU wrapped libraries.");
-
- URI uri = getClass().getResource("/neu-kotlin-libraries-wrapped").toURI();
- Path p;
- if ("jar".equals(uri.getScheme())) {
- fs = FileSystems.newFileSystem(uri, Collections.emptyMap());
- p = fs.getPath(
- "/neu-kotlin-libraries-wrapped");
- } else {
- p = Paths.get(uri);
- }
- System.out.println("Loading NEU Kotlin from " + p.toAbsolutePath());
- Path tempDirectory = Files.createTempDirectory("notenoughupdates-extracted-kotlin");
- System.out.println("Using temporary directory " + tempDirectory + " to store extracted kotlin.");
- tempDirectory.toFile().deleteOnExit();
- try (Stream<Path> libraries = Files.walk(p, 1)) {
- libraries.filter(it -> it.getFileName().toString().toLowerCase(Locale.ROOT).endsWith(".jar"))
- .forEach(it -> {
- try {
- Path extractedPath = tempDirectory.resolve(it.getFileName().toString());
- extractedPath.toFile().deleteOnExit();
- Files.copy(it, extractedPath);
- addClassSourceTwice(classLoader, extractedPath.toUri().toURL());
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- });
- }
- classLoader.loadClass("kotlin.KotlinVersion");
- System.out.println("Could successfully load a Kotlin class.");
- } catch (Throwable e) {
- System.err.println("Failed to load Kotlin into NEU. This is most likely a bad thing.");
- e.printStackTrace();
- } finally {
- if (fs != null) {
- try {
- fs.close();
- } catch (Throwable e) {
- e.printStackTrace();
- }
- }
- }
- }
-
- private void addClassSourceTwice(LaunchClassLoader classLoader, URL url) throws Exception {
- classLoader.addURL(url);
- ClassLoader classLoaderYetAgain = classLoader.getClass().getClassLoader();
- Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
- addURL.setAccessible(true);
- addURL.invoke(classLoaderYetAgain, url);
- }
-
- @Override
- public String getLaunchTarget() {
- return null;
- }
-
- @Override
- public String[] getLaunchArguments() {
- return new String[0];
+ performLoading(classLoader);
}
}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/loader/MixinLoadingTweaker.java b/src/main/java/io/github/moulberry/notenoughupdates/loader/MixinLoadingTweaker.java
new file mode 100644
index 00000000..84ad90e8
--- /dev/null
+++ b/src/main/java/io/github/moulberry/notenoughupdates/loader/MixinLoadingTweaker.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package io.github.moulberry.notenoughupdates.loader;
+
+import net.minecraft.launchwrapper.Launch;
+import net.minecraft.launchwrapper.LaunchClassLoader;
+
+import java.nio.file.Path;
+
+public class MixinLoadingTweaker extends JARLoadingTweaker {
+
+ @Override
+ protected Path getFilesToLoad() {
+ return getShadowedElement("/neu-mixin-libraries-wrapped");
+ }
+
+ @Override
+ protected String getTestClass() {
+ return "org.spongepowered.asm.launch.MixinBootstrap";
+ }
+
+ @Override
+ public void injectIntoClassLoader(LaunchClassLoader classLoader) {
+ // Explicitly don't inject in here. Instead use the constructor.
+ }
+
+ public MixinLoadingTweaker() {
+ performLoading(Launch.classLoader);
+ }
+}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/loader/NEUDelegatingTweaker.java b/src/main/java/io/github/moulberry/notenoughupdates/loader/NEUDelegatingTweaker.java
index 1c2cd285..15f848cb 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/loader/NEUDelegatingTweaker.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/loader/NEUDelegatingTweaker.java
@@ -57,10 +57,11 @@ public class NEUDelegatingTweaker implements ITweaker {
}
private void discoverTweakers() {
+ delegates.add(MixinLoadingTweaker.class.getName());
if (BuildFlags.ENABLE_ONECONFIG_COMPAT_LAYER) {
delegates.add("cc.polyfrost.oneconfig.loader.stage0.LaunchWrapperTweaker");
}
- delegates.add(MixinTweaker.class.getName());
+ delegates.add("org.spongepowered.asm.launch.MixinTweaker");
delegates.add(ModLoadingTweaker.class.getName());
delegates.add(KotlinLoadingTweaker.class.getName());
}
diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml
index 412917d1..c05af117 100644
--- a/src/main/resources/META-INF/mods.toml
+++ b/src/main/resources/META-INF/mods.toml
@@ -1,6 +1,4 @@
# This mods.toml is loaded by forge 1.13-1.19 and is only here to make forge display an error message
-modLoader = "javafml"
-loaderVersion = "[12,)"
license = "LGPL"
[[mods]]