diff --git a/patches/server/0001-Setup-Gradle-project.patch b/patches/server/0001-Setup-Gradle-project.patch index b5c120a1df..d3e3f1ad9d 100644 --- a/patches/server/0001-Setup-Gradle-project.patch +++ b/patches/server/0001-Setup-Gradle-project.patch @@ -28,7 +28,7 @@ index 37dab9e868dbfb019c271a547d975a48ad1cb571..3811c0d849a3eb028ed1a6b7a2d4747f +/.factorypath diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 -index 0000000000000000000000000000000000000000..b3055953028759e4754d507c31f387b6bf7c0108 +index 0000000000000000000000000000000000000000..a41b15de7eba00d62822f582015d324ccde7dfe7 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,119 @@ @@ -135,9 +135,9 @@ index 0000000000000000000000000000000000000000..b3055953028759e4754d507c31f387b6 + runtime.filterNot { it.asFile.absolutePath == vanilla } + } + -+tasks.registerRunTask("runShadow") { -+ description = "Spin up a test server from the shadowJar archiveFile" -+ classpath(tasks.shadowJar.flatMap { it.archiveFile }) ++tasks.registerRunTask("runServerJar") { ++ description = "Spin up a test server from the serverJar archiveFile" ++ classpath(tasks.serverJar.flatMap { it.archiveFile }) + classpath(runtimeClasspathWithoutVanillaServer) +} + diff --git a/patches/server/0003-Build-system-changes.patch b/patches/server/0003-Build-system-changes.patch index 52428906e4..f7608aaf06 100644 --- a/patches/server/0003-Build-system-changes.patch +++ b/patches/server/0003-Build-system-changes.patch @@ -9,7 +9,7 @@ public net.minecraft.server.packs.VanillaPackResourcesBuilder safeGetPath(Ljava/ Co-authored-by: Jake Potrebic diff --git a/build.gradle.kts b/build.gradle.kts -index b3055953028759e4754d507c31f387b6bf7c0108..39e4021d3fa7e79bd28463a01e3e6d07181f6765 100644 +index a41b15de7eba00d62822f582015d324ccde7dfe7..4d38e90fddc74fb0b0d1be23990d35e60ccd9544 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,9 +8,7 @@ plugins { diff --git a/patches/server/0004-Test-changes.patch b/patches/server/0004-Test-changes.patch index da0eca4b4b..b504fb1161 100644 --- a/patches/server/0004-Test-changes.patch +++ b/patches/server/0004-Test-changes.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Test changes diff --git a/build.gradle.kts b/build.gradle.kts -index 39e4021d3fa7e79bd28463a01e3e6d07181f6765..83598b48724e3a4f40a153be3e681564105b90b4 100644 +index 4d38e90fddc74fb0b0d1be23990d35e60ccd9544..583f2c236d98d2c8348787eadc813d1218e25336 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -22,6 +22,7 @@ dependencies { diff --git a/patches/server/0005-Paper-config-files.patch b/patches/server/0005-Paper-config-files.patch index 3e158b1a0c..69e6aa4696 100644 --- a/patches/server/0005-Paper-config-files.patch +++ b/patches/server/0005-Paper-config-files.patch @@ -15,7 +15,7 @@ public net.minecraft.server.dedicated.DedicatedServerProperties reload(Lnet/mine public net.minecraft.world.level.NaturalSpawner SPAWNING_CATEGORIES diff --git a/build.gradle.kts b/build.gradle.kts -index 83598b48724e3a4f40a153be3e681564105b90b4..94fcbfae0678391d38ee8e6e54576d9fb294585e 100644 +index 583f2c236d98d2c8348787eadc813d1218e25336..2a7db88148b708754d5f33ed5266ecefcad9d27c 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,6 +10,7 @@ dependencies { diff --git a/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch b/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch index 3692466a0c..b40a930712 100644 --- a/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch +++ b/patches/server/0011-Use-TerminalConsoleAppender-for-console-improvements.patch @@ -25,7 +25,7 @@ Other changes: Co-Authored-By: Emilia Kond diff --git a/build.gradle.kts b/build.gradle.kts -index 94fcbfae0678391d38ee8e6e54576d9fb294585e..05ea33821177d5a4917cd3cb69be85fefb9452a7 100644 +index 2a7db88148b708754d5f33ed5266ecefcad9d27c..0aed38d217707a916f2a42ede9525b88560b6c8b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,9 +5,29 @@ plugins { diff --git a/patches/server/0012-Handle-plugin-prefixes-using-Log4J-configuration.patch b/patches/server/0012-Handle-plugin-prefixes-using-Log4J-configuration.patch index e3a8285a0e..32b5c0e06d 100644 --- a/patches/server/0012-Handle-plugin-prefixes-using-Log4J-configuration.patch +++ b/patches/server/0012-Handle-plugin-prefixes-using-Log4J-configuration.patch @@ -15,7 +15,7 @@ This may cause additional prefixes to be disabled for plugins bypassing the plugin logger. diff --git a/build.gradle.kts b/build.gradle.kts -index 05ea33821177d5a4917cd3cb69be85fefb9452a7..859ef5811880e988640230374f180fb2d197a26e 100644 +index 0aed38d217707a916f2a42ede9525b88560b6c8b..4260860c3dc0335b570899ab461c17f0ade00ed6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -23,7 +23,7 @@ dependencies { diff --git a/patches/server/0014-Use-AsyncAppender-to-keep-logging-IO-off-main-thread.patch b/patches/server/0014-Use-AsyncAppender-to-keep-logging-IO-off-main-thread.patch index 920a040798..3f7d87c091 100644 --- a/patches/server/0014-Use-AsyncAppender-to-keep-logging-IO-off-main-thread.patch +++ b/patches/server/0014-Use-AsyncAppender-to-keep-logging-IO-off-main-thread.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Use AsyncAppender to keep logging IO off main thread diff --git a/build.gradle.kts b/build.gradle.kts -index 859ef5811880e988640230374f180fb2d197a26e..2412647683b78f811537bf527d2c70bd3ec7ad21 100644 +index 4260860c3dc0335b570899ab461c17f0ade00ed6..d3005f310a256c000a62314832d5e90eecfefbf6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,8 +32,7 @@ dependencies { diff --git a/patches/server/0015-Deobfuscate-stacktraces-in-log-messages-crash-report.patch b/patches/server/0015-Deobfuscate-stacktraces-in-log-messages-crash-report.patch index c9901448e0..77aa4f4e51 100644 --- a/patches/server/0015-Deobfuscate-stacktraces-in-log-messages-crash-report.patch +++ b/patches/server/0015-Deobfuscate-stacktraces-in-log-messages-crash-report.patch @@ -6,17 +6,17 @@ Subject: [PATCH] Deobfuscate stacktraces in log messages, crash reports, and diff --git a/build.gradle.kts b/build.gradle.kts -index 2412647683b78f811537bf527d2c70bd3ec7ad21..dbb67a5dc1eecb1339cd4da1a23e69ed675ddbe4 100644 +index d3005f310a256c000a62314832d5e90eecfefbf6..3587ff0a4c0fe92c99501aa5251f379481e43437 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -32,6 +32,7 @@ dependencies { - implementation("org.ow2.asm:asm-commons:9.7") - implementation("org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT") // Paper - config files - implementation("commons-lang:commons-lang:2.6") -+ implementation("net.fabricmc:mapping-io:0.5.0") // Paper - needed to read mappings for stacktrace deobfuscation - runtimeOnly("com.lmax:disruptor:3.4.4") // Paper +@@ -43,6 +43,7 @@ dependencies { + testImplementation("org.mockito:mockito-core:5.11.0") + testImplementation("org.ow2.asm:asm-tree:9.7") + testImplementation("org.junit-pioneer:junit-pioneer:2.2.0") // Paper - CartesianTest ++ implementation("net.neoforged:srgutils:1.0.9") // Paper - mappings handling + } - runtimeOnly("org.apache.maven:maven-resolver-provider:3.9.6") + val craftbukkitPackageVersion = "1_20_R4" // Paper diff --git a/src/log4jPlugins/java/io/papermc/paper/logging/StacktraceDeobfuscatingRewritePolicy.java b/src/log4jPlugins/java/io/papermc/paper/logging/StacktraceDeobfuscatingRewritePolicy.java new file mode 100644 index 0000000000000000000000000000000000000000..66b6011ee3684695b2ab9292961c80bf2a420ee9 @@ -91,27 +91,21 @@ index 0000000000000000000000000000000000000000..66b6011ee3684695b2ab9292961c80bf +} diff --git a/src/main/java/io/papermc/paper/util/ObfHelper.java b/src/main/java/io/papermc/paper/util/ObfHelper.java new file mode 100644 -index 0000000000000000000000000000000000000000..e8ff684d8bd994c64ff34f20e1e0601b678244c1 +index 0000000000000000000000000000000000000000..9e6d48335b37fa5204bfebf396d748089884555b --- /dev/null +++ b/src/main/java/io/papermc/paper/util/ObfHelper.java -@@ -0,0 +1,147 @@ +@@ -0,0 +1,156 @@ +package io.papermc.paper.util; + +import java.io.IOException; +import java.io.InputStream; -+import java.io.InputStreamReader; -+import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Objects; +import java.util.Set; -+import java.util.function.Function; +import java.util.stream.Collectors; -+import net.fabricmc.mappingio.MappingReader; -+import net.fabricmc.mappingio.format.MappingFormat; -+import net.fabricmc.mappingio.tree.MappingTree; -+import net.fabricmc.mappingio.tree.MemoryMappingTree; ++import net.neoforged.srgutils.IMappingFile; +import org.checkerframework.checker.nullness.qual.NonNull; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.checkerframework.framework.qual.DefaultQualifier; @@ -120,9 +114,6 @@ index 0000000000000000000000000000000000000000..e8ff684d8bd994c64ff34f20e1e0601b +public enum ObfHelper { + INSTANCE; + -+ public static final String MOJANG_PLUS_YARN_NAMESPACE = "mojang+yarn"; -+ public static final String SPIGOT_NAMESPACE = "spigot"; -+ + private final @Nullable Map mappingsByObfName; + private final @Nullable Map mappingsByMojangName; + @@ -190,73 +181,90 @@ index 0000000000000000000000000000000000000000..e8ff684d8bd994c64ff34f20e1e0601b + if (mappingsInputStream == null) { + return null; + } -+ final MemoryMappingTree tree = new MemoryMappingTree(); -+ MappingReader.read(new InputStreamReader(mappingsInputStream, StandardCharsets.UTF_8), MappingFormat.TINY_2_FILE, tree); ++ final IMappingFile mappings = IMappingFile.load(mappingsInputStream); // Mappings are mojang->spigot + final Set classes = new HashSet<>(); + + final StringPool pool = new StringPool(); -+ for (final MappingTree.ClassMapping cls : tree.getClasses()) { ++ for (final IMappingFile.IClass cls : mappings.getClasses()) { + final Map methods = new HashMap<>(); ++ final Map fields = new HashMap<>(); ++ final Map strippedMethods = new HashMap<>(); + -+ for (final MappingTree.MethodMapping methodMapping : cls.getMethods()) { ++ for (final IMappingFile.IMethod methodMapping : cls.getMethods()) { + methods.put( -+ pool.string(methodKey( -+ Objects.requireNonNull(methodMapping.getName(SPIGOT_NAMESPACE)), -+ Objects.requireNonNull(methodMapping.getDesc(SPIGOT_NAMESPACE)) -+ )), -+ pool.string(Objects.requireNonNull(methodMapping.getName(MOJANG_PLUS_YARN_NAMESPACE))) ++ pool.string(methodKey( ++ Objects.requireNonNull(methodMapping.getMapped()), ++ Objects.requireNonNull(methodMapping.getMappedDescriptor()) ++ )), ++ pool.string(Objects.requireNonNull(methodMapping.getOriginal())) ++ ); ++ ++ strippedMethods.put( ++ pool.string(pool.string(strippedMethodKey( ++ methodMapping.getMapped(), ++ methodMapping.getDescriptor() ++ ))), ++ pool.string(methodMapping.getOriginal()) ++ ); ++ } ++ for (final IMappingFile.IField field : cls.getFields()) { ++ fields.put( ++ pool.string(field.getMapped()), ++ pool.string(field.getOriginal()) + ); + } + + final ClassMapping map = new ClassMapping( -+ Objects.requireNonNull(cls.getName(SPIGOT_NAMESPACE)).replace('/', '.'), -+ Objects.requireNonNull(cls.getName(MOJANG_PLUS_YARN_NAMESPACE)).replace('/', '.'), -+ Map.copyOf(methods) ++ Objects.requireNonNull(cls.getMapped()).replace('/', '.'), ++ Objects.requireNonNull(cls.getOriginal()).replace('/', '.'), ++ Map.copyOf(methods), ++ Map.copyOf(fields), ++ Map.copyOf(strippedMethods) + ); + classes.add(map); + } + + return Set.copyOf(classes); + } catch (final IOException ex) { -+ System.err.println("Failed to load mappings for stacktrace deobfuscation."); ++ System.err.println("Failed to load mappings."); + ex.printStackTrace(); + return null; + } + } + -+ public static String methodKey(final String obfName, final String obfDescriptor) { -+ return obfName + obfDescriptor; ++ public static String strippedMethodKey(final String methodName, final String methodDescriptor) { ++ final String methodKey = methodKey(methodName, methodDescriptor); ++ final int returnDescriptorEnd = methodKey.indexOf(')'); ++ return methodKey.substring(0, returnDescriptorEnd + 1); + } + -+ private static final class StringPool { -+ private final Map pool = new HashMap<>(); -+ -+ public String string(final String string) { -+ return this.pool.computeIfAbsent(string, Function.identity()); -+ } ++ public static String methodKey(final String methodName, final String methodDescriptor) { ++ return methodName + methodDescriptor; + } + + public record ClassMapping( -+ String obfName, -+ String mojangName, -+ Map methodsByObf ++ String obfName, ++ String mojangName, ++ Map methodsByObf, ++ Map fieldsByObf, ++ // obf name with mapped desc to mapped name. return value is excluded from desc as reflection doesn't use it ++ Map strippedMethods + ) {} +} diff --git a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java new file mode 100644 -index 0000000000000000000000000000000000000000..eb910d4abf91488fa7cf1f5d47e0ee916c47f512 +index 0000000000000000000000000000000000000000..242811578a786e3807a1a7019d472d5a68f87116 --- /dev/null +++ b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java -@@ -0,0 +1,163 @@ +@@ -0,0 +1,144 @@ +package io.papermc.paper.util; + +import io.papermc.paper.configuration.GlobalConfiguration; -+import it.unimi.dsi.fastutil.ints.IntArrayList; -+import it.unimi.dsi.fastutil.ints.IntList; ++import it.unimi.dsi.fastutil.ints.Int2ObjectMap; ++import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import java.io.IOException; +import java.io.InputStream; +import java.util.Collections; -+import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import org.checkerframework.checker.nullness.qual.NonNull; @@ -272,9 +280,9 @@ index 0000000000000000000000000000000000000000..eb910d4abf91488fa7cf1f5d47e0ee91 +public enum StacktraceDeobfuscator { + INSTANCE; + -+ private final Map, Map> lineMapCache = Collections.synchronizedMap(new LinkedHashMap<>(128, 0.75f, true) { ++ private final Map, Int2ObjectMap> lineMapCache = Collections.synchronizedMap(new LinkedHashMap<>(128, 0.75f, true) { + @Override -+ protected boolean removeEldestEntry(final Map.Entry, Map> eldest) { ++ protected boolean removeEldestEntry(final Map.Entry, Int2ObjectMap> eldest) { + return this.size() > 127; + } + }); @@ -339,18 +347,7 @@ index 0000000000000000000000000000000000000000..eb910d4abf91488fa7cf1f5d47e0ee91 + } + + private @Nullable String determineMethodForLine(final Class clazz, final int lineNumber) { -+ final Map lineMap = this.lineMapCache.computeIfAbsent(clazz, StacktraceDeobfuscator::buildLineMap); -+ for (final var entry : lineMap.entrySet()) { -+ final String methodKey = entry.getKey(); -+ final IntList lines = entry.getValue(); -+ for (int i = 0, linesSize = lines.size(); i < linesSize; i++) { -+ final int num = lines.getInt(i); -+ if (num == lineNumber) { -+ return methodKey; -+ } -+ } -+ } -+ return null; ++ return this.lineMapCache.computeIfAbsent(clazz, StacktraceDeobfuscator::buildLineMap).get(lineNumber); + } + + private static String sourceFileName(final String fullClassName) { @@ -362,34 +359,27 @@ index 0000000000000000000000000000000000000000..eb910d4abf91488fa7cf1f5d47e0ee91 + return rootClassName + ".java"; + } + -+ private static Map buildLineMap(final Class key) { -+ final Map lineMap = new HashMap<>(); ++ private static Int2ObjectMap buildLineMap(final Class key) { ++ final StringPool pool = new StringPool(); ++ final Int2ObjectMap lineMap = new Int2ObjectOpenHashMap<>(); + final class LineCollectingMethodVisitor extends MethodVisitor { -+ private final IntList lines = new IntArrayList(); + private final String name; + private final String descriptor; + -+ LineCollectingMethodVisitor(String name, String descriptor) { ++ LineCollectingMethodVisitor(final String name, final String descriptor) { + super(Opcodes.ASM9); + this.name = name; + this.descriptor = descriptor; + } + + @Override -+ public void visitLineNumber(int line, Label start) { -+ super.visitLineNumber(line, start); -+ this.lines.add(line); -+ } -+ -+ @Override -+ public void visitEnd() { -+ super.visitEnd(); -+ lineMap.put(ObfHelper.methodKey(this.name, this.descriptor), this.lines); ++ public void visitLineNumber(final int line, final Label start) { ++ lineMap.put(line, pool.string(ObfHelper.methodKey(this.name, this.descriptor))); + } + } + final ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM9) { + @Override -+ public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { ++ public MethodVisitor visitMethod(final int access, final String name, final String descriptor, final String signature, final String[] exceptions) { + return new LineCollectingMethodVisitor(name, descriptor); + } + }; @@ -411,6 +401,46 @@ index 0000000000000000000000000000000000000000..eb910d4abf91488fa7cf1f5d47e0ee91 + return lineMap; + } +} +diff --git a/src/main/java/io/papermc/paper/util/StringPool.java b/src/main/java/io/papermc/paper/util/StringPool.java +new file mode 100644 +index 0000000000000000000000000000000000000000..c0a486cb46ff30353c3ff09567891cd36238eeb4 +--- /dev/null ++++ b/src/main/java/io/papermc/paper/util/StringPool.java +@@ -0,0 +1,34 @@ ++package io.papermc.paper.util; ++ ++import java.util.HashMap; ++import java.util.Map; ++import java.util.function.Function; ++import org.checkerframework.checker.nullness.qual.NonNull; ++import org.checkerframework.framework.qual.DefaultQualifier; ++ ++/** ++ * De-duplicates {@link String} instances without using {@link String#intern()}. ++ * ++ *

Interning may not be desired as we may want to use the heap for our pool, ++ * so it can be garbage collected as normal, etc.

++ * ++ *

Additionally, interning can be slow due to the potentially large size of the ++ * pool (as it is shared for the entire JVM), and because most JVMs implement ++ * it using JNI.

++ */ ++@DefaultQualifier(NonNull.class) ++public final class StringPool { ++ private final Map pool; ++ ++ public StringPool() { ++ this(new HashMap<>()); ++ } ++ ++ public StringPool(final Map map) { ++ this.pool = map; ++ } ++ ++ public String string(final String string) { ++ return this.pool.computeIfAbsent(string, Function.identity()); ++ } ++} diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java index a23407fa1b906743890cff74f5051ad55d59c85e..06c514b2d0674cd7df6692981f020437ea0f2f91 100644 --- a/src/main/java/net/minecraft/CrashReport.java diff --git a/patches/server/0020-Plugin-remapping.patch b/patches/server/0020-Plugin-remapping.patch index 62d0316083..4f89a129ef 100644 --- a/patches/server/0020-Plugin-remapping.patch +++ b/patches/server/0020-Plugin-remapping.patch @@ -6,15 +6,14 @@ Subject: [PATCH] Plugin remapping Co-authored-by: Nassim Jahnke diff --git a/build.gradle.kts b/build.gradle.kts -index dbb67a5dc1eecb1339cd4da1a23e69ed675ddbe4..c29c309503d5d5defe7991baca34b0d692d57e36 100644 +index 3587ff0a4c0fe92c99501aa5251f379481e43437..600b442986fa5ca9dd12f900caa284b854cc30ca 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -44,9 +44,14 @@ dependencies { - testImplementation("org.mockito:mockito-core:5.11.0") +@@ -44,9 +44,13 @@ dependencies { testImplementation("org.ow2.asm:asm-tree:9.7") 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 -+ implementation("net.neoforged:srgutils:1.0.9") // Paper - remap plugins - bump transitive of ART +} + +paperweight { @@ -25,7 +24,7 @@ index dbb67a5dc1eecb1339cd4da1a23e69ed675ddbe4..c29c309503d5d5defe7991baca34b0d6 tasks.jar { archiveClassifier.set("dev") -@@ -66,7 +71,7 @@ tasks.jar { +@@ -66,7 +70,7 @@ tasks.jar { "Specification-Vendor" to "Bukkit Team", "Git-Branch" to gitBranch, // Paper "Git-Commit" to gitHash, // Paper @@ -34,13 +33,13 @@ index dbb67a5dc1eecb1339cd4da1a23e69ed675ddbe4..c29c309503d5d5defe7991baca34b0d6 ) for (tld in setOf("net", "com", "org")) { attributes("$tld/bukkit", "Sealed" to true) -@@ -155,20 +160,41 @@ val runtimeClasspathWithoutVanillaServer = configurations.runtimeClasspath.flatM +@@ -155,20 +159,41 @@ val runtimeClasspathWithoutVanillaServer = configurations.runtimeClasspath.flatM runtime.filterNot { it.asFile.absolutePath == vanilla } } --tasks.registerRunTask("runShadow") { -- description = "Spin up a test server from the shadowJar archiveFile" -- classpath(tasks.shadowJar.flatMap { it.archiveFile }) +-tasks.registerRunTask("runServerJar") { +- description = "Spin up a test server from the serverJar archiveFile" +- classpath(tasks.serverJar.flatMap { it.archiveFile }) +tasks.registerRunTask("runServer") { + description = "Spin up a test server from the Mojang mapped server jar" + classpath(tasks.includeMappings.flatMap { it.outputJar }) @@ -1362,10 +1361,10 @@ index 0000000000000000000000000000000000000000..8e4229634d41a42b3d93948eebb77def + } +} diff --git a/src/main/java/io/papermc/paper/util/ObfHelper.java b/src/main/java/io/papermc/paper/util/ObfHelper.java -index e8ff684d8bd994c64ff34f20e1e0601b678244c1..3f03d5efcd95e3adb76dc4292b3d2c420fdc58af 100644 +index 9e6d48335b37fa5204bfebf396d748089884555b..6067be951c4c52c4b1da51efc01436b2c90ea3bf 100644 --- a/src/main/java/io/papermc/paper/util/ObfHelper.java +++ b/src/main/java/io/papermc/paper/util/ObfHelper.java -@@ -89,10 +89,10 @@ public enum ObfHelper { +@@ -80,10 +80,10 @@ public enum ObfHelper { } private static @Nullable Set loadMappingsIfPresent() { @@ -1377,9 +1376,9 @@ index e8ff684d8bd994c64ff34f20e1e0601b678244c1..3f03d5efcd95e3adb76dc4292b3d2c42 + return null; + } + try (final InputStream mappingsInputStream = MappingEnvironment.mappingsStream()) { - final MemoryMappingTree tree = new MemoryMappingTree(); - MappingReader.read(new InputStreamReader(mappingsInputStream, StandardCharsets.UTF_8), MappingFormat.TINY_2_FILE, tree); + final IMappingFile mappings = IMappingFile.load(mappingsInputStream); // Mappings are mojang->spigot final Set classes = new HashSet<>(); + diff --git a/src/main/java/io/papermc/paper/util/concurrent/ScalingThreadPool.java b/src/main/java/io/papermc/paper/util/concurrent/ScalingThreadPool.java new file mode 100644 index 0000000000000000000000000000000000000000..badff5d6ae6dd8d209c82bc7e8afe370db6148f2 diff --git a/patches/server/0022-Remap-reflection-calls-in-plugins-using-internals.patch b/patches/server/0022-Remap-reflection-calls-in-plugins-using-internals.patch index 348061d5a7..817d23fa98 100644 --- a/patches/server/0022-Remap-reflection-calls-in-plugins-using-internals.patch +++ b/patches/server/0022-Remap-reflection-calls-in-plugins-using-internals.patch @@ -6,21 +6,13 @@ 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 c29c309503d5d5defe7991baca34b0d692d57e36..1caa3ef9f0fd71f2bea2e1ea36bb2fa34c6ee689 100644 +index 600b442986fa5ca9dd12f900caa284b854cc30ca..caf738482232039e6e28376daa37b2a3a7465c69 100644 --- a/build.gradle.kts +++ b/build.gradle.kts -@@ -32,7 +32,6 @@ dependencies { - implementation("org.ow2.asm:asm-commons:9.7") - implementation("org.spongepowered:configurate-yaml:4.2.0-SNAPSHOT") // Paper - config files - implementation("commons-lang:commons-lang:2.6") -- implementation("net.fabricmc:mapping-io:0.5.0") // Paper - needed to read mappings for stacktrace deobfuscation - runtimeOnly("com.lmax:disruptor:3.4.4") // Paper - - runtimeOnly("org.apache.maven:maven-resolver-provider:3.9.6") -@@ -46,6 +45,12 @@ dependencies { +@@ -45,6 +45,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 - implementation("net.neoforged:srgutils:1.0.9") // Paper - remap plugins - bump transitive of ART + // Paper start - Remap reflection + val reflectionRewriterVersion = "0.0.1" + implementation("io.papermc:reflection-rewriter:$reflectionRewriterVersion") @@ -364,165 +356,11 @@ index 8e4229634d41a42b3d93948eebb77def7c0c72b1..38745299ea49f253a410e77557100903 private static final @Nullable String MAPPINGS_HASH = readMappingsHash(); private static final boolean REOBF = checkReobf(); -diff --git a/src/main/java/io/papermc/paper/util/ObfHelper.java b/src/main/java/io/papermc/paper/util/ObfHelper.java -index 3f03d5efcd95e3adb76dc4292b3d2c420fdc58af..9eecb96cb7ec6d6a157ed2c5637e05138c3f55b9 100644 ---- a/src/main/java/io/papermc/paper/util/ObfHelper.java -+++ b/src/main/java/io/papermc/paper/util/ObfHelper.java -@@ -2,19 +2,13 @@ package io.papermc.paper.util; - - import java.io.IOException; - import java.io.InputStream; --import java.io.InputStreamReader; --import java.nio.charset.StandardCharsets; - import java.util.HashMap; - import java.util.HashSet; - import java.util.Map; - import java.util.Objects; - import java.util.Set; --import java.util.function.Function; - import java.util.stream.Collectors; --import net.fabricmc.mappingio.MappingReader; --import net.fabricmc.mappingio.format.MappingFormat; --import net.fabricmc.mappingio.tree.MappingTree; --import net.fabricmc.mappingio.tree.MemoryMappingTree; -+import net.neoforged.srgutils.IMappingFile; - import org.checkerframework.checker.nullness.qual.NonNull; - import org.checkerframework.checker.nullness.qual.Nullable; - import org.checkerframework.framework.qual.DefaultQualifier; -@@ -23,9 +17,6 @@ import org.checkerframework.framework.qual.DefaultQualifier; - public enum ObfHelper { - INSTANCE; - -- public static final String MOJANG_PLUS_YARN_NAMESPACE = "mojang+yarn"; -- public static final String SPIGOT_NAMESPACE = "spigot"; -- - private final @Nullable Map mappingsByObfName; - private final @Nullable Map mappingsByMojangName; - -@@ -93,55 +84,73 @@ public enum ObfHelper { - return null; - } - try (final InputStream mappingsInputStream = MappingEnvironment.mappingsStream()) { -- final MemoryMappingTree tree = new MemoryMappingTree(); -- MappingReader.read(new InputStreamReader(mappingsInputStream, StandardCharsets.UTF_8), MappingFormat.TINY_2_FILE, tree); -+ final IMappingFile mappings = IMappingFile.load(mappingsInputStream); // Mappings are mojang->spigot - final Set classes = new HashSet<>(); - - final StringPool pool = new StringPool(); -- for (final MappingTree.ClassMapping cls : tree.getClasses()) { -+ for (final IMappingFile.IClass cls : mappings.getClasses()) { - final Map methods = new HashMap<>(); -+ final Map fields = new HashMap<>(); -+ final Map strippedMethods = new HashMap<>(); - -- for (final MappingTree.MethodMapping methodMapping : cls.getMethods()) { -+ for (final IMappingFile.IMethod methodMapping : cls.getMethods()) { - methods.put( - pool.string(methodKey( -- Objects.requireNonNull(methodMapping.getName(SPIGOT_NAMESPACE)), -- Objects.requireNonNull(methodMapping.getDesc(SPIGOT_NAMESPACE)) -+ Objects.requireNonNull(methodMapping.getMapped()), -+ Objects.requireNonNull(methodMapping.getMappedDescriptor()) - )), -- pool.string(Objects.requireNonNull(methodMapping.getName(MOJANG_PLUS_YARN_NAMESPACE))) -+ pool.string(Objects.requireNonNull(methodMapping.getOriginal())) -+ ); -+ -+ strippedMethods.put( -+ pool.string(pool.string(strippedMethodKey( -+ methodMapping.getMapped(), -+ methodMapping.getDescriptor() -+ ))), -+ pool.string(methodMapping.getOriginal()) -+ ); -+ } -+ for (final IMappingFile.IField field : cls.getFields()) { -+ fields.put( -+ pool.string(field.getMapped()), -+ pool.string(field.getOriginal()) - ); - } - - final ClassMapping map = new ClassMapping( -- Objects.requireNonNull(cls.getName(SPIGOT_NAMESPACE)).replace('/', '.'), -- Objects.requireNonNull(cls.getName(MOJANG_PLUS_YARN_NAMESPACE)).replace('/', '.'), -- Map.copyOf(methods) -+ Objects.requireNonNull(cls.getMapped()).replace('/', '.'), -+ Objects.requireNonNull(cls.getOriginal()).replace('/', '.'), -+ Map.copyOf(methods), -+ Map.copyOf(fields), -+ Map.copyOf(strippedMethods) - ); - classes.add(map); - } - - return Set.copyOf(classes); - } catch (final IOException ex) { -- System.err.println("Failed to load mappings for stacktrace deobfuscation."); -+ System.err.println("Failed to load mappings."); - ex.printStackTrace(); - return null; - } - } - -- public static String methodKey(final String obfName, final String obfDescriptor) { -- return obfName + obfDescriptor; -+ public static String strippedMethodKey(final String methodName, final String methodDescriptor) { -+ final String methodKey = methodKey(methodName, methodDescriptor); -+ final int returnDescriptorEnd = methodKey.indexOf(')'); -+ return methodKey.substring(0, returnDescriptorEnd + 1); - } - -- private static final class StringPool { -- private final Map pool = new HashMap<>(); -- -- public String string(final String string) { -- return this.pool.computeIfAbsent(string, Function.identity()); -- } -+ public static String methodKey(final String methodName, final String methodDescriptor) { -+ return methodName + methodDescriptor; - } - - public record ClassMapping( - String obfName, - String mojangName, -- Map methodsByObf -+ Map methodsByObf, -+ Map fieldsByObf, -+ // obf name with mapped desc to mapped name. return value is excluded from desc as reflection doesn't use it -+ Map strippedMethods - ) {} - } diff --git a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java -index eb910d4abf91488fa7cf1f5d47e0ee916c47f512..0b65fdf53124f3dd042b2363b1b8df8e1ca7de00 100644 +index 242811578a786e3807a1a7019d472d5a68f87116..0b65fdf53124f3dd042b2363b1b8df8e1ca7de00 100644 --- a/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java +++ b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java -@@ -1,12 +1,11 @@ - package io.papermc.paper.util; - - import io.papermc.paper.configuration.GlobalConfiguration; --import it.unimi.dsi.fastutil.ints.IntArrayList; --import it.unimi.dsi.fastutil.ints.IntList; -+import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; - import java.io.IOException; - import java.io.InputStream; - import java.util.Collections; --import java.util.HashMap; - import java.util.LinkedHashMap; - import java.util.Map; - import org.checkerframework.checker.nullness.qual.NonNull; -@@ -22,14 +21,17 @@ import org.objectweb.asm.Opcodes; - public enum StacktraceDeobfuscator { - INSTANCE; - -- private final Map, Map> lineMapCache = Collections.synchronizedMap(new LinkedHashMap<>(128, 0.75f, true) { -+ private final Map, Int2ObjectMap> lineMapCache = Collections.synchronizedMap(new LinkedHashMap<>(128, 0.75f, true) { - @Override -- protected boolean removeEldestEntry(final Map.Entry, Map> eldest) { -+ protected boolean removeEldestEntry(final Map.Entry, Int2ObjectMap> eldest) { - return this.size() > 127; - } +@@ -29,6 +29,9 @@ public enum StacktraceDeobfuscator { }); public void deobfuscateThrowable(final Throwable throwable) { @@ -532,7 +370,7 @@ index eb910d4abf91488fa7cf1f5d47e0ee916c47f512..0b65fdf53124f3dd042b2363b1b8df8e if (GlobalConfiguration.get() != null && !GlobalConfiguration.get().logging.deobfuscateStacktraces) { // handle null as true return; } -@@ -45,6 +47,9 @@ public enum StacktraceDeobfuscator { +@@ -44,6 +47,9 @@ public enum StacktraceDeobfuscator { } public StackTraceElement[] deobfuscateStacktrace(final StackTraceElement[] traceElements) { @@ -542,108 +380,6 @@ index eb910d4abf91488fa7cf1f5d47e0ee916c47f512..0b65fdf53124f3dd042b2363b1b8df8e if (GlobalConfiguration.get() != null && !GlobalConfiguration.get().logging.deobfuscateStacktraces) { // handle null as true return traceElements; } -@@ -89,18 +94,7 @@ public enum StacktraceDeobfuscator { - } - - private @Nullable String determineMethodForLine(final Class clazz, final int lineNumber) { -- final Map lineMap = this.lineMapCache.computeIfAbsent(clazz, StacktraceDeobfuscator::buildLineMap); -- for (final var entry : lineMap.entrySet()) { -- final String methodKey = entry.getKey(); -- final IntList lines = entry.getValue(); -- for (int i = 0, linesSize = lines.size(); i < linesSize; i++) { -- final int num = lines.getInt(i); -- if (num == lineNumber) { -- return methodKey; -- } -- } -- } -- return null; -+ return this.lineMapCache.computeIfAbsent(clazz, StacktraceDeobfuscator::buildLineMap).get(lineNumber); - } - - private static String sourceFileName(final String fullClassName) { -@@ -112,34 +106,27 @@ public enum StacktraceDeobfuscator { - return rootClassName + ".java"; - } - -- private static Map buildLineMap(final Class key) { -- final Map lineMap = new HashMap<>(); -+ private static Int2ObjectMap buildLineMap(final Class key) { -+ final StringPool pool = new StringPool(); -+ final Int2ObjectMap lineMap = new Int2ObjectOpenHashMap<>(); - final class LineCollectingMethodVisitor extends MethodVisitor { -- private final IntList lines = new IntArrayList(); - private final String name; - private final String descriptor; - -- LineCollectingMethodVisitor(String name, String descriptor) { -+ LineCollectingMethodVisitor(final String name, final String descriptor) { - super(Opcodes.ASM9); - this.name = name; - this.descriptor = descriptor; - } - - @Override -- public void visitLineNumber(int line, Label start) { -- super.visitLineNumber(line, start); -- this.lines.add(line); -- } -- -- @Override -- public void visitEnd() { -- super.visitEnd(); -- lineMap.put(ObfHelper.methodKey(this.name, this.descriptor), this.lines); -+ public void visitLineNumber(final int line, final Label start) { -+ lineMap.put(line, pool.string(ObfHelper.methodKey(this.name, this.descriptor))); - } - } - final ClassVisitor classVisitor = new ClassVisitor(Opcodes.ASM9) { - @Override -- public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { -+ public MethodVisitor visitMethod(final int access, final String name, final String descriptor, final String signature, final String[] exceptions) { - return new LineCollectingMethodVisitor(name, descriptor); - } - }; -diff --git a/src/main/java/io/papermc/paper/util/StringPool.java b/src/main/java/io/papermc/paper/util/StringPool.java -new file mode 100644 -index 0000000000000000000000000000000000000000..c0a486cb46ff30353c3ff09567891cd36238eeb4 ---- /dev/null -+++ b/src/main/java/io/papermc/paper/util/StringPool.java -@@ -0,0 +1,34 @@ -+package io.papermc.paper.util; -+ -+import java.util.HashMap; -+import java.util.Map; -+import java.util.function.Function; -+import org.checkerframework.checker.nullness.qual.NonNull; -+import org.checkerframework.framework.qual.DefaultQualifier; -+ -+/** -+ * De-duplicates {@link String} instances without using {@link String#intern()}. -+ * -+ *

Interning may not be desired as we may want to use the heap for our pool, -+ * so it can be garbage collected as normal, etc.

-+ * -+ *

Additionally, interning can be slow due to the potentially large size of the -+ * pool (as it is shared for the entire JVM), and because most JVMs implement -+ * it using JNI.

-+ */ -+@DefaultQualifier(NonNull.class) -+public final class StringPool { -+ private final Map pool; -+ -+ public StringPool() { -+ this(new HashMap<>()); -+ } -+ -+ public StringPool(final Map map) { -+ this.pool = map; -+ } -+ -+ public String string(final String string) { -+ return this.pool.computeIfAbsent(string, Function.identity()); -+ } -+} diff --git a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java b/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java index 457a963ee6ebd3cf5c3831f6660e3850335af49f..61744d8fde3ba98585cf261fc09f0acc042b67b8 100644 --- a/src/main/java/net/minecraft/world/level/redstone/CollectingNeighborUpdater.java diff --git a/patches/server/0283-Brigadier-Mojang-API.patch b/patches/server/0283-Brigadier-Mojang-API.patch index 80e75802b7..ce03b4e287 100644 --- a/patches/server/0283-Brigadier-Mojang-API.patch +++ b/patches/server/0283-Brigadier-Mojang-API.patch @@ -10,7 +10,7 @@ Adds CommandRegisteredEvent - Allows manipulating the CommandNode to add more children/metadata for the client diff --git a/build.gradle.kts b/build.gradle.kts -index 1caa3ef9f0fd71f2bea2e1ea36bb2fa34c6ee689..b1b7d9b72c9f79fe2cfcde47be35a7e73b35d6ff 100644 +index caf738482232039e6e28376daa37b2a3a7465c69..8e667150eb288c4e2cbc8e9d97de040f38abdfb1 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -13,6 +13,7 @@ val alsoShade: Configuration by configurations.creating diff --git a/patches/server/0363-Implement-Mob-Goal-API.patch b/patches/server/0363-Implement-Mob-Goal-API.patch index 50b5ac2812..f618eaf066 100644 --- a/patches/server/0363-Implement-Mob-Goal-API.patch +++ b/patches/server/0363-Implement-Mob-Goal-API.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Implement Mob Goal API diff --git a/build.gradle.kts b/build.gradle.kts -index b1b7d9b72c9f79fe2cfcde47be35a7e73b35d6ff..81b42b378f2d44ce1ffba5ee3f50aad3c13e60fa 100644 +index 8e667150eb288c4e2cbc8e9d97de040f38abdfb1..e4caad0371110c90b7c65cd6dccc53d549c98aca 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -39,6 +39,7 @@ dependencies { diff --git a/patches/server/0723-Add-support-for-Proxy-Protocol.patch b/patches/server/0723-Add-support-for-Proxy-Protocol.patch index 8a97a4d29d..d1b1e9e5fc 100644 --- a/patches/server/0723-Add-support-for-Proxy-Protocol.patch +++ b/patches/server/0723-Add-support-for-Proxy-Protocol.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Add support for Proxy Protocol diff --git a/build.gradle.kts b/build.gradle.kts -index 81b42b378f2d44ce1ffba5ee3f50aad3c13e60fa..4216f5b1d5fa5769b6c2b24204e2146c4511cc8b 100644 +index e4caad0371110c90b7c65cd6dccc53d549c98aca..97d7857828007f5f164c76a33a68d7d2f4250dce 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -28,6 +28,7 @@ dependencies { diff --git a/patches/server/1012-Use-Velocity-compression-and-cipher-natives.patch b/patches/server/1012-Use-Velocity-compression-and-cipher-natives.patch index bf3cd56769..0c8f9cc197 100644 --- a/patches/server/1012-Use-Velocity-compression-and-cipher-natives.patch +++ b/patches/server/1012-Use-Velocity-compression-and-cipher-natives.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Use Velocity compression and cipher natives diff --git a/build.gradle.kts b/build.gradle.kts -index 4216f5b1d5fa5769b6c2b24204e2146c4511cc8b..3b0cb2a4e200fb31b8789b2d99f033758b4f7145 100644 +index 97d7857828007f5f164c76a33a68d7d2f4250dce..2143aa04db50ec04448af338170d67369a5ca023 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -35,6 +35,11 @@ dependencies {