diff options
author | Linnea Gräf <nea@nea.moe> | 2024-03-07 21:55:09 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-03-07 21:55:09 +0100 |
commit | 5c8c3e81a891da36fa752d5f67886bc02ed504dd (patch) | |
tree | 0ada1c40c51a41465703d34c2962cea6d19b78da /src/main/java | |
parent | af5543f73ffcf16cf520b7cf854a18c7e70f4237 (diff) | |
download | NotEnoughUpdates-5c8c3e81a891da36fa752d5f67886bc02ed504dd.tar.gz NotEnoughUpdates-5c8c3e81a891da36fa752d5f67886bc02ed504dd.tar.bz2 NotEnoughUpdates-5c8c3e81a891da36fa752d5f67886bc02ed504dd.zip |
Fix wrong mod loader warning on modern versions of minecraft (#1030)
Diffstat (limited to 'src/main/java')
6 files changed, 255 insertions, 104 deletions
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()); } |