diff --git a/Spigot-Server-Patches/0453-Optimize-Collision-to-not-load-chunks.patch b/Spigot-Server-Patches/0453-Optimize-Collision-to-not-load-chunks.patch index 1b9a9618b9..1402ef3e64 100644 --- a/Spigot-Server-Patches/0453-Optimize-Collision-to-not-load-chunks.patch +++ b/Spigot-Server-Patches/0453-Optimize-Collision-to-not-load-chunks.patch @@ -14,10 +14,10 @@ movement will load only the chunk the player enters anyways and avoids loading massive amounts of surrounding chunks due to large AABB lookups. diff --git a/src/main/java/net/minecraft/server/ICollisionAccess.java b/src/main/java/net/minecraft/server/ICollisionAccess.java -index f851ed11df14fd9aa8017f44d82fb6cfc3bde345..d9aeb27a3d6cc2fef2030eafd01d92ef7758111c 100644 +index f851ed11df14fd9aa8017f44d82fb6cfc3bde345..bdebbaf0b93ae7186b0afb3b2c04fdcf11148121 100644 --- a/src/main/java/net/minecraft/server/ICollisionAccess.java +++ b/src/main/java/net/minecraft/server/ICollisionAccess.java -@@ -83,19 +83,28 @@ public interface ICollisionAccess extends IBlockAccess { +@@ -83,19 +83,29 @@ public interface ICollisionAccess extends IBlockAccess { } while (cursorposition.a()) { @@ -40,12 +40,13 @@ index f851ed11df14fd9aa8017f44d82fb6cfc3bde345..d9aeb27a3d6cc2fef2030eafd01d92ef + // Paper start - ensure we don't load chunks + //int k2 = k1 >> 4; + //int l2 = i2 >> 4; -+ //boolean far = entity != null && MCUtil.distance(entity.locX(), entity.locY(), entity.locZ(), x, y, z) > 8; ++ boolean far = entity != null && MCUtil.distance(entity.locX(), entity.locY(), entity.locZ(), x, y, z) > 1; + blockposition_mutableblockposition.setValues(x, y, z); // Paper - moved up ++ + IBlockData iblockdata = ICollisionAccess.this.getTypeIfLoaded(blockposition_mutableblockposition); + if (iblockdata == null) { + if (!(entity instanceof EntityPlayer) || entity.world.paperConfig.preventMovingIntoUnloadedChunks) { -+ VoxelShape voxelshape3 = VoxelShapes.a(new AxisAlignedBB(new BlockPosition(x, y, z))); ++ VoxelShape voxelshape3 = VoxelShapes.of(far ? entity.getBoundingBox() : new AxisAlignedBB(new BlockPosition(x, y, z))); + consumer.accept(voxelshape3); + return true; + } diff --git a/Spigot-Server-Patches/0512-Implement-JellySquid-s-Entity-Collision-optimisation.patch b/Spigot-Server-Patches/0512-Implement-JellySquid-s-Entity-Collision-optimisation.patch index d39a91f188..b7ce243b29 100644 --- a/Spigot-Server-Patches/0512-Implement-JellySquid-s-Entity-Collision-optimisation.patch +++ b/Spigot-Server-Patches/0512-Implement-JellySquid-s-Entity-Collision-optimisation.patch @@ -9,10 +9,10 @@ Original code by JellySquid, licensed under GNU Lesser General Public License v3 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 d9aeb27a3d6cc2fef2030eafd01d92ef7758111c..67c3f0fc718089bb1f57bbb45fda5677bd628cbd 100644 +index bdebbaf0b93ae7186b0afb3b2c04fdcf11148121..be4e311eadbd5a3b4d17ec6eb691d3ff0af711ae 100644 --- a/src/main/java/net/minecraft/server/ICollisionAccess.java +++ b/src/main/java/net/minecraft/server/ICollisionAccess.java -@@ -108,11 +108,24 @@ public interface ICollisionAccess extends IBlockAccess { +@@ -109,11 +109,24 @@ 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); diff --git a/Spigot-Server-Patches/0513-Remove-some-Streams-usage-in-Entity-Collision.patch b/Spigot-Server-Patches/0513-Remove-some-Streams-usage-in-Entity-Collision.patch new file mode 100644 index 0000000000..1747a3ab6a --- /dev/null +++ b/Spigot-Server-Patches/0513-Remove-some-Streams-usage-in-Entity-Collision.patch @@ -0,0 +1,177 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sat, 9 May 2020 18:36:27 -0400 +Subject: [PATCH] Remove some Streams usage in Entity Collision + +While there is more down the collision system, remove some of the wrapping +Spliterator stuff as even this wrapper stream has shown up in profiling. + +With other collision optimizations, we might also even avoid inner streams too. + +diff --git a/src/main/java/net/minecraft/server/GeneratorAccess.java b/src/main/java/net/minecraft/server/GeneratorAccess.java +index e865a5694f78fb9273a0625ab2c30b87d0711a90..5648ba73c533f622c35c808decdb305f8a1cf6b0 100644 +--- a/src/main/java/net/minecraft/server/GeneratorAccess.java ++++ b/src/main/java/net/minecraft/server/GeneratorAccess.java +@@ -52,6 +52,7 @@ public interface GeneratorAccess extends IEntityAccess, IWorldReader, VirtualLev + this.a((EntityHuman) null, i, blockposition, j); + } + ++ @Override default java.util.List getEntityCollisions(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set set, boolean returnFast) {return IEntityAccess.super.getEntityCollisions(entity, axisalignedbb, set, returnFast); } // Paper + @Override + default Stream b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set set) { + return IEntityAccess.super.b(entity, axisalignedbb, set); +diff --git a/src/main/java/net/minecraft/server/ICollisionAccess.java b/src/main/java/net/minecraft/server/ICollisionAccess.java +index be4e311eadbd5a3b4d17ec6eb691d3ff0af711ae..434d8fd019b63e7352c435fe72cdfc32e338e8c5 100644 +--- a/src/main/java/net/minecraft/server/ICollisionAccess.java ++++ b/src/main/java/net/minecraft/server/ICollisionAccess.java +@@ -43,18 +43,39 @@ public interface ICollisionAccess extends IBlockAccess { + } + + default boolean a(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set set) { +- return this.c(entity, axisalignedbb, set).allMatch(VoxelShape::isEmpty); ++ // Paper start - reduce stream usage ++ java.util.List blockCollisions = getBlockCollision(entity, axisalignedbb, true); ++ for (int i = 0; i < blockCollisions.size(); i++) { ++ VoxelShape blockCollision = blockCollisions.get(i); ++ if (!blockCollision.isEmpty()) { ++ return false; ++ } ++ } ++ return getEntityCollisions(entity, axisalignedbb, set, true).isEmpty(); ++ // Paper end + } + ++ default java.util.List getEntityCollisions(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set set, boolean returnFast) { return java.util.Collections.emptyList(); } // Paper + default Stream b(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set set) { + return Stream.empty(); + } + + default Stream c(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set set) { +- return Streams.concat(new Stream[]{this.b(entity, axisalignedbb), this.b(entity, axisalignedbb, set)}); ++ // Paper start - reduce stream usage ++ java.util.List blockCollisions = getBlockCollision(entity, axisalignedbb, false); ++ java.util.List entityCollisions = getEntityCollisions(entity, axisalignedbb, set, false); ++ return Stream.concat(blockCollisions.stream(), entityCollisions.stream()); ++ // Paper end + } + + default Stream b(@Nullable final Entity entity, AxisAlignedBB axisalignedbb) { ++ // Paper start - reduce stream usage ++ java.util.List collision = getBlockCollision(entity, axisalignedbb, false); ++ return !collision.isEmpty() ? collision.stream() : Stream.empty(); ++ } ++ ++ default java.util.List getBlockCollision(@Nullable final Entity entity, AxisAlignedBB axisalignedbb, boolean returnFast) { ++ // Paper end + int i = MathHelper.floor(axisalignedbb.minX - 1.0E-7D) - 1; + int j = MathHelper.floor(axisalignedbb.maxX + 1.0E-7D) + 1; + int k = MathHelper.floor(axisalignedbb.minY - 1.0E-7D) - 1; +@@ -66,19 +87,19 @@ public interface ICollisionAccess extends IBlockAccess { + final BlockPosition.MutableBlockPosition blockposition_mutableblockposition = new BlockPosition.MutableBlockPosition(); + final VoxelShape voxelshape = VoxelShapes.a(axisalignedbb); + +- return StreamSupport.stream(new AbstractSpliterator(Long.MAX_VALUE, 1280) { +- boolean a = entity == null; +- +- public boolean tryAdvance(Consumer consumer) { +- if (!this.a) { +- this.a = true; ++ // Paper start - reduce stream usage (this part done by Aikar) ++ java.util.List collisions = new java.util.ArrayList<>(); ++ if (true) {//return StreamSupport.stream(new AbstractSpliterator(Long.MAX_VALUE, 1280) { ++ if (true) { //public boolean tryAdvance(Consumer consumer) {*/ // Paper ++ if (entity != null) { ++ // Paper end + VoxelShape voxelshape1 = ICollisionAccess.this.getWorldBorder().a(); + boolean flag = VoxelShapes.c(voxelshape1, VoxelShapes.a(entity.getBoundingBox().shrink(1.0E-7D)), OperatorBoolean.AND); + boolean flag1 = VoxelShapes.c(voxelshape1, VoxelShapes.a(entity.getBoundingBox().g(1.0E-7D)), OperatorBoolean.AND); + + if (!flag && flag1) { +- consumer.accept(voxelshape1); +- return true; ++ collisions.add(voxelshape1);// Paper ++ if (returnFast) return collisions; + } + } + +@@ -98,9 +119,8 @@ public interface ICollisionAccess extends IBlockAccess { + IBlockData iblockdata = ICollisionAccess.this.getTypeIfLoaded(blockposition_mutableblockposition); + if (iblockdata == null) { + if (!(entity instanceof EntityPlayer) || entity.world.paperConfig.preventMovingIntoUnloadedChunks) { +- VoxelShape voxelshape3 = VoxelShapes.of(far ? entity.getBoundingBox() : new AxisAlignedBB(new BlockPosition(x, y, z))); +- consumer.accept(voxelshape3); +- return true; ++ collisions.add(VoxelShapes.of(far ? entity.getBoundingBox() : new AxisAlignedBB(new BlockPosition(x, y, z)))); ++ if (returnFast) return collisions; + } + } else { + //blockposition_mutableblockposition.d(k1, l1, i2); // moved up +@@ -117,14 +137,14 @@ public interface ICollisionAccess extends IBlockAccess { + + 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; ++ collisions.add(voxelshape2.offset(x, y, z)); ++ if (returnFast) return collisions; + } + } else { + VoxelShape shape = voxelshape2.offset(x, y, z); + if (VoxelShapes.applyOperation(shape, voxelshape, OperatorBoolean.AND)) { +- consumer.accept(shape); +- return true; ++ collisions.add(shape); ++ if (returnFast) return collisions; + } + // Paper end + } +@@ -133,8 +153,9 @@ public interface ICollisionAccess extends IBlockAccess { + } + } + +- return false; ++ //return false; // Paper + } +- }, false); ++ } //}, false); ++ return collisions; // Paper + } + } +diff --git a/src/main/java/net/minecraft/server/IEntityAccess.java b/src/main/java/net/minecraft/server/IEntityAccess.java +index d434aaaaf0ab6a18ab0fe5ad0bf8ed4662f49120..3bc57ef91d557383178533b0cc87a71a521d6b3e 100644 +--- a/src/main/java/net/minecraft/server/IEntityAccess.java ++++ b/src/main/java/net/minecraft/server/IEntityAccess.java +@@ -55,8 +55,10 @@ public interface IEntityAccess { + // Paper start - remove streams from entity collision + if (axisalignedbb.getAverageSideLength() < 1.0E-7D) { + return Stream.empty(); +- + } ++ return getEntityCollisions(entity, axisalignedbb, set, false).stream(); ++ } ++ default List getEntityCollisions(@Nullable Entity entity, AxisAlignedBB axisalignedbb, Set set, boolean returnFast) { + 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<>(); +@@ -74,6 +76,7 @@ public interface IEntityAccess { + + if (otherEntityBox != null && selection.intersects(otherEntityBox)) { + shapes.add(VoxelShapes.of(otherEntityBox)); ++ if (returnFast) return shapes; + } + + if (entity != null) { +@@ -81,11 +84,12 @@ public interface IEntityAccess { + + if (otherEntityHardBox != null && selection.intersects(otherEntityHardBox)) { + shapes.add(VoxelShapes.of(otherEntityHardBox)); ++ if (returnFast) return shapes; + } + } + } + +- return shapes.stream(); ++ return shapes; + // Paper end + } +