diff --git a/patches/server/0713-Deobfuscate-stacktraces-in-log-messages-crash-report.patch b/patches/server/0713-Deobfuscate-stacktraces-in-log-messages-crash-report.patch index c0082f7672..211026b90e 100644 --- a/patches/server/0713-Deobfuscate-stacktraces-in-log-messages-crash-report.patch +++ b/patches/server/0713-Deobfuscate-stacktraces-in-log-messages-crash-report.patch @@ -159,20 +159,22 @@ index 0000000000000000000000000000000000000000..d019802a36dbaca4bf299a55d28381e4 +} 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..271e0a2ec549836a32565bb9100d432cd68d6046 +index 0000000000000000000000000000000000000000..e9082fa4e04c88fe53429af77b1c23a03aeafc2d --- /dev/null +++ b/src/main/java/io/papermc/paper/util/ObfHelper.java -@@ -0,0 +1,87 @@ +@@ -0,0 +1,141 @@ +package io.papermc.paper.util; + +import com.google.common.base.Charsets; +import com.google.common.collect.ImmutableMap; ++import com.google.common.collect.ImmutableSet; +import com.mojang.datafixers.util.Pair; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.Map; ++import java.util.Set; +import net.fabricmc.mapping.tree.ClassDef; +import net.fabricmc.mapping.tree.MethodDef; +import net.fabricmc.mapping.tree.TinyMappingFactory; @@ -188,23 +190,75 @@ index 0000000000000000000000000000000000000000..271e0a2ec549836a32565bb9100d432c + public static final String MOJANG_PLUS_YARN_NAMESPACE = "mojang+yarn"; + public static final String SPIGOT_NAMESPACE = "spigot"; + -+ private final @Nullable Map mappings; ++ private final @Nullable Map mappingsByObfName; ++ private final @Nullable Map mappingsByMojangName; + + ObfHelper() { -+ this.mappings = loadMappingsIfPresent(); ++ final @Nullable Set maps = loadMappingsIfPresent(); ++ if (maps != null) { ++ this.mappingsByObfName = maps.stream().collect(ImmutableMap.toImmutableMap(ClassMapping::obfName, map -> map)); ++ this.mappingsByMojangName = maps.stream().collect(ImmutableMap.toImmutableMap(ClassMapping::mojangName, map -> map)); ++ } else { ++ this.mappingsByObfName = null; ++ this.mappingsByMojangName = null; ++ } + } + -+ public @Nullable Map mappings() { -+ return this.mappings; ++ public @Nullable Map mappingsByObfName() { ++ return this.mappingsByObfName; + } + -+ private static @Nullable Map loadMappingsIfPresent() { ++ public @Nullable Map mappingsByMojangName() { ++ return this.mappingsByMojangName; ++ } ++ ++ /** ++ * Attempts to get the obf name for a given class by its Mojang name. Will ++ * return the input string if mappings are not present. ++ * ++ * @param fullyQualifiedMojangName fully qualified class name (dotted) ++ * @return mapped or original fully qualified (dotted) class name ++ */ ++ public String reobfClassName(final String fullyQualifiedMojangName) { ++ if (this.mappingsByMojangName == null) { ++ return fullyQualifiedMojangName; ++ } ++ ++ final ClassMapping map = this.mappingsByMojangName.get(fullyQualifiedMojangName); ++ if (map == null) { ++ return fullyQualifiedMojangName; ++ } ++ ++ return map.obfName(); ++ } ++ ++ /** ++ * Attempts to get the Mojang name for a given class by its obf name. Will ++ * return the input string if mappings are not present. ++ * ++ * @param fullyQualifiedObfName fully qualified class name (dotted) ++ * @return mapped or original fully qualified (dotted) class name ++ */ ++ public String deobfClassName(final String fullyQualifiedObfName) { ++ if (this.mappingsByObfName == null) { ++ return fullyQualifiedObfName; ++ } ++ ++ final ClassMapping map = this.mappingsByObfName.get(fullyQualifiedObfName); ++ if (map == null) { ++ return fullyQualifiedObfName; ++ } ++ ++ return map.mojangName(); ++ } ++ ++ private static @Nullable Set loadMappingsIfPresent() { + try (final @Nullable InputStream mappingsInputStream = StacktraceDeobfuscator.class.getClassLoader().getResourceAsStream("META-INF/mappings/reobf.tiny")) { + if (mappingsInputStream == null) { + return null; + } + final TinyTree tree = TinyMappingFactory.loadWithDetection(new BufferedReader(new InputStreamReader(mappingsInputStream, Charsets.UTF_8))); -+ final var builder = ImmutableMap.builder(); ++ final var builder = ImmutableSet.builder(); + + for (final ClassDef classDef : tree.getClasses()) { + final String obfClassName = classDef.getName(SPIGOT_NAMESPACE).replace('/', '.'); @@ -227,7 +281,7 @@ index 0000000000000000000000000000000000000000..271e0a2ec549836a32565bb9100d432c + classDef.getName(MOJANG_PLUS_YARN_NAMESPACE).replace('/', '.'), + methodMappings.build() + ); -+ builder.put(map.obfName(), map); ++ builder.add(map); + } + + return builder.build(); @@ -252,7 +306,7 @@ index 0000000000000000000000000000000000000000..271e0a2ec549836a32565bb9100d432c +} 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..6ef365dfd3caa0a726983fc57125f4d9a86959fc +index 0000000000000000000000000000000000000000..f3099d3cfa4ea8ad56b1abdd0e7b77aaa4465244 --- /dev/null +++ b/src/main/java/io/papermc/paper/util/StacktraceDeobfuscator.java @@ -0,0 +1,156 @@ @@ -307,7 +361,7 @@ index 0000000000000000000000000000000000000000..6ef365dfd3caa0a726983fc57125f4d9 + return traceElements; + } + -+ final @Nullable Map mappings = ObfHelper.INSTANCE.mappings(); ++ final @Nullable Map mappings = ObfHelper.INSTANCE.mappingsByObfName(); + if (mappings == null || traceElements.length == 0) { + return traceElements; + } diff --git a/patches/server/0727-Rate-options-and-timings-for-sensors-and-behaviors.patch b/patches/server/0727-Rate-options-and-timings-for-sensors-and-behaviors.patch index 0eedbe3f9f..12708e0626 100644 --- a/patches/server/0727-Rate-options-and-timings-for-sensors-and-behaviors.patch +++ b/patches/server/0727-Rate-options-and-timings-for-sensors-and-behaviors.patch @@ -111,7 +111,7 @@ index 0e7d29dbbdb862dd5876adee26fbba02267e5276..c334f29c69c1e6e3fe55cd6695e7df40 } diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java -index b1212e162ba938b3abe0df747a633ba9cbbe57c8..b1928807851a4fca53e117573b25c62a6deeb8e1 100644 +index b1212e162ba938b3abe0df747a633ba9cbbe57c8..c24ff2ef1054523e58892c2b35080cffb6ab744a 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java +++ b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java @@ -14,6 +14,10 @@ public abstract class Behavior { @@ -125,22 +125,15 @@ index b1212e162ba938b3abe0df747a633ba9cbbe57c8..b1928807851a4fca53e117573b25c62a public Behavior(Map, MemoryStatus> requiredMemoryState) { this(requiredMemoryState, 60); -@@ -27,6 +31,22 @@ public abstract class Behavior { +@@ -27,6 +31,15 @@ public abstract class Behavior { this.minDuration = minRunTime; this.maxDuration = maxRunTime; this.entryCondition = requiredMemoryState; + // Paper start - configurable behavior tick rate and timings -+ String key = this.getClass().getSimpleName(); -+ final var mappings = io.papermc.paper.util.ObfHelper.INSTANCE.mappings(); -+ if (mappings != null) { -+ final var classMapping = mappings.get(this.getClass().getName()); -+ if (classMapping != null) { -+ key = classMapping.mojangName(); -+ int lastSeparator = key.lastIndexOf('.'); -+ if (lastSeparator != -1) { -+ key = key.substring(lastSeparator + 1); -+ } -+ } ++ String key = io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(this.getClass().getName()); ++ int lastSeparator = key.lastIndexOf('.'); ++ if (lastSeparator != -1) { ++ key = key.substring(lastSeparator + 1); + } + this.configKey = key.toLowerCase(java.util.Locale.ROOT); + this.timing = co.aikar.timings.MinecraftTimings.getBehaviorTimings(configKey); @@ -148,7 +141,7 @@ index b1212e162ba938b3abe0df747a633ba9cbbe57c8..b1928807851a4fca53e117573b25c62a } public Behavior.Status getStatus() { -@@ -34,11 +54,19 @@ public abstract class Behavior { +@@ -34,11 +47,19 @@ public abstract class Behavior { } public final boolean tryStart(ServerLevel world, E entity, long time) { @@ -168,7 +161,7 @@ index b1212e162ba938b3abe0df747a633ba9cbbe57c8..b1928807851a4fca53e117573b25c62a return true; } else { return false; -@@ -49,11 +77,13 @@ public abstract class Behavior { +@@ -49,11 +70,13 @@ public abstract class Behavior { } public final void tickOrStop(ServerLevel world, E entity, long time) { @@ -183,10 +176,10 @@ index b1212e162ba938b3abe0df747a633ba9cbbe57c8..b1928807851a4fca53e117573b25c62a } diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java -index f94aa5147c52d2e36d6018f51b85e9dac7a6208a..8f99a78a55ab8f0ddfa1dd790a9a4a8c23a7f841 100644 +index f94aa5147c52d2e36d6018f51b85e9dac7a6208a..87f804e35e2f124f5ee73d9d9a4fd4b3069b00d0 100644 --- a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java +++ b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java -@@ -19,8 +19,28 @@ public abstract class Sensor { +@@ -19,8 +19,21 @@ public abstract class Sensor { private static final TargetingConditions ATTACK_TARGET_CONDITIONS_IGNORE_INVISIBILITY_AND_LINE_OF_SIGHT = TargetingConditions.forCombat().range(16.0D).ignoreLineOfSight().ignoreInvisibilityTesting(); private final int scanRate; private long timeToTick; @@ -197,17 +190,10 @@ index f94aa5147c52d2e36d6018f51b85e9dac7a6208a..8f99a78a55ab8f0ddfa1dd790a9a4a8c public Sensor(int senseInterval) { + // Paper start - configurable sensor tick rate and timings -+ String key = this.getClass().getSimpleName(); -+ final var mappings = io.papermc.paper.util.ObfHelper.INSTANCE.mappings(); -+ if (mappings != null) { -+ final var classMapping = mappings.get(this.getClass().getName()); -+ if (classMapping != null) { -+ key = classMapping.mojangName(); -+ int lastSeparator = key.lastIndexOf('.'); -+ if (lastSeparator != -1) { -+ key = key.substring(lastSeparator + 1); -+ } -+ } ++ String key = io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(this.getClass().getName()); ++ int lastSeparator = key.lastIndexOf('.'); ++ if (lastSeparator != -1) { ++ key = key.substring(lastSeparator + 1); + } + this.configKey = key.toLowerCase(java.util.Locale.ROOT); + this.timing = co.aikar.timings.MinecraftTimings.getSensorTimings(configKey, senseInterval); @@ -215,7 +201,7 @@ index f94aa5147c52d2e36d6018f51b85e9dac7a6208a..8f99a78a55ab8f0ddfa1dd790a9a4a8c this.scanRate = senseInterval; this.timeToTick = (long)RANDOM.nextInt(senseInterval); } -@@ -31,8 +51,12 @@ public abstract class Sensor { +@@ -31,8 +44,12 @@ public abstract class Sensor { public final void tick(ServerLevel world, E entity) { if (--this.timeToTick <= 0L) {