mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-30 04:02:50 +01:00
83767f9544
allows for better runtime class redefinition closes #10459
443 lines
21 KiB
Diff
443 lines
21 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Nassim Jahnke <nassim@njahnke.dev>
|
|
Date: Sun, 30 Oct 2022 23:47:26 +0100
|
|
Subject: [PATCH] Remap reflection calls in plugins using internals
|
|
|
|
Co-authored-by: Jason Penilla <11360596+jpenilla@users.noreply.github.com>
|
|
|
|
diff --git a/build.gradle.kts b/build.gradle.kts
|
|
index 5ffd1d7c130e01a4a7516b361e48bfaf41d4f321..e9498f78cb6c0973a820f093ff7a31bef44ba27f 100644
|
|
--- a/build.gradle.kts
|
|
+++ b/build.gradle.kts
|
|
@@ -47,6 +47,12 @@ dependencies {
|
|
testImplementation("org.junit-pioneer:junit-pioneer:2.2.0") // Paper - CartesianTest
|
|
implementation("net.neoforged:srgutils:1.0.9") // Paper - mappings handling
|
|
implementation("net.neoforged:AutoRenamingTool:2.0.3") // Paper - remap plugins
|
|
+ // Paper start - Remap reflection
|
|
+ val reflectionRewriterVersion = "0.0.1"
|
|
+ implementation("io.papermc:reflection-rewriter:$reflectionRewriterVersion")
|
|
+ implementation("io.papermc:reflection-rewriter-runtime:$reflectionRewriterVersion")
|
|
+ implementation("io.papermc:reflection-rewriter-proxy-generator:$reflectionRewriterVersion")
|
|
+ // Paper end - Remap reflection
|
|
}
|
|
|
|
paperweight {
|
|
diff --git a/src/main/java/io/papermc/paper/configuration/serializer/PacketClassSerializer.java b/src/main/java/io/papermc/paper/configuration/serializer/PacketClassSerializer.java
|
|
index 893ad5e7c2d32ccd64962d95d146bbd317c28ab8..3d73ea0e63c97b2b08e719b7be7af3894fb2d4e8 100644
|
|
--- a/src/main/java/io/papermc/paper/configuration/serializer/PacketClassSerializer.java
|
|
+++ b/src/main/java/io/papermc/paper/configuration/serializer/PacketClassSerializer.java
|
|
@@ -5,6 +5,7 @@ import com.google.common.collect.ImmutableBiMap;
|
|
import com.mojang.logging.LogUtils;
|
|
import io.leangen.geantyref.TypeToken;
|
|
import io.papermc.paper.configuration.serializer.collections.MapSerializer;
|
|
+import io.papermc.paper.util.MappingEnvironment;
|
|
import io.papermc.paper.util.ObfHelper;
|
|
import net.minecraft.network.protocol.Packet;
|
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
|
@@ -69,7 +70,7 @@ public final class PacketClassSerializer extends ScalarSerializer<Class<? extend
|
|
@Override
|
|
protected @Nullable Object serialize(final Class<? extends Packet<?>> packetClass, final Predicate<Class<?>> typeSupported) {
|
|
final String name = packetClass.getName();
|
|
- @Nullable String mojName = ObfHelper.INSTANCE.mappingsByMojangName() == null ? name : MOJANG_TO_OBF.inverse().get(name); // if the mappings are null, running on moj-mapped server
|
|
+ @Nullable String mojName = ObfHelper.INSTANCE.mappingsByMojangName() == null || !MappingEnvironment.reobf() ? name : MOJANG_TO_OBF.inverse().get(name); // if the mappings are null, running on moj-mapped server
|
|
if (mojName == null && MOJANG_TO_OBF.containsKey(name)) {
|
|
mojName = name;
|
|
}
|
|
diff --git a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperClassloaderBytecodeModifier.java b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperClassloaderBytecodeModifier.java
|
|
index f9a2c55a354c877749db3f92956de802ae575788..39182cdd17473da0123dc7172dce507eab29fedc 100644
|
|
--- a/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperClassloaderBytecodeModifier.java
|
|
+++ b/src/main/java/io/papermc/paper/plugin/entrypoint/classloader/PaperClassloaderBytecodeModifier.java
|
|
@@ -1,12 +1,17 @@
|
|
package io.papermc.paper.plugin.entrypoint.classloader;
|
|
|
|
import io.papermc.paper.plugin.configuration.PluginMeta;
|
|
+import org.objectweb.asm.ClassReader;
|
|
+import org.objectweb.asm.ClassWriter;
|
|
|
|
// Stub, implement in future.
|
|
public class PaperClassloaderBytecodeModifier implements ClassloaderBytecodeModifier {
|
|
|
|
@Override
|
|
public byte[] modify(PluginMeta configuration, byte[] bytecode) {
|
|
- return bytecode;
|
|
+ ClassReader classReader = new ClassReader(bytecode);
|
|
+ ClassWriter classWriter = new ClassWriter(classReader, 0);
|
|
+ classReader.accept(io.papermc.paper.pluginremap.reflect.ReflectionRemapper.visitor(classWriter), 0);
|
|
+ return classWriter.toByteArray();
|
|
}
|
|
}
|
|
diff --git a/src/main/java/io/papermc/paper/pluginremap/reflect/PaperReflection.java b/src/main/java/io/papermc/paper/pluginremap/reflect/PaperReflection.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..c653d1f5af8b407cfba715e6027dbb695046892a
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/pluginremap/reflect/PaperReflection.java
|
|
@@ -0,0 +1,212 @@
|
|
+package io.papermc.paper.pluginremap.reflect;
|
|
+
|
|
+import com.mojang.logging.LogUtils;
|
|
+import io.papermc.paper.util.MappingEnvironment;
|
|
+import io.papermc.paper.util.ObfHelper;
|
|
+import io.papermc.reflectionrewriter.runtime.AbstractDefaultRulesReflectionProxy;
|
|
+import io.papermc.reflectionrewriter.runtime.DefineClassReflectionProxy;
|
|
+import java.lang.invoke.MethodHandles;
|
|
+import java.nio.ByteBuffer;
|
|
+import java.security.CodeSource;
|
|
+import java.security.ProtectionDomain;
|
|
+import java.util.Map;
|
|
+import java.util.Objects;
|
|
+import java.util.stream.Collectors;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.checker.nullness.qual.Nullable;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+import org.objectweb.asm.ClassReader;
|
|
+import org.objectweb.asm.ClassWriter;
|
|
+import org.slf4j.Logger;
|
|
+
|
|
+// todo proper inheritance handling
|
|
+@SuppressWarnings("unused")
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public final class PaperReflection extends AbstractDefaultRulesReflectionProxy implements DefineClassReflectionProxy {
|
|
+ // concat to avoid being rewritten by shadow
|
|
+ private static final Logger LOGGER = LogUtils.getLogger();
|
|
+ private static final String CB_PACKAGE_PREFIX = "org.bukkit.".concat("craftbukkit.");
|
|
+ private static final String LEGACY_CB_PACKAGE_PREFIX = "org.bukkit.".concat("craftbukkit.") + MappingEnvironment.LEGACY_CB_VERSION + ".";
|
|
+
|
|
+ private final DefineClassReflectionProxy defineClassProxy;
|
|
+ private final Map<String, ObfHelper.ClassMapping> mappingsByMojangName;
|
|
+ private final Map<String, ObfHelper.ClassMapping> mappingsByObfName;
|
|
+ // Reflection does not care about method return values, so this map removes the return value descriptor from the key
|
|
+ private final Map<String, Map<String, String>> strippedMethodMappings;
|
|
+
|
|
+ PaperReflection() {
|
|
+ this.defineClassProxy = DefineClassReflectionProxy.create(PaperReflection::processClass);
|
|
+ if (!MappingEnvironment.hasMappings()) {
|
|
+ this.mappingsByMojangName = Map.of();
|
|
+ this.mappingsByObfName = Map.of();
|
|
+ this.strippedMethodMappings = Map.of();
|
|
+ return;
|
|
+ }
|
|
+ final ObfHelper obfHelper = ObfHelper.INSTANCE;
|
|
+ this.mappingsByMojangName = Objects.requireNonNull(obfHelper.mappingsByMojangName(), "mappingsByMojangName");
|
|
+ this.mappingsByObfName = Objects.requireNonNull(obfHelper.mappingsByObfName(), "mappingsByObfName");
|
|
+ this.strippedMethodMappings = this.mappingsByMojangName.entrySet().stream().collect(Collectors.toUnmodifiableMap(
|
|
+ Map.Entry::getKey,
|
|
+ entry -> entry.getValue().strippedMethods()
|
|
+ ));
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected String mapClassName(final String name) {
|
|
+ final ObfHelper.@Nullable ClassMapping mapping = this.mappingsByObfName.get(name);
|
|
+ return mapping != null ? mapping.mojangName() : removeCraftBukkitRelocation(name);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected String mapDeclaredMethodName(final Class<?> clazz, final String name, final Class<?>... parameterTypes) {
|
|
+ final @Nullable Map<String, String> mapping = this.strippedMethodMappings.get(clazz.getName());
|
|
+ if (mapping == null) {
|
|
+ return name;
|
|
+ }
|
|
+ return mapping.getOrDefault(strippedMethodKey(name, parameterTypes), name);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected String mapMethodName(final Class<?> clazz, final String name, final Class<?>... parameterTypes) {
|
|
+ final @Nullable String mapped = this.findMappedMethodName(clazz, name, parameterTypes);
|
|
+ return mapped != null ? mapped : name;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected String mapDeclaredFieldName(final Class<?> clazz, final String name) {
|
|
+ final ObfHelper.@Nullable ClassMapping mapping = this.mappingsByMojangName.get(clazz.getName());
|
|
+ if (mapping == null) {
|
|
+ return name;
|
|
+ }
|
|
+ return mapping.fieldsByObf().getOrDefault(name, name);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ protected String mapFieldName(final Class<?> clazz, final String name) {
|
|
+ final @Nullable String mapped = this.findMappedFieldName(clazz, name);
|
|
+ return mapped != null ? mapped : name;
|
|
+ }
|
|
+
|
|
+ private @Nullable String findMappedMethodName(final Class<?> clazz, final String name, final Class<?>... parameterTypes) {
|
|
+ final Map<String, String> map = this.strippedMethodMappings.get(clazz.getName());
|
|
+ @Nullable String mapped = null;
|
|
+ if (map != null) {
|
|
+ mapped = map.get(strippedMethodKey(name, parameterTypes));
|
|
+ if (mapped != null) {
|
|
+ return mapped;
|
|
+ }
|
|
+ }
|
|
+ // JVM checks super before interfaces
|
|
+ final Class<?> superClass = clazz.getSuperclass();
|
|
+ if (superClass != null) {
|
|
+ mapped = this.findMappedMethodName(superClass, name, parameterTypes);
|
|
+ }
|
|
+ if (mapped == null) {
|
|
+ for (final Class<?> i : clazz.getInterfaces()) {
|
|
+ mapped = this.findMappedMethodName(i, name, parameterTypes);
|
|
+ if (mapped != null) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return mapped;
|
|
+ }
|
|
+
|
|
+ private @Nullable String findMappedFieldName(final Class<?> clazz, final String name) {
|
|
+ final ObfHelper.ClassMapping mapping = this.mappingsByMojangName.get(clazz.getName());
|
|
+ @Nullable String mapped = null;
|
|
+ if (mapping != null) {
|
|
+ mapped = mapping.fieldsByObf().get(name);
|
|
+ if (mapped != null) {
|
|
+ return mapped;
|
|
+ }
|
|
+ }
|
|
+ // The JVM checks super before interfaces
|
|
+ final Class<?> superClass = clazz.getSuperclass();
|
|
+ if (superClass != null) {
|
|
+ mapped = this.findMappedFieldName(superClass, name);
|
|
+ }
|
|
+ if (mapped == null) {
|
|
+ for (final Class<?> i : clazz.getInterfaces()) {
|
|
+ mapped = this.findMappedFieldName(i, name);
|
|
+ if (mapped != null) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return mapped;
|
|
+ }
|
|
+
|
|
+ private static String strippedMethodKey(final String methodName, final Class<?>... parameterTypes) {
|
|
+ return methodName + parameterDescriptor(parameterTypes);
|
|
+ }
|
|
+
|
|
+ private static String parameterDescriptor(final Class<?>... parameterTypes) {
|
|
+ final StringBuilder builder = new StringBuilder();
|
|
+ builder.append('(');
|
|
+ for (final Class<?> parameterType : parameterTypes) {
|
|
+ builder.append(parameterType.descriptorString());
|
|
+ }
|
|
+ builder.append(')');
|
|
+ return builder.toString();
|
|
+ }
|
|
+
|
|
+ private static String removeCraftBukkitRelocation(final String name) {
|
|
+ if (MappingEnvironment.hasMappings()) {
|
|
+ // Relocation is applied in reobf, and when mappings are present they handle the relocation
|
|
+ return name;
|
|
+ }
|
|
+ if (name.startsWith(LEGACY_CB_PACKAGE_PREFIX)) {
|
|
+ return CB_PACKAGE_PREFIX + name.substring(LEGACY_CB_PACKAGE_PREFIX.length());
|
|
+ }
|
|
+ return name;
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Class<?> defineClass(final Object loader, final byte[] b, final int off, final int len) throws ClassFormatError {
|
|
+ return this.defineClassProxy.defineClass(loader, b, off, len);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Class<?> defineClass(final Object loader, final String name, final byte[] b, final int off, final int len) throws ClassFormatError {
|
|
+ return this.defineClassProxy.defineClass(loader, name, b, off, len);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Class<?> defineClass(final Object loader, final @Nullable String name, final byte[] b, final int off, final int len, final @Nullable ProtectionDomain protectionDomain) throws ClassFormatError {
|
|
+ return this.defineClassProxy.defineClass(loader, name, b, off, len, protectionDomain);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Class<?> defineClass(final Object loader, final String name, final ByteBuffer b, final ProtectionDomain protectionDomain) throws ClassFormatError {
|
|
+ return this.defineClassProxy.defineClass(loader, name, b, protectionDomain);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Class<?> defineClass(final Object secureLoader, final String name, final byte[] b, final int off, final int len, final CodeSource cs) {
|
|
+ return this.defineClassProxy.defineClass(secureLoader, name, b, off, len, cs);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Class<?> defineClass(final Object secureLoader, final String name, final ByteBuffer b, final CodeSource cs) {
|
|
+ return this.defineClassProxy.defineClass(secureLoader, name, b, cs);
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public Class<?> defineClass(final MethodHandles.Lookup lookup, final byte[] bytes) throws IllegalAccessException {
|
|
+ return this.defineClassProxy.defineClass(lookup, bytes);
|
|
+ }
|
|
+
|
|
+ // todo apply bytecode remap here as well
|
|
+ private static byte[] processClass(final byte[] bytes) {
|
|
+ try {
|
|
+ final ClassReader reader = new ClassReader(bytes);
|
|
+ final ClassWriter writer = new ClassWriter(reader, 0);
|
|
+ reader.accept(ReflectionRemapper.visitor(writer), 0);
|
|
+ return writer.toByteArray();
|
|
+ } catch (final Exception ex) {
|
|
+ LOGGER.warn("Failed to process class bytes", ex);
|
|
+ return bytes;
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/pluginremap/reflect/ReflectionRemapper.java b/src/main/java/io/papermc/paper/pluginremap/reflect/ReflectionRemapper.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..5fa5868e82d1f00498d0c5771369e1718b2df4ee
|
|
--- /dev/null
|
|
+++ b/src/main/java/io/papermc/paper/pluginremap/reflect/ReflectionRemapper.java
|
|
@@ -0,0 +1,54 @@
|
|
+package io.papermc.paper.pluginremap.reflect;
|
|
+
|
|
+import io.papermc.asm.ClassInfoProvider;
|
|
+import io.papermc.asm.RewriteRuleVisitorFactory;
|
|
+import io.papermc.paper.util.MappingEnvironment;
|
|
+import io.papermc.reflectionrewriter.BaseReflectionRules;
|
|
+import io.papermc.reflectionrewriter.DefineClassRule;
|
|
+import io.papermc.reflectionrewriter.proxygenerator.ProxyGenerator;
|
|
+import java.lang.invoke.MethodHandles;
|
|
+import java.lang.reflect.Method;
|
|
+import org.checkerframework.checker.nullness.qual.NonNull;
|
|
+import org.checkerframework.framework.qual.DefaultQualifier;
|
|
+import org.objectweb.asm.ClassVisitor;
|
|
+import org.objectweb.asm.Opcodes;
|
|
+
|
|
+@DefaultQualifier(NonNull.class)
|
|
+public final class ReflectionRemapper {
|
|
+ private static final String PAPER_REFLECTION_HOLDER = "io.papermc.paper.pluginremap.reflect.PaperReflectionHolder";
|
|
+ private static final String PAPER_REFLECTION_HOLDER_DESC = PAPER_REFLECTION_HOLDER.replace('.', '/');
|
|
+ private static final RewriteRuleVisitorFactory VISITOR_FACTORY = RewriteRuleVisitorFactory.create(
|
|
+ Opcodes.ASM9,
|
|
+ chain -> chain.then(new BaseReflectionRules(PAPER_REFLECTION_HOLDER).rules())
|
|
+ .then(DefineClassRule.create(PAPER_REFLECTION_HOLDER_DESC, true)),
|
|
+ ClassInfoProvider.basic()
|
|
+ );
|
|
+
|
|
+ static {
|
|
+ if (!MappingEnvironment.reobf()) {
|
|
+ setupProxy();
|
|
+ }
|
|
+ }
|
|
+
|
|
+ private ReflectionRemapper() {
|
|
+ }
|
|
+
|
|
+ public static ClassVisitor visitor(final ClassVisitor parent) {
|
|
+ if (MappingEnvironment.reobf()) {
|
|
+ return parent;
|
|
+ }
|
|
+ return VISITOR_FACTORY.createVisitor(parent);
|
|
+ }
|
|
+
|
|
+ private static void setupProxy() {
|
|
+ try {
|
|
+ final byte[] bytes = ProxyGenerator.generateProxy(PaperReflection.class, PAPER_REFLECTION_HOLDER_DESC);
|
|
+ final MethodHandles.Lookup lookup = MethodHandles.lookup();
|
|
+ final Class<?> generated = lookup.defineClass(bytes);
|
|
+ final Method init = generated.getDeclaredMethod("init", PaperReflection.class);
|
|
+ init.invoke(null, new PaperReflection());
|
|
+ } catch (final ReflectiveOperationException ex) {
|
|
+ throw new RuntimeException(ex);
|
|
+ }
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/io/papermc/paper/util/MappingEnvironment.java b/src/main/java/io/papermc/paper/util/MappingEnvironment.java
|
|
index 8e4229634d41a42b3d93948eebb77def7c0c72b1..38745299ea49f253a410e77557100903ecb472b0 100644
|
|
--- a/src/main/java/io/papermc/paper/util/MappingEnvironment.java
|
|
+++ b/src/main/java/io/papermc/paper/util/MappingEnvironment.java
|
|
@@ -10,6 +10,7 @@ import org.checkerframework.framework.qual.DefaultQualifier;
|
|
|
|
@DefaultQualifier(NonNull.class)
|
|
public final class MappingEnvironment {
|
|
+ public static final String LEGACY_CB_VERSION = "v1_20_R4";
|
|
private static final @Nullable String MAPPINGS_HASH = readMappingsHash();
|
|
private static final boolean REOBF = checkReobf();
|
|
|
|
diff --git a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
|
index 242811578a786e3807a1a7019d472d5a68f87116..0b65fdf53124f3dd042b2363b1b8df8e1ca7de00 100644
|
|
--- a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
|
+++ b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java
|
|
@@ -29,6 +29,9 @@ public enum StacktraceDeobfuscator {
|
|
});
|
|
|
|
public void deobfuscateThrowable(final Throwable throwable) {
|
|
+ if (!MappingEnvironment.reobf()) {
|
|
+ return;
|
|
+ }
|
|
if (GlobalConfiguration.get() != null && !GlobalConfiguration.get().logging.deobfuscateStacktraces) { // handle null as true
|
|
return;
|
|
}
|
|
@@ -44,6 +47,9 @@ public enum StacktraceDeobfuscator {
|
|
}
|
|
|
|
public StackTraceElement[] deobfuscateStacktrace(final StackTraceElement[] traceElements) {
|
|
+ if (!MappingEnvironment.reobf()) {
|
|
+ return traceElements;
|
|
+ }
|
|
if (GlobalConfiguration.get() != null && !GlobalConfiguration.get().logging.deobfuscateStacktraces) { // handle null as true
|
|
return traceElements;
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
|
index 8420a53672cfb0f060d9c85c445d200b6701f521..fc04bfcb8b5dfa6d093c8d75b2f20c502ef94a63 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/util/Commodore.java
|
|
@@ -76,36 +76,26 @@ public class Commodore {
|
|
private static final Map<String, RerouteMethodData> FIELD_RENAME_METHOD_REROUTE = Commodore.createReroutes(FieldRename.class);
|
|
|
|
// Paper start - Plugin rewrites
|
|
- private static final Map<String, String> SEARCH_AND_REMOVE = initReplacementsMap();
|
|
- private static Map<String, String> initReplacementsMap() {
|
|
- Map<String, String> getAndRemove = new HashMap<>();
|
|
- // Be wary of maven shade's relocations
|
|
-
|
|
- final java.util.jar.Manifest manifest = io.papermc.paper.util.JarManifests.manifest(Commodore.class);
|
|
- if (Boolean.getBoolean( "debug.rewriteForIde") && manifest != null)
|
|
- {
|
|
- // unversion incoming calls for pre-relocate debug work
|
|
- final String NMS_REVISION_PACKAGE = "v" + manifest.getMainAttributes().getValue("CraftBukkit-Package-Version") + "/";
|
|
-
|
|
- getAndRemove.put("org/bukkit/".concat("craftbukkit/" + NMS_REVISION_PACKAGE), NMS_REVISION_PACKAGE);
|
|
+ private static final String CB_PACKAGE_PREFIX = "org/bukkit/".concat("craftbukkit/");
|
|
+ private static final String LEGACY_CB_PACKAGE_PREFIX = CB_PACKAGE_PREFIX + io.papermc.paper.util.MappingEnvironment.LEGACY_CB_VERSION + "/";
|
|
+ private static String runtimeCbPkgPrefix() {
|
|
+ if (io.papermc.paper.util.MappingEnvironment.reobf()) {
|
|
+ return LEGACY_CB_PACKAGE_PREFIX;
|
|
}
|
|
-
|
|
- return getAndRemove;
|
|
+ return CB_PACKAGE_PREFIX;
|
|
}
|
|
|
|
@Nonnull
|
|
private static String getOriginalOrRewrite(@Nonnull String original)
|
|
{
|
|
- String rewrite = null;
|
|
- for ( Map.Entry<String, String> entry : SEARCH_AND_REMOVE.entrySet() )
|
|
- {
|
|
- if ( original.contains( entry.getKey() ) )
|
|
- {
|
|
- rewrite = original.replace( entry.getValue(), "" );
|
|
+ // Relocation is applied in reobf, and when mappings are present they handle the relocation
|
|
+ if (!io.papermc.paper.util.MappingEnvironment.reobf() && !io.papermc.paper.util.MappingEnvironment.hasMappings()) {
|
|
+ if (original.contains(LEGACY_CB_PACKAGE_PREFIX)) {
|
|
+ original = original.replace(LEGACY_CB_PACKAGE_PREFIX, CB_PACKAGE_PREFIX);
|
|
}
|
|
}
|
|
|
|
- return rewrite != null ? rewrite : original;
|
|
+ return original;
|
|
}
|
|
// Paper end - Plugin rewrites
|
|
|
|
@@ -176,7 +166,7 @@ public class Commodore {
|
|
ClassReader cr = new ClassReader(b);
|
|
ClassWriter cw = new ClassWriter(cr, 0);
|
|
|
|
- cr.accept(new ClassRemapper(new ClassVisitor(Opcodes.ASM9, cw) {
|
|
+ cr.accept(new ClassRemapper(new ClassVisitor(Opcodes.ASM9, io.papermc.paper.pluginremap.reflect.ReflectionRemapper.visitor(cw)) { // Paper
|
|
final Set<RerouteMethodData> rerouteMethodData = new HashSet<>();
|
|
String className;
|
|
boolean isInterface;
|