From 32297028342629999adccc5b9d4829c99e391e34 Mon Sep 17 00:00:00 2001 From: JellySquid Date: Wed, 22 Apr 2020 17:11:50 +0200 Subject: [PATCH] Implement JellySquid's Entity Collision optimisations patch This patch replaces the vanilla collision code for both block and entity collisions with faster implementations by JellySquid, used originally in her Lithium mod. Optimizes Full Block voxel collisions, and removes streams from Entity collisions Original code by JellySquid, licensed under GNU Lesser General Public License v3.0 you can find the original code on https://github.com/jellysquid3/lithium-fabric/tree/1.15.x/fabric (Yarn mappings) Ported by Co-authored-by: Zoutelande <54509836+Zoutelande@users.noreply.github.com> Touched up by Aikar to keep previous paper optimizations --- ...ient-rendering-skulls-from-same-user.patch | 10 +- ...quid-s-Entity-Collision-optimisation.patch | 101 ++++++++++++++++++ Spigot-Server-Patches/MC-Utils.patch | 75 +++++++++++++ 3 files changed, 184 insertions(+), 2 deletions(-) create mode 100644 Spigot-Server-Patches/Implement-JellySquid-s-Entity-Collision-optimisation.patch diff --git a/Spigot-Server-Patches/Fix-client-rendering-skulls-from-same-user.patch b/Spigot-Server-Patches/Fix-client-rendering-skulls-from-same-user.patch index 17b907a1d..f5c519bfb 100644 --- a/Spigot-Server-Patches/Fix-client-rendering-skulls-from-same-user.patch +++ b/Spigot-Server-Patches/Fix-client-rendering-skulls-from-same-user.patch @@ -29,7 +29,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/PacketDataSerializer.java +++ b/src/main/java/net/minecraft/server/PacketDataSerializer.java @@ -0,0 +0,0 @@ public class PacketDataSerializer extends ByteBuf { - CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); + if (item.usesDurability() || item.o()) { + // Spigot start - filter + itemstack = itemstack.cloneItemStack(); +- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ //CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported // Spigot end nbttagcompound = itemstack.getTag(); + // Paper start @@ -48,6 +52,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 itemstack.setTag(this.l()); // CraftBukkit start if (itemstack.getTag() != null) { +- CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); + // Paper start - Fix skulls of same owner - restore orig ID since we changed it on send to client + if (itemstack.tag.hasKey("SkullOwnerOrig")) { + NBTTagCompound owner = itemstack.tag.getCompound("SkullOwner"); @@ -58,9 +63,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + itemstack.tag.remove("SkullOwnerOrig"); + } + // Paper end - CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); ++ // CraftItemStack.setItemMeta(itemstack, CraftItemStack.getItemMeta(itemstack)); // Paper - This is no longer needed due to NBT being supported } // CraftBukkit end + return itemstack; diff --git a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java b/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/PacketPlayOutMapChunk.java diff --git a/Spigot-Server-Patches/Implement-JellySquid-s-Entity-Collision-optimisation.patch b/Spigot-Server-Patches/Implement-JellySquid-s-Entity-Collision-optimisation.patch new file mode 100644 index 000000000..afa783e78 --- /dev/null +++ b/Spigot-Server-Patches/Implement-JellySquid-s-Entity-Collision-optimisation.patch @@ -0,0 +1,101 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: JellySquid +Date: Sat, 9 May 2020 16:25:21 -0400 +Subject: [PATCH] Implement JellySquid's Entity Collision optimisations patch + +Optimizes Full Block voxel collisions, and removes streams from Entity collisions + +Original code by JellySquid, licensed under GNU Lesser General Public License v3.0 +you can find the original code on https://github.com/jellysquid3/lithium-fabric/tree/1.15.x/fabric (Yarn mappings) + +diff --git a/src/main/java/net/minecraft/server/ICollisionAccess.java b/src/main/java/net/minecraft/server/ICollisionAccess.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/ICollisionAccess.java ++++ b/src/main/java/net/minecraft/server/ICollisionAccess.java +@@ -0,0 +0,0 @@ public interface ICollisionAccess extends IBlockAccess { + + if ((j2 != 1 || iblockdata.f()) && (j2 != 2 || iblockdata.getBlock() == Blocks.MOVING_PISTON)) { + VoxelShape voxelshape2 = iblockdata.b((IBlockAccess) ICollisionAccess.this, blockposition_mutableblockposition, voxelshapecollision); +- VoxelShape voxelshape3 = voxelshape2.a((double) k1, (double) l1, (double) i2); + +- if (VoxelShapes.c(voxelshape, voxelshape3, OperatorBoolean.AND)) { +- consumer.accept(voxelshape3); +- return true; ++ // Paper start - Lithium Collision Optimizations ++ if (voxelshape2 == VoxelShapes.empty()) { ++ continue; ++ } ++ ++ if (voxelshape2 == VoxelShapes.fullCube()) { ++ if (axisalignedbb.intersects(x, y, z, x + 1.0D, y + 1.0D, z + 1.0D)) { ++ consumer.accept(voxelshape2.offset(x, y, z)); ++ return true; ++ } ++ } else { ++ VoxelShape shape = voxelshape2.offset(x, y, z); ++ if (VoxelShapes.applyOperation(shape, voxelshape, OperatorBoolean.AND)) { ++ consumer.accept(shape); ++ return true; ++ } ++ // Paper end + } + } + } +diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/IEntityAccess.java ++++ b/src/main/java/net/minecraft/server/IEntityAccess.java +@@ -0,0 +0,0 @@ public interface IEntityAccess { + // Paper end - optimise hard collision + + default Stream b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set set) { +- if (axisalignedbb.a() < 1.0E-7D) { ++ // Paper start - remove streams from entity collision ++ if (axisalignedbb.getAverageSideLength() < 1.0E-7D) { + return Stream.empty(); +- } else { +- AxisAlignedBB axisalignedbb1 = axisalignedbb.g(1.0E-7D); +- Stream stream = ((entity != null && entity.hardCollides()) ? this.getEntities(entity, axisalignedbb) : this.getHardCollidingEntities(entity, axisalignedbb1)).stream().filter((entity1) -> { // Paper - decompile fix // Paper - optimise hard collision +- return !set.contains(entity1); +- }).filter((entity1) -> { +- return entity == null || !entity.isSameVehicle(entity1); +- }).flatMap((entity1) -> { +- return Stream.of(entity1.au(), entity == null ? null : entity.j(entity1)); // Paper - optimise hard collision - diff on change, these are the methods that only hard colliding entities override +- }).filter(Objects::nonNull); +- +- return stream.filter(axisalignedbb1::c).map(VoxelShapes::a); ++ + } ++ AxisAlignedBB selection = axisalignedbb.grow(1.0E-7D); ++ List entities = entity != null && entity.hardCollides() ? getEntities(entity, selection) : getHardCollidingEntities(entity, selection); ++ List shapes = new java.util.ArrayList<>(); ++ ++ for (Entity otherEntity : entities) { ++ if (!set.isEmpty() && set.contains(otherEntity)) { ++ continue; ++ } ++ ++ if (entity != null && entity.isSameVehicle(otherEntity)) { ++ continue; ++ } ++ ++ AxisAlignedBB otherEntityBox = otherEntity.getCollisionBox(); ++ ++ if (otherEntityBox != null && selection.intersects(otherEntityBox)) { ++ shapes.add(VoxelShapes.of(otherEntityBox)); ++ } ++ ++ if (entity != null) { ++ AxisAlignedBB otherEntityHardBox = entity.getHardCollisionBox(otherEntity); ++ ++ if (otherEntityHardBox != null && selection.intersects(otherEntityHardBox)) { ++ shapes.add(VoxelShapes.of(otherEntityHardBox)); ++ } ++ } ++ } ++ ++ return shapes.stream(); ++ // Paper end + } + + @Nullable diff --git a/Spigot-Server-Patches/MC-Utils.patch b/Spigot-Server-Patches/MC-Utils.patch index 45222799d..f79591b4b 100644 --- a/Spigot-Server-Patches/MC-Utils.patch +++ b/Spigot-Server-Patches/MC-Utils.patch @@ -2340,6 +2340,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public boolean c(AxisAlignedBB axisalignedbb) { return this.a(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ); } + ++ public final boolean intersects(double d0, double d1, double d2, double d3, double d4, double d5) { return a(d0, d1, d2, d3, d4, d5); } // Paper - OBFHELPER + public boolean a(double d0, double d1, double d2, double d3, double d4, double d5) { + return this.minX < d3 && this.maxX > d0 && this.minY < d4 && this.maxY > d1 && this.minZ < d5 && this.maxZ > d2; + } +@@ -0,0 +0,0 @@ public class AxisAlignedBB { + return d0 >= this.minX && d0 < this.maxX && d1 >= this.minY && d1 < this.maxY && d2 >= this.minZ && d2 < this.maxZ; + } + ++ public final double getAverageSideLength(){return a();} // Paper - OBFHELPER + public double a() { + double d0 = this.b(); + double d1 = this.c(); diff --git a/src/main/java/net/minecraft/server/BlockAccessAir.java b/src/main/java/net/minecraft/server/BlockAccessAir.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/BlockAccessAir.java @@ -3061,6 +3074,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void b(PacketDataSerializer packetdataserializer) { this.a(); packetdataserializer.writeByte(this.i); +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener { + + } + ++ public final AxisAlignedBB getCollisionBox(){return au();} //Paper - OBFHELPER + @Nullable + public AxisAlignedBB au() { + return null; +@@ -0,0 +0,0 @@ public abstract class Entity implements INamableTileEntity, ICommandListener { + return false; + } + ++ public final AxisAlignedBB getHardCollisionBox(Entity entity){ return j(entity);}//Paper - OBFHELPER + @Nullable + public AxisAlignedBB j(Entity entity) { + return null; diff --git a/src/main/java/net/minecraft/server/EntityCreature.java b/src/main/java/net/minecraft/server/EntityCreature.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/EntityCreature.java @@ -3204,6 +3237,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 default int h(BlockPosition blockposition) { return this.getType(blockposition).h(); } +diff --git a/src/main/java/net/minecraft/server/IBlockData.java b/src/main/java/net/minecraft/server/IBlockData.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/IBlockData.java ++++ b/src/main/java/net/minecraft/server/IBlockData.java +@@ -0,0 +0,0 @@ public class IBlockData extends BlockDataAbstract implements + return this.c != null && this.c.f != null ? this.c.f[enumdirection.ordinal()] : VoxelShapes.a(this.j(iblockaccess, blockposition), enumdirection); + } + ++ public final boolean exceedsCube(){ return f();} // Paper - OBFHELPER + public boolean f() { + return this.c == null || this.c.h; + } diff --git a/src/main/java/net/minecraft/server/IOWorker.java b/src/main/java/net/minecraft/server/IOWorker.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/IOWorker.java @@ -4222,6 +4267,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public static TicketType a(String s, Comparator comparator) { return new TicketType<>(s, comparator, 0L); +diff --git a/src/main/java/net/minecraft/server/VoxelShapes.java b/src/main/java/net/minecraft/server/VoxelShapes.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/VoxelShapes.java ++++ b/src/main/java/net/minecraft/server/VoxelShapes.java +@@ -0,0 +0,0 @@ public final class VoxelShapes { + public static final VoxelShape a = create(Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY); + private static final VoxelShape c = new VoxelShapeArray(new VoxelShapeBitSet(0, 0, 0), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D}), new DoubleArrayList(new double[]{0.0D})); + ++ public static final VoxelShape empty() {return a();} // Paper - OBFHELPER + public static VoxelShape a() { + return VoxelShapes.c; + } + ++ public static final VoxelShape fullCube() {return b();} // Paper - OBFHELPER + public static VoxelShape b() { + return VoxelShapes.b; + } diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/World.java @@ -4286,6 +4348,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Fluid fluid = this.getFluid(blockposition); return this.setTypeAndData(blockposition, fluid.getBlockData(), 3 | (flag ? 64 : 0)); +diff --git a/src/main/java/net/minecraft/server/WorldBorder.java b/src/main/java/net/minecraft/server/WorldBorder.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/WorldBorder.java ++++ b/src/main/java/net/minecraft/server/WorldBorder.java +@@ -0,0 +0,0 @@ public class WorldBorder { + return this.b(entity.locX(), entity.locZ()); + } + ++ public final VoxelShape asVoxelShape(){ return a();} // Paper - OBFHELPER ++ + public VoxelShape a() { + return this.i.m(); + } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemStack.java