1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
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<Path> 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<IMappingFile> 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<Path> remapLibraries(final List<Path> libraries) {
+ final List<CompletableFuture<Path>> 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<Path> remapPlugin(
+ final RemappedPluginIndex index,
+ final Path inputFile
+ ) {
+ return this.remap(index, inputFile, false);
+ }
+
+ private CompletableFuture<Path> 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<Path> remapPlugin(final RemappedPluginIndex index, final Path inputFile) {
+ private CompletableFuture<Path> 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);
}
|