From 92f680ed84b0f01aadf60a67750b4d448dde9c61 Mon Sep 17 00:00:00 2001 From: Aikar Date: Mon, 11 May 2020 21:18:11 -0400 Subject: [PATCH] Fix Pathfinding and obscure glitchy buggy 0 tick farms I swear the crap that stuff will abuse to make stuff happen is insane. Hash codes apparently changing behavior of stuff based on its value, so reverting https://github.com/PaperMC/Paper/commit/2d401d2dfb7ed380439c00c8cef6dac8e9fc642e Fixes #3346 Fixes #3341 --- ...0251-Improve-BlockPosition-inlining.patch} | 64 ++++++------------- .../0435-Optimise-random-block-ticking.patch | 6 +- ...der-Remove-Streams-Optimized-collect.patch | 4 +- 3 files changed, 23 insertions(+), 51 deletions(-) rename Spigot-Server-Patches/{0251-Improve-BlockPosition-inline-and-hashCode-equals.patch => 0251-Improve-BlockPosition-inlining.patch} (82%) diff --git a/Spigot-Server-Patches/0251-Improve-BlockPosition-inline-and-hashCode-equals.patch b/Spigot-Server-Patches/0251-Improve-BlockPosition-inlining.patch similarity index 82% rename from Spigot-Server-Patches/0251-Improve-BlockPosition-inline-and-hashCode-equals.patch rename to Spigot-Server-Patches/0251-Improve-BlockPosition-inlining.patch index 728f8e1589..2d668ce57b 100644 --- a/Spigot-Server-Patches/0251-Improve-BlockPosition-inline-and-hashCode-equals.patch +++ b/Spigot-Server-Patches/0251-Improve-BlockPosition-inlining.patch @@ -1,7 +1,7 @@ From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Techcable Date: Wed, 30 Nov 2016 20:56:58 -0600 -Subject: [PATCH] Improve BlockPosition inline and hashCode/equals +Subject: [PATCH] Improve BlockPosition inlining Normally the JVM can inline virtual getters by having two sets of code, one is the 'optimized' code and the other is the 'deoptimized' code. If a single type is used 99% of the time, then its worth it to inline, and to revert to 'deoptimized' the 1% of the time we encounter other types. @@ -20,15 +20,11 @@ This should result in an across the board speedup in anything that accesses bloc This is based upon conclusions drawn from inspecting the assenmbly generated bythe JIT compiler on my microbenchmarks. They had 'callq' (invoke) instead of 'mov' (get from memory) instructions. -Co-Authored-By: Aikar -for: -Also cache the hashCode and long values to use it for speeding up hashmap usage - diff --git a/src/main/java/net/minecraft/server/BaseBlockPosition.java b/src/main/java/net/minecraft/server/BaseBlockPosition.java -index 71089442c189336fc0061852a661581784a64013..334a6ab0df1978c42fdf8ad454e96f60e70c76dc 100644 +index 71089442c189336fc0061852a661581784a64013..8f47b6c9e70d10c444ab328dc3bf3a46499b14d5 100644 --- a/src/main/java/net/minecraft/server/BaseBlockPosition.java +++ b/src/main/java/net/minecraft/server/BaseBlockPosition.java -@@ -7,32 +7,32 @@ import javax.annotation.concurrent.Immutable; +@@ -7,32 +7,30 @@ import javax.annotation.concurrent.Immutable; public class BaseBlockPosition implements Comparable { public static final BaseBlockPosition ZERO = new BaseBlockPosition(0, 0, 0); @@ -41,11 +37,9 @@ index 71089442c189336fc0061852a661581784a64013..334a6ab0df1978c42fdf8ad454e96f60 // Paper start - public boolean isValidLocation() { - return a >= -30000000 && c >= -30000000 && a < 30000000 && c < 30000000 && b >= 0 && b < 256; -+ protected int x; // If these ever become non final, review this entire patch, look for places need to rehash on write ++ protected int x; + protected int y; + protected int z; -+ private int hashCodeCached = 0; -+ private long cachedLong = Long.MAX_VALUE; + + public final boolean isValidLocation() { + return x >= -30000000 && z >= -30000000 && x < 30000000 && z < 30000000 && y >= 0 && y < 256; @@ -75,37 +69,19 @@ index 71089442c189336fc0061852a661581784a64013..334a6ab0df1978c42fdf8ad454e96f60 if (this == object) { return true; } else if (!(object instanceof BaseBlockPosition)) { -@@ -40,29 +40,49 @@ public class BaseBlockPosition implements Comparable { +@@ -40,29 +38,31 @@ public class BaseBlockPosition implements Comparable { } else { BaseBlockPosition baseblockposition = (BaseBlockPosition) object; - return this.getX() != baseblockposition.getX() ? false : (this.getY() != baseblockposition.getY() ? false : this.getZ() == baseblockposition.getZ()); -+ return this.asLong() == baseblockposition.asLong(); // Paper ++ return x == baseblockposition.x && z == baseblockposition.z && y == baseblockposition.y; // Paper } } - public int hashCode() { - return (this.getY() + this.getZ() * 31) * 31 + this.getX(); -+ public final int hashCode() { -+ // Paper start -+ if (this.cachedLong == Long.MAX_VALUE) { -+ rebuildCache(); -+ } -+ return this.hashCodeCached; -+ } -+ private void rebuildCache() { -+ this.cachedLong = BlockPosition.asLong(getX(), getY(), getZ()); -+ this.hashCodeCached = (this.getY() + this.getZ() * 1031) * 1031 + this.getX(); -+ } -+ public final long asLong() { -+ if (this.cachedLong == Long.MAX_VALUE) { -+ rebuildCache(); -+ } -+ return this.cachedLong; -+ } -+ public final void rehash() { -+ this.cachedLong = Long.MAX_VALUE; -+ // Paper end ++ public final int hashCode() { // Paper ++ return (this.y + this.z * 31) * 31 + this.x; // Paper } public int compareTo(BaseBlockPosition baseblockposition) { @@ -134,7 +110,7 @@ index 71089442c189336fc0061852a661581784a64013..334a6ab0df1978c42fdf8ad454e96f60 public BaseBlockPosition down() { return this.down(1); -@@ -75,13 +95,14 @@ public class BaseBlockPosition implements Comparable { +@@ -75,13 +75,14 @@ public class BaseBlockPosition implements Comparable { public BaseBlockPosition shift(EnumDirection enumdirection, int i) { return i == 0 ? this : new BaseBlockPosition(this.getX() + enumdirection.getAdjacentX() * i, this.getY() + enumdirection.getAdjacentY() * i, this.getZ() + enumdirection.getAdjacentZ() * i); } @@ -150,7 +126,7 @@ index 71089442c189336fc0061852a661581784a64013..334a6ab0df1978c42fdf8ad454e96f60 } public boolean a(IPosition iposition, double d0) { -@@ -106,9 +127,9 @@ public class BaseBlockPosition implements Comparable { +@@ -106,9 +107,9 @@ public class BaseBlockPosition implements Comparable { } public int n(BaseBlockPosition baseblockposition) { @@ -164,7 +140,7 @@ index 71089442c189336fc0061852a661581784a64013..334a6ab0df1978c42fdf8ad454e96f60 return (int) (f + f1 + f2); } diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index f8ac39e1b019b0918996f745d99f6ed09db0fd11..0ce39e34c1d60ec0fc9d4a0e1b802d8c96177b4b 100644 +index f8ac39e1b019b0918996f745d99f6ed09db0fd11..ec0e8f970dba64561afd6477a5df2821d9a8889a 100644 --- a/src/main/java/net/minecraft/server/BlockPosition.java +++ b/src/main/java/net/minecraft/server/BlockPosition.java @@ -99,6 +99,7 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali @@ -175,15 +151,15 @@ index f8ac39e1b019b0918996f745d99f6ed09db0fd11..0ce39e34c1d60ec0fc9d4a0e1b802d8c public static long a(int i, int j, int k) { long l = 0L; -@@ -112,7 +113,7 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali - return i & -16L; +@@ -113,7 +114,7 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali } -- public long asLong() { -+ public long asLong_unused() { // Paper - moved to parent - return a(this.getX(), this.getY(), this.getZ()); + public long asLong() { +- return a(this.getX(), this.getY(), this.getZ()); ++ return a(this.x, this.y, this.z); // Paper } + public BlockPosition a(double d0, double d1, double d2) { @@ -343,11 +344,13 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali } @@ -226,7 +202,7 @@ index f8ac39e1b019b0918996f745d99f6ed09db0fd11..0ce39e34c1d60ec0fc9d4a0e1b802d8c @Override public int getX() { return this.b; -@@ -404,13 +413,17 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali +@@ -404,13 +413,16 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali @Override public int getZ() { return this.d; @@ -243,12 +219,11 @@ index f8ac39e1b019b0918996f745d99f6ed09db0fd11..0ce39e34c1d60ec0fc9d4a0e1b802d8c + this.x = i; + this.y = j; + this.z = k; -+ rehash(); + // Paper end return this; } -@@ -440,26 +453,29 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali +@@ -440,26 +452,26 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali } public BlockPosition.MutableBlockPosition c(EnumDirection enumdirection, int i) { @@ -265,21 +240,18 @@ index f8ac39e1b019b0918996f745d99f6ed09db0fd11..0ce39e34c1d60ec0fc9d4a0e1b802d8c public void o(int i) { - this.b = i; + this.x = i; // Paper change to x -+ rehash(); // Paper } public final void setY(final int y) { this.p(y); } // Paper - OBFHELPER public void p(int i) { - this.c = i; + this.y = i; // Paper change to y -+ rehash(); // Paper } public final void setZ(final int z) { this.q(z); } // Paper - OBFHELPER public void q(int i) { - this.d = i; + this.z = i; // Paper change to z -+ rehash(); // Paper } @Override diff --git a/Spigot-Server-Patches/0435-Optimise-random-block-ticking.patch b/Spigot-Server-Patches/0435-Optimise-random-block-ticking.patch index cb5d2171d0..4348e8daab 100644 --- a/Spigot-Server-Patches/0435-Optimise-random-block-ticking.patch +++ b/Spigot-Server-Patches/0435-Optimise-random-block-ticking.patch @@ -99,10 +99,10 @@ index 6d351f0979ecfa8e500edf8dd03b4a455fd5d180..a44f65f40d2080b63069602a454266ee @Override diff --git a/src/main/java/net/minecraft/server/BlockPosition.java b/src/main/java/net/minecraft/server/BlockPosition.java -index df93e32242bb91ddb1c2da8965956d38ee381dc2..063f8eb08635aaa44803f2a67d118805294ae938 100644 +index a3a376e35eaf17b128048bd26a22eef713e7d535..3fcfe416d26808fa1c9bfdc5b413b149764c544a 100644 --- a/src/main/java/net/minecraft/server/BlockPosition.java +++ b/src/main/java/net/minecraft/server/BlockPosition.java -@@ -453,6 +453,7 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali +@@ -452,6 +452,7 @@ public class BlockPosition extends BaseBlockPosition implements MinecraftSeriali return this.d(MathHelper.floor(d0), MathHelper.floor(d1), MathHelper.floor(d2)); } @@ -363,7 +363,7 @@ index 0c23fc89d7ad980aa8b094784e88e2d91fb4f07b..de9f49b884838105c537b73d69234eb2 public boolean isSavingDisabled() { diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index c348e3e5008e9213f96f2eb718cfb07c340bf77b..fcbc9f29139ce5cd3b165130006f9c326a5d9eea 100644 +index 0d6abbab237916df4f7d7d79f2f4725018d8edf9..cb2ae8eff36f46b6963ee45d7740ac48afac1ab0 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java @@ -531,7 +531,12 @@ public class WorldServer extends World { diff --git a/Spigot-Server-Patches/0520-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch b/Spigot-Server-Patches/0520-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch index 5844ef3486..afb15db8d5 100644 --- a/Spigot-Server-Patches/0520-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch +++ b/Spigot-Server-Patches/0520-Optimize-Pathfinder-Remove-Streams-Optimized-collect.patch @@ -16,7 +16,7 @@ This lets us get faster foreach iteration, as well as avoids map lookups on the values when needed. diff --git a/src/main/java/net/minecraft/server/Pathfinder.java b/src/main/java/net/minecraft/server/Pathfinder.java -index 67c63cfe333e328cbd00ada970bd81efebfe30b6..ae6594ea853e08085aa65bd884d4211d2bf28d16 100644 +index 67c63cfe333e328cbd00ada970bd81efebfe30b6..71b96943d865105f279dda613b7ac6b3ffed793b 100644 --- a/src/main/java/net/minecraft/server/Pathfinder.java +++ b/src/main/java/net/minecraft/server/Pathfinder.java @@ -31,9 +31,15 @@ public class Pathfinder { @@ -155,7 +155,7 @@ index 67c63cfe333e328cbd00ada970bd81efebfe30b6..ae6594ea853e08085aa65bd884d4211d - for (Iterator iterator = set.iterator(); iterator.hasNext(); f = Math.min(f1, f)) { - PathDestination pathdestination = (PathDestination) iterator.next(); -+ for (int i = 0, listSize = list.size(); i < listSize; i++) { // Paper ++ for (int i = 0, listSize = list.size(); i < listSize; f = Math.min(f1, f), i++) { // Paper + PathDestination pathdestination = list.get(i).getKey(); // Paper f1 = pathpoint.a(pathdestination);