From 17e7874fcec92eefa4fd17bb4da6292db01ebec1 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Sun, 28 Apr 2024 13:57:26 -0700 Subject: [PATCH] Remap plugin libraries with namespace set to spigot --- .../0474-Add-hook-to-remap-library-jars.patch | 38 ++++ ...braries-with-namespace-set-to-spigot.patch | 210 ++++++++++++++++++ 2 files changed, 248 insertions(+) create mode 100644 patches/api/0474-Add-hook-to-remap-library-jars.patch create mode 100644 patches/server/1047-Remap-plugin-libraries-with-namespace-set-to-spigot.patch diff --git a/patches/api/0474-Add-hook-to-remap-library-jars.patch b/patches/api/0474-Add-hook-to-remap-library-jars.patch new file mode 100644 index 0000000000..fe1609629e --- /dev/null +++ b/patches/api/0474-Add-hook-to-remap-library-jars.patch @@ -0,0 +1,38 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Sun, 28 Apr 2024 13:51:08 -0700 +Subject: [PATCH] Add hook to remap library jars + + +diff --git a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +index 5b0203e908f84c531886b8ea8faeb591eb045636..8e1b6be2462aaa692efa1f72986921a6dc357196 100644 +--- a/src/main/java/org/bukkit/plugin/java/LibraryLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +@@ -47,6 +47,7 @@ public class LibraryLoader + private final DefaultRepositorySystemSession session; + private final List repositories; + public static java.util.function.BiFunction LIBRARY_LOADER_FACTORY; // Paper - rewrite reflection in libraries ++ public static java.util.function.Function, List> REMAPPER; // Paper - remap libraries + + public LibraryLoader(@NotNull Logger logger) + { +@@ -111,9 +112,18 @@ public class LibraryLoader + } + + List jarFiles = new ArrayList<>(); ++ List jarPaths = new ArrayList<>(); // Paper - remap libraries + for ( ArtifactResult artifact : result.getArtifactResults() ) + { +- File file = artifact.getArtifact().getFile(); ++ // Paper start - remap libraries ++ jarPaths.add(artifact.getArtifact().getFile().toPath()); ++ } ++ if (REMAPPER != null) { ++ jarPaths = REMAPPER.apply(jarPaths); ++ } ++ for (java.nio.file.Path path : jarPaths) { ++ File file = path.toFile(); ++ // Paper end - remap libraries + + URL url; + try diff --git a/patches/server/1047-Remap-plugin-libraries-with-namespace-set-to-spigot.patch b/patches/server/1047-Remap-plugin-libraries-with-namespace-set-to-spigot.patch new file mode 100644 index 0000000000..03df91b0f9 --- /dev/null +++ b/patches/server/1047-Remap-plugin-libraries-with-namespace-set-to-spigot.patch @@ -0,0 +1,210 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> +Date: Sun, 28 Apr 2024 13:54:18 -0700 +Subject: [PATCH] Remap plugin libraries with namespace set to spigot + + +diff --git a/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java b/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java +index bb1cfa8ea8b11fc36ea72c8e382b8554bccd0ce5..6f14cb9a73faa1d0ae2939d08809d9f6c2a99e1d 100644 +--- a/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java ++++ b/src/main/java/io/papermc/paper/plugin/PluginInitializerManager.java +@@ -7,9 +7,11 @@ import io.papermc.paper.plugin.entrypoint.LaunchEntryPointHandler; + import io.papermc.paper.plugin.provider.PluginProvider; + import io.papermc.paper.plugin.provider.type.paper.PaperPluginParent; + import io.papermc.paper.pluginremap.PluginRemapper; ++import java.util.function.Function; + import joptsimple.OptionSet; + import net.minecraft.server.dedicated.DedicatedServer; + import org.bukkit.configuration.file.YamlConfiguration; ++import org.bukkit.plugin.java.LibraryLoader; + import org.jetbrains.annotations.NotNull; + import org.jetbrains.annotations.Nullable; + import org.slf4j.Logger; +@@ -33,6 +35,7 @@ public class PluginInitializerManager { + this.pluginRemapper = Boolean.getBoolean("paper.disable-plugin-rewriting") + ? null + : PluginRemapper.create(pluginDirectory); ++ LibraryLoader.REMAPPER = this.pluginRemapper == null ? Function.identity() : this.pluginRemapper::remapLibraries; + } + + private static PluginInitializerManager parse(@NotNull final OptionSet minecraftOptionSet) throws Exception { +diff --git a/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java +index ca6cb891e9da9d7e08f1a82fab212d2063cc9ef6..82032370e7896b621e37ee3726016440e177619f 100644 +--- a/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java ++++ b/src/main/java/io/papermc/paper/plugin/loader/PaperClasspathBuilder.java +@@ -1,5 +1,6 @@ + package io.papermc.paper.plugin.loader; + ++import io.papermc.paper.plugin.PluginInitializerManager; + import io.papermc.paper.plugin.bootstrap.PluginProviderContext; + import io.papermc.paper.plugin.entrypoint.classloader.BytecodeModifyingURLClassLoader; + import io.papermc.paper.plugin.entrypoint.classloader.PaperPluginClassLoader; +@@ -45,9 +46,12 @@ public class PaperClasspathBuilder implements PluginClasspathBuilder { + } + + List paths = paperLibraryStore.getPaths(); ++ if (PluginInitializerManager.instance().pluginRemapper != null) { ++ paths = PluginInitializerManager.instance().pluginRemapper.remapLibraries(paths); ++ } + URL[] urls = new URL[paths.size()]; + for (int i = 0; i < paths.size(); i++) { +- Path path = paperLibraryStore.getPaths().get(i); ++ Path path = paths.get(i); + try { + urls[i] = path.toUri().toURL(); + } catch (MalformedURLException e) { +diff --git a/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java b/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java +index 6f1e4ae352dcc6aacd9703b1653701f93974d1bd..a1ce1307b2834f2415bdddbf42d80e2d69a480e1 100644 +--- a/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java ++++ b/src/main/java/io/papermc/paper/pluginremap/PluginRemapper.java +@@ -44,6 +44,7 @@ public final class PluginRemapper { + public static final boolean DEBUG_LOGGING = Boolean.getBoolean("Paper.PluginRemapperDebug"); + private static final String PAPER_REMAPPED = ".paper-remapped"; + private static final String UNKNOWN_ORIGIN = "unknown-origin"; ++ private static final String LIBRARIES = "libraries"; + private static final String EXTRA_PLUGINS = "extra-plugins"; + private static final String REMAP_CLASSPATH = "remap-classpath"; + private static final String REVERSED_MAPPINGS = "mappings/reversed"; +@@ -54,6 +55,7 @@ public final class PluginRemapper { + private final RemappedPluginIndex remappedPlugins; + private final RemappedPluginIndex extraPlugins; + private final UnknownOriginRemappedPluginIndex unknownOrigin; ++ private final UnknownOriginRemappedPluginIndex libraries; + private @Nullable CompletableFuture reversedMappings; + + public PluginRemapper(final Path pluginsDir) { +@@ -65,6 +67,7 @@ public final class PluginRemapper { + this.remappedPlugins = new RemappedPluginIndex(remappedPlugins, false); + this.extraPlugins = new RemappedPluginIndex(this.remappedPlugins.dir().resolve(EXTRA_PLUGINS), true); + this.unknownOrigin = new UnknownOriginRemappedPluginIndex(this.remappedPlugins.dir().resolve(UNKNOWN_ORIGIN)); ++ this.libraries = new UnknownOriginRemappedPluginIndex(this.remappedPlugins.dir().resolve(LIBRARIES)); + } + + public static @Nullable PluginRemapper create(final Path pluginsDir) { +@@ -93,6 +96,7 @@ public final class PluginRemapper { + this.remappedPlugins.write(); + this.extraPlugins.write(); + this.unknownOrigin.write(clean); ++ this.libraries.write(clean); + } + + // Called on startup and reload +@@ -112,6 +116,29 @@ public final class PluginRemapper { + this.save(false); + } + ++ public List remapLibraries(final List libraries) { ++ final List> tasks = new ArrayList<>(); ++ for (final Path lib : libraries) { ++ if (!lib.getFileName().toString().endsWith(".jar")) { ++ if (DEBUG_LOGGING) { ++ LOGGER.info("Library '{}' is not a jar.", libraries); ++ } ++ tasks.add(CompletableFuture.completedFuture(lib)); ++ continue; ++ } ++ final @Nullable Path cached = this.libraries.getIfPresent(lib); ++ if (cached != null) { ++ if (DEBUG_LOGGING) { ++ LOGGER.info("Library '{}' has not changed since last remap.", libraries); ++ } ++ tasks.add(CompletableFuture.completedFuture(cached)); ++ continue; ++ } ++ tasks.add(this.remapLibrary(this.libraries, lib)); ++ } ++ return waitForAll(tasks); ++ } ++ + public Path rewritePlugin(final Path plugin) { + // Already remapped + if (plugin.getParent().equals(this.remappedPlugins.dir()) +@@ -232,6 +259,20 @@ public final class PluginRemapper { + }, executor).thenCompose(f -> f); + } + ++ private CompletableFuture remapPlugin( ++ final RemappedPluginIndex index, ++ final Path inputFile ++ ) { ++ return this.remap(index, inputFile, false); ++ } ++ ++ private CompletableFuture remapLibrary( ++ final RemappedPluginIndex index, ++ final Path inputFile ++ ) { ++ return this.remap(index, inputFile, true); ++ } ++ + /** + * Returns the remapped file if remapping was necessary, otherwise null. + * +@@ -239,7 +280,11 @@ public final class PluginRemapper { + * @param inputFile input file + * @return remapped file, or inputFile if no remapping was necessary + */ +- private CompletableFuture remapPlugin(final RemappedPluginIndex index, final Path inputFile) { ++ private CompletableFuture remap( ++ final RemappedPluginIndex index, ++ final Path inputFile, ++ final boolean library ++ ) { + final Path destination = index.input(inputFile); + + try (final FileSystem fs = FileSystems.newFileSystem(inputFile, new HashMap<>())) { +@@ -255,18 +300,35 @@ public final class PluginRemapper { + } else { + ns = null; + } +- if (ns != null && (ns.equals(InsertManifestAttribute.MOJANG_NAMESPACE) || ns.equals(InsertManifestAttribute.MOJANG_PLUS_YARN_NAMESPACE))) { +- if (DEBUG_LOGGING) { +- LOGGER.info("Plugin '{}' is already Mojang mapped.", inputFile); ++ final boolean mojangMappedManifest = ns != null && (ns.equals(InsertManifestAttribute.MOJANG_NAMESPACE) || ns.equals(InsertManifestAttribute.MOJANG_PLUS_YARN_NAMESPACE)); ++ if (library) { ++ if (mojangMappedManifest) { ++ if (DEBUG_LOGGING) { ++ LOGGER.info("Library '{}' is already Mojang mapped.", inputFile); ++ } ++ index.skip(inputFile); ++ return CompletableFuture.completedFuture(inputFile); ++ } else if (ns == null) { ++ if (DEBUG_LOGGING) { ++ LOGGER.info("Library '{}' does not specify a mappings namespace (not remapping).", inputFile); ++ } ++ index.skip(inputFile); ++ return CompletableFuture.completedFuture(inputFile); + } +- index.skip(inputFile); +- return CompletableFuture.completedFuture(inputFile); +- } else if (ns == null && Files.exists(fs.getPath(PluginFileType.PAPER_PLUGIN_YML))) { +- if (DEBUG_LOGGING) { +- LOGGER.info("Plugin '{}' is a Paper plugin with no namespace specified.", inputFile); ++ } else { ++ if (mojangMappedManifest) { ++ if (DEBUG_LOGGING) { ++ LOGGER.info("Plugin '{}' is already Mojang mapped.", inputFile); ++ } ++ index.skip(inputFile); ++ return CompletableFuture.completedFuture(inputFile); ++ } else if (ns == null && Files.exists(fs.getPath(PluginFileType.PAPER_PLUGIN_YML))) { ++ if (DEBUG_LOGGING) { ++ LOGGER.info("Plugin '{}' is a Paper plugin with no namespace specified.", inputFile); ++ } ++ index.skip(inputFile); ++ return CompletableFuture.completedFuture(inputFile); + } +- index.skip(inputFile); +- return CompletableFuture.completedFuture(inputFile); + } + } catch (final IOException ex) { + throw new RuntimeException("Failed to open plugin jar " + inputFile, ex); +@@ -290,7 +352,7 @@ public final class PluginRemapper { + } catch (final Exception ex) { + throw new RuntimeException("Failed to remap plugin jar '" + inputFile + "'", ex); + } +- LOGGER.info("Done remapping plugin '{}' in {}ms.", inputFile, System.currentTimeMillis() - start); ++ LOGGER.info("Done remapping {} '{}' in {}ms.", library ? "library" : "plugin", inputFile, System.currentTimeMillis() - start); + return destination; + }, this.threadPool); + }