From 958666a8f6ab8b45652d1a682b25e42100bcb0da Mon Sep 17 00:00:00 2001 From: Noah van der Aa Date: Fri, 9 Aug 2024 02:10:47 +0200 Subject: diff cleanup --- patches/api/0392-Add-Shearable-API.patch | 24 +-- .../api/0430-Experimental-annotations-change.patch | 4 +- .../0379-Add-BlockStateMeta-clearBlockState.patch | 15 +- patches/server/0808-Add-Shearable-API.patch | 18 +- ...improve-checking-handled-tags-in-itemmeta.patch | 34 +-- ...llision-checking-in-player-move-packet-ha.patch | 170 --------------- .../1036-Optimise-nearby-player-retrieval.patch | 228 --------------------- ...llision-checking-in-player-move-packet-ha.patch | 170 +++++++++++++++ .../1036-Optimise-nearby-player-retrieval.patch | 228 +++++++++++++++++++++ 9 files changed, 425 insertions(+), 466 deletions(-) delete mode 100644 patches/unapplied-old/server/1027-Optimise-collision-checking-in-player-move-packet-ha.patch delete mode 100644 patches/unapplied-old/server/1036-Optimise-nearby-player-retrieval.patch create mode 100644 patches/unapplied/server/1027-Optimise-collision-checking-in-player-move-packet-ha.patch create mode 100644 patches/unapplied/server/1036-Optimise-nearby-player-retrieval.patch diff --git a/patches/api/0392-Add-Shearable-API.patch b/patches/api/0392-Add-Shearable-API.patch index dcd0ffe7bd..aa842fac9f 100644 --- a/patches/api/0392-Add-Shearable-API.patch +++ b/patches/api/0392-Add-Shearable-API.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Add Shearable API diff --git a/src/main/java/io/papermc/paper/entity/Shearable.java b/src/main/java/io/papermc/paper/entity/Shearable.java new file mode 100644 -index 0000000000000000000000000000000000000000..b547922db418ff813ddb6a3b37dced0db393e1f5 +index 0000000000000000000000000000000000000000..45a18019bec1890f0abbdd8eaf15a8e9f6f1c803 --- /dev/null +++ b/src/main/java/io/papermc/paper/entity/Shearable.java -@@ -0,0 +1,53 @@ +@@ -0,0 +1,43 @@ +package io.papermc.paper.entity; + +import net.kyori.adventure.sound.Sound; @@ -19,7 +19,7 @@ index 0000000000000000000000000000000000000000..b547922db418ff813ddb6a3b37dced0d +/** + * Represents an entity that can be sheared. + */ -+public interface Shearable extends Entity { ++public interface Shearable extends Entity, org.bukkit.entity.Shearable { + + /** + * Forces the entity to be sheared and then play the effect as if it were sheared by a player. @@ -52,19 +52,9 @@ index 0000000000000000000000000000000000000000..b547922db418ff813ddb6a3b37dced0d + * @return if the entity can be sheared + */ + boolean readyToBeSheared(); -+ -+ /** -+ * @return Whether the sheep is sheared. -+ */ -+ public boolean isSheared(); -+ -+ /** -+ * @param flag Whether to shear the sheep -+ */ -+ public void setSheared(boolean flag); +} diff --git a/src/main/java/org/bukkit/entity/Bogged.java b/src/main/java/org/bukkit/entity/Bogged.java -index 8b75a505a55a96a5795ac31a2d37307add12cd9e..6296a6f3f3e794677fd3a626376f357c740ec356 100644 +index 8b75a505a55a96a5795ac31a2d37307add12cd9e..a36bb84c17120bc578ab01d45f6f12fb1faf9548 100644 --- a/src/main/java/org/bukkit/entity/Bogged.java +++ b/src/main/java/org/bukkit/entity/Bogged.java @@ -6,5 +6,5 @@ import org.jetbrains.annotations.ApiStatus; @@ -72,7 +62,7 @@ index 8b75a505a55a96a5795ac31a2d37307add12cd9e..6296a6f3f3e794677fd3a626376f357c */ @ApiStatus.Experimental -public interface Bogged extends AbstractSkeleton, Shearable { -+public interface Bogged extends AbstractSkeleton, Shearable, io.papermc.paper.entity.Shearable { // Paper - Shear API ++public interface Bogged extends AbstractSkeleton, io.papermc.paper.entity.Shearable { // Paper - Shear API } diff --git a/src/main/java/org/bukkit/entity/MushroomCow.java b/src/main/java/org/bukkit/entity/MushroomCow.java index cef1700834643fe28ed5737578d91ecefbe99e2f..86c0043ef4e1288b6fe2f68a9b6d01c3de2c3454 100644 @@ -88,7 +78,7 @@ index cef1700834643fe28ed5737578d91ecefbe99e2f..86c0043ef4e1288b6fe2f68a9b6d01c3 /** * Checks for the presence of custom potion effects to be applied to the diff --git a/src/main/java/org/bukkit/entity/Sheep.java b/src/main/java/org/bukkit/entity/Sheep.java -index 46bc1a0ed9ee320c68a38362c1fa1f31319f01d8..01a0e5b1bb18d7a28d68329c2e2ab78a8df45f8e 100644 +index 46bc1a0ed9ee320c68a38362c1fa1f31319f01d8..45f55faed0d5f0db2671fa1ace59591e8061c4f2 100644 --- a/src/main/java/org/bukkit/entity/Sheep.java +++ b/src/main/java/org/bukkit/entity/Sheep.java @@ -5,5 +5,5 @@ import org.bukkit.material.Colorable; @@ -96,7 +86,7 @@ index 46bc1a0ed9ee320c68a38362c1fa1f31319f01d8..01a0e5b1bb18d7a28d68329c2e2ab78a * Represents a Sheep. */ -public interface Sheep extends Animals, Colorable, Shearable { -+public interface Sheep extends Animals, Colorable, Shearable, io.papermc.paper.entity.Shearable { // Paper - Shear API ++public interface Sheep extends Animals, Colorable, io.papermc.paper.entity.Shearable { // Paper - Shear API } diff --git a/src/main/java/org/bukkit/entity/Snowman.java b/src/main/java/org/bukkit/entity/Snowman.java index 10f8f6d45ae9280651c3ebddd1f90acbd7d6ff29..7fbfdb07585c7b28acea1f0c1f58ada0cc744441 100644 diff --git a/patches/api/0430-Experimental-annotations-change.patch b/patches/api/0430-Experimental-annotations-change.patch index 9ea8f3a126..59788de534 100644 --- a/patches/api/0430-Experimental-annotations-change.patch +++ b/patches/api/0430-Experimental-annotations-change.patch @@ -104,7 +104,7 @@ index 60fbacee263e55f91ac977f020e390d46024723a..ecff691c3a0878659fb051926ef769ce /** diff --git a/src/main/java/org/bukkit/entity/Bogged.java b/src/main/java/org/bukkit/entity/Bogged.java -index 6296a6f3f3e794677fd3a626376f357c740ec356..7d993f8bd18ec1d3260d12f0ff8078a86ee4867d 100644 +index a36bb84c17120bc578ab01d45f6f12fb1faf9548..719bccf8638f8ad358d37fa7eeccbc4c08d32868 100644 --- a/src/main/java/org/bukkit/entity/Bogged.java +++ b/src/main/java/org/bukkit/entity/Bogged.java @@ -5,6 +5,5 @@ import org.jetbrains.annotations.ApiStatus; @@ -112,7 +112,7 @@ index 6296a6f3f3e794677fd3a626376f357c740ec356..7d993f8bd18ec1d3260d12f0ff8078a8 * Represents a Bogged Skeleton. */ -@ApiStatus.Experimental - public interface Bogged extends AbstractSkeleton, Shearable, io.papermc.paper.entity.Shearable { // Paper - Shear API + public interface Bogged extends AbstractSkeleton, io.papermc.paper.entity.Shearable { // Paper - Shear API } diff --git a/src/main/java/org/bukkit/entity/Breeze.java b/src/main/java/org/bukkit/entity/Breeze.java index a75e725805c193a408683885cba83ca168347165..254bc6e18961a72f471334cc0535e3c7a9d70012 100644 diff --git a/patches/server/0379-Add-BlockStateMeta-clearBlockState.patch b/patches/server/0379-Add-BlockStateMeta-clearBlockState.patch index ecafb80ec5..4a4ca75acd 100644 --- a/patches/server/0379-Add-BlockStateMeta-clearBlockState.patch +++ b/patches/server/0379-Add-BlockStateMeta-clearBlockState.patch @@ -23,21 +23,10 @@ index 301d883a7626e3abd222517400367fc40d6fa2bd..23dbc56edf0d16cf07ced2899942abae public BlockState getBlockState() { return (this.blockEntityTag != null) ? this.blockEntityTag.copy() : CraftMetaBlockState.getBlockState(this.material, null); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java -index 3542c6e72f5ff459d50b73fa210ea835f52dfa49..2ad744875fea490eb8aa3883e4567ec1824c811a 100644 +index 3542c6e72f5ff459d50b73fa210ea835f52dfa49..43aa4920440a1626217a0fbc52d8404617ae7d10 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java -@@ -7,8 +7,10 @@ import java.util.ArrayList; - import java.util.List; - import java.util.Map; - import net.minecraft.core.BlockPos; -+import net.minecraft.core.component.DataComponentMap; - import net.minecraft.core.component.DataComponentPatch; - import net.minecraft.core.component.DataComponents; -+import net.minecraft.world.item.component.CustomData; - import net.minecraft.world.level.block.entity.BannerPatternLayers; - import org.bukkit.DyeColor; - import org.bukkit.Material; -@@ -298,4 +300,11 @@ public class CraftMetaShield extends CraftMetaItem implements ShieldMeta, BlockS +@@ -298,4 +298,11 @@ public class CraftMetaShield extends CraftMetaItem implements ShieldMeta, BlockS default -> throw new IllegalArgumentException("Unknown banner colour"); }; } diff --git a/patches/server/0808-Add-Shearable-API.patch b/patches/server/0808-Add-Shearable-API.patch index 17902a41b9..ca10e1a4d2 100644 --- a/patches/server/0808-Add-Shearable-API.patch +++ b/patches/server/0808-Add-Shearable-API.patch @@ -45,7 +45,7 @@ index 0139e85c0751564bb4d2847b7b2e48f75fee9e53..e8e4704304504e69c7964dcd4df8ce5d public CraftBogged(CraftServer server, net.minecraft.world.entity.monster.Bogged entity) { super(server, entity); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java -index 986f7b18112ef183de3bbff269a92bf6ac945477..abba0986cc562f688682ba5e4822837a503586eb 100644 +index 986f7b18112ef183de3bbff269a92bf6ac945477..5ac263889ff9cc4f4f6365ccb57917a23ad6edc1 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java @@ -14,7 +14,7 @@ import org.bukkit.entity.MushroomCow; @@ -57,7 +57,7 @@ index 986f7b18112ef183de3bbff269a92bf6ac945477..abba0986cc562f688682ba5e4822837a public CraftMushroomCow(CraftServer server, net.minecraft.world.entity.animal.MushroomCow entity) { super(server, entity); } -@@ -105,4 +105,11 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow { +@@ -105,4 +105,16 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow { public String toString() { return "CraftMushroomCow"; } @@ -67,6 +67,11 @@ index 986f7b18112ef183de3bbff269a92bf6ac945477..abba0986cc562f688682ba5e4822837a + public void setSheared(boolean sheared) { + if (sheared) this.shear(); + } ++ ++ @Override ++ public boolean isSheared() { ++ return false; ++ } + // Paper end } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSheep.java @@ -83,7 +88,7 @@ index 030bf7b6312799231d0b614ba5c84fec23c276e3..37291d7ad9fdf0fe78894f82a418f40b super(server, entity); } diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -index 1e9807b8f468742d208f817e22d7625106fc1b58..a0bd62d6abaa195bc49063fa23e87a7697f24b99 100644 +index 1e9807b8f468742d208f817e22d7625106fc1b58..05cee4906169425ee6e80cf1302f2fa01f09d58f 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java @@ -4,7 +4,7 @@ import net.minecraft.world.entity.animal.SnowGolem; @@ -95,7 +100,7 @@ index 1e9807b8f468742d208f817e22d7625106fc1b58..a0bd62d6abaa195bc49063fa23e87a76 public CraftSnowman(CraftServer server, SnowGolem entity) { super(server, entity); } -@@ -28,4 +28,11 @@ public class CraftSnowman extends CraftGolem implements Snowman, com.destroystok +@@ -28,4 +28,16 @@ public class CraftSnowman extends CraftGolem implements Snowman, com.destroystok public String toString() { return "CraftSnowman"; } @@ -105,6 +110,11 @@ index 1e9807b8f468742d208f817e22d7625106fc1b58..a0bd62d6abaa195bc49063fa23e87a76 + public void setSheared(boolean sheared) { + this.setDerp(sheared); + } ++ ++ @Override ++ public boolean isSheared() { ++ return this.isDerp(); ++ } + // Paper end } diff --git a/src/test/java/io/papermc/paper/entity/ShearableTest.java b/src/test/java/io/papermc/paper/entity/ShearableTest.java diff --git a/patches/server/0966-improve-checking-handled-tags-in-itemmeta.patch b/patches/server/0966-improve-checking-handled-tags-in-itemmeta.patch index aa8b2ec38f..6504354703 100644 --- a/patches/server/0966-improve-checking-handled-tags-in-itemmeta.patch +++ b/patches/server/0966-improve-checking-handled-tags-in-itemmeta.patch @@ -4,36 +4,6 @@ Date: Mon, 10 Jul 2023 16:10:15 -0700 Subject: [PATCH] improve checking handled tags in itemmeta -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java -index abba0986cc562f688682ba5e4822837a503586eb..5ac263889ff9cc4f4f6365ccb57917a23ad6edc1 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftMushroomCow.java -@@ -111,5 +111,10 @@ public class CraftMushroomCow extends CraftCow implements MushroomCow, io.paperm - public void setSheared(boolean sheared) { - if (sheared) this.shear(); - } -+ -+ @Override -+ public boolean isSheared() { -+ return false; -+ } - // Paper end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -index a0bd62d6abaa195bc49063fa23e87a7697f24b99..05cee4906169425ee6e80cf1302f2fa01f09d58f 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java -@@ -34,5 +34,10 @@ public class CraftSnowman extends CraftGolem implements Snowman, com.destroystok - public void setSheared(boolean sheared) { - this.setDerp(sheared); - } -+ -+ @Override -+ public boolean isSheared() { -+ return this.isDerp(); -+ } - // Paper end - } diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemMetas.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemMetas.java index a4c4ba0d02f9a072236ce86c1e98e2c60b059cb8..c9cda18761c6f925f7490984a7e035396a44a73a 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftItemMetas.java @@ -744,10 +714,10 @@ index d1cb8d520b6d7b0981d70412def71e7aab04560a..7f9182809f6e67ff571db0f365bc7e05 potionContents.potion().ifPresent((potion) -> { this.type = CraftPotionType.minecraftHolderToBukkit(potion); diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java -index 2ad744875fea490eb8aa3883e4567ec1824c811a..c98b1cb9a2aca9c1e76893b4c9c851c747c13bcd 100644 +index 43aa4920440a1626217a0fbc52d8404617ae7d10..5b30f7bff841f5830ac554532b62150fbd7716f1 100644 --- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java +++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaShield.java -@@ -44,7 +44,7 @@ public class CraftMetaShield extends CraftMetaItem implements ShieldMeta, BlockS +@@ -42,7 +42,7 @@ public class CraftMetaShield extends CraftMetaItem implements ShieldMeta, BlockS } CraftMetaShield(DataComponentPatch tag) { diff --git a/patches/unapplied-old/server/1027-Optimise-collision-checking-in-player-move-packet-ha.patch b/patches/unapplied-old/server/1027-Optimise-collision-checking-in-player-move-packet-ha.patch deleted file mode 100644 index 1e3006e3e6..0000000000 --- a/patches/unapplied-old/server/1027-Optimise-collision-checking-in-player-move-packet-ha.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Thu, 2 Jul 2020 12:02:43 -0700 -Subject: [PATCH] Optimise collision checking in player move packet handling - -Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision - -CHECK ME - -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 7796e191747be545e744564a2b0b65790f69114d..2b94b2dc3f29e7005b1a30c83f4a68e1263780b4 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -572,7 +572,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - return; - } - -- boolean flag = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); -+ AABB oldBox = entity.getBoundingBox(); // Paper - copy from player movement packet - - d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above - d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above -@@ -588,6 +588,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - - entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8)); -+ boolean didCollide = toX != entity.getX() || toY != entity.getY() || toZ != entity.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... - double d11 = d7; - - d6 = d3 - entity.getX(); -@@ -601,15 +602,23 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - boolean flag2 = false; - - if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot -- flag2 = true; -+ flag2 = true; // Paper - diff on change, this should be moved wrongly - ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", new Object[]{entity.getName().getString(), this.player.getName().getString(), Math.sqrt(d10)}); - } - - entity.absMoveTo(d3, d4, d5, f, f1); - this.player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit -- boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); - -- if (flag && (flag2 || !flag3)) { -+ // Paper start - optimise out extra getCubes -+ boolean teleportBack = flag2; // violating this is always a fail -+ if (!teleportBack) { -+ // note: only call after setLocation, or else getBoundingBox is wrong -+ AABB newBox = entity.getBoundingBox(); -+ if (didCollide || !oldBox.equals(newBox)) { -+ teleportBack = this.hasNewCollision(worldserver, entity, oldBox, newBox); -+ } // else: no collision at all detected, why do we care? -+ } -+ if (teleportBack) { // Paper end - optimise out extra getCubes - entity.absMoveTo(d0, d1, d2, f, f1); - this.player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit - this.send(new ClientboundMoveVehiclePacket(entity)); -@@ -691,7 +700,32 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - - private boolean noBlocksAround(Entity entity) { -- return entity.level().getBlockStates(entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D)).allMatch(BlockBehaviour.BlockStateBase::isAir); -+ // Paper start - stop using streams, this is already a known fixed problem in Entity#move -+ AABB box = entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D); -+ int minX = Mth.floor(box.minX); -+ int minY = Mth.floor(box.minY); -+ int minZ = Mth.floor(box.minZ); -+ int maxX = Mth.floor(box.maxX); -+ int maxY = Mth.floor(box.maxY); -+ int maxZ = Mth.floor(box.maxZ); -+ -+ Level world = entity.level(); -+ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); -+ -+ for (int y = minY; y <= maxY; ++y) { -+ for (int z = minZ; z <= maxZ; ++z) { -+ for (int x = minX; x <= maxX; ++x) { -+ pos.set(x, y, z); -+ BlockState type = world.getBlockStateIfLoaded(pos); -+ if (type != null && !type.isAir()) { -+ return false; -+ } -+ } -+ } -+ } -+ -+ return true; -+ // Paper end - stop using streams, this is already a known fixed problem in Entity#move - } - - @Override -@@ -1387,7 +1421,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - } - -- AABB axisalignedbb = this.player.getBoundingBox(); -+ AABB axisalignedbb = this.player.getBoundingBox(); // Paper - diff on change, should be old AABB - - d6 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above - d7 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above -@@ -1429,6 +1463,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - - this.player.move(MoverType.PLAYER, new Vec3(d6, d7, d8)); - this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move -+ boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... - // Paper start - prevent position desync - if (this.awaitingPositionFromClient != null) { - return; // ... thanks Mojang for letting move calls teleport across dimensions. -@@ -1459,7 +1494,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - - // Paper start - Add fail move event -- boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2)); -+ // Paper start - optimise out extra getCubes -+ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly; -+ this.player.absMoveTo(d0, d1, d2, f, f1); // prevent desync by tping to the set position, dropped for unknown reasons by mojang -+ if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) { -+ AABB newBox = this.player.getBoundingBox(); -+ if (didCollide || !axisalignedbb.equals(newBox)) { -+ // note: only call after setLocation, or else getBoundingBox is wrong -+ teleportBack = this.hasNewCollision(worldserver, this.player, axisalignedbb, newBox); -+ } // else: no collision at all detected, why do we care? -+ } -+ // Paper end - optimise out extra getCubes - if (teleportBack) { - io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK, - toX, toY, toZ, toYaw, toPitch, false); -@@ -1570,7 +1615,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - - private boolean updateAwaitingTeleport() { - if (this.awaitingPositionFromClient != null) { -- if (this.tickCount - this.awaitingTeleportTime > 20) { -+ if (false && this.tickCount - this.awaitingTeleportTime > 20) { // Paper - this will greatly screw with clients with > 1000ms RTT - this.awaitingTeleportTime = this.tickCount; - this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); - } -@@ -1583,6 +1628,33 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - } - -+ // Paper start - optimise out extra getCubes -+ private boolean hasNewCollision(final ServerLevel world, final Entity entity, final AABB oldBox, final AABB newBox) { -+ final List collisionsBB = new java.util.ArrayList<>(); -+ final List collisionsVoxel = new java.util.ArrayList<>(); -+ io.papermc.paper.util.CollisionUtil.getCollisions( -+ world, entity, newBox, collisionsVoxel, collisionsBB, -+ io.papermc.paper.util.CollisionUtil.COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS | io.papermc.paper.util.CollisionUtil.COLLISION_FLAG_CHECK_BORDER, -+ null, null -+ ); -+ -+ for (int i = 0, len = collisionsBB.size(); i < len; ++i) { -+ final AABB box = collisionsBB.get(i); -+ if (!io.papermc.paper.util.CollisionUtil.voxelShapeIntersect(box, oldBox)) { -+ return true; -+ } -+ } -+ -+ for (int i = 0, len = collisionsVoxel.size(); i < len; ++i) { -+ final VoxelShape voxel = collisionsVoxel.get(i); -+ if (!io.papermc.paper.util.CollisionUtil.voxelShapeIntersectNoEmpty(voxel, oldBox)) { -+ return true; -+ } -+ } -+ -+ return false; -+ } -+ // Paper end - optimise out extra getCubes - private boolean isPlayerCollidingWithAnythingNew(LevelReader world, AABB box, double newX, double newY, double newZ) { - AABB axisalignedbb1 = this.player.getBoundingBox().move(newX - this.player.getX(), newY - this.player.getY(), newZ - this.player.getZ()); - Iterable iterable = world.getCollisions(this.player, axisalignedbb1.deflate(9.999999747378752E-6D)); diff --git a/patches/unapplied-old/server/1036-Optimise-nearby-player-retrieval.patch b/patches/unapplied-old/server/1036-Optimise-nearby-player-retrieval.patch deleted file mode 100644 index eae5d781cc..0000000000 --- a/patches/unapplied-old/server/1036-Optimise-nearby-player-retrieval.patch +++ /dev/null @@ -1,228 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Spottedleaf -Date: Sat, 23 Sep 2023 23:15:52 -0700 -Subject: [PATCH] Optimise nearby player retrieval - -Instead of searching/testing every player online on the server, -we can instead use the nearby player tracking system to reduce -the number of tests per search. - -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index d4376ed215d97066a21e462fae2a0e25ad8a16a1..aab652174a8175765cad548f7c61ce353ca74803 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -581,6 +581,115 @@ public class ServerLevel extends Level implements WorldGenLevel { - this.lagCompensationTick = (System.nanoTime() - net.minecraft.server.MinecraftServer.SERVER_INIT) / (java.util.concurrent.TimeUnit.MILLISECONDS.toNanos(50L)); - } - // Paper end - lag compensation -+ // Paper start - optimise nearby player retrieval -+ @Override -+ public java.util.List getNearbyPlayers(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, -+ net.minecraft.world.entity.LivingEntity entity, -+ net.minecraft.world.phys.AABB box) { -+ return this.getNearbyEntities(Player.class, targetPredicate, entity, box); -+ } -+ -+ @Override -+ public Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { -+ if (maxDistance > 0.0D) { -+ io.papermc.paper.util.player.NearbyPlayers players = this.chunkSource.chunkMap.getNearbyPlayers(); -+ -+ com.destroystokyo.paper.util.maplist.ReferenceList nearby = players.getPlayersByBlock( -+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(x), -+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(z), -+ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL -+ ); -+ -+ if (nearby == null) { -+ return null; -+ } -+ -+ ServerPlayer nearest = null; -+ double nearestDist = maxDistance * maxDistance; -+ Object[] rawData = nearby.getRawData(); -+ for (int i = 0, len = nearby.size(); i < len; ++i) { -+ ServerPlayer player = (ServerPlayer)rawData[i]; -+ double dist = player.distanceToSqr(x, y, z); -+ if (dist >= nearestDist) { -+ continue; -+ } -+ -+ if (targetPredicate == null || targetPredicate.test(player)) { -+ nearest = player; -+ nearestDist = dist; -+ } -+ } -+ -+ return nearest; -+ } else { -+ ServerPlayer nearest = null; -+ double nearestDist = Double.MAX_VALUE; -+ -+ for (ServerPlayer player : this.players()) { -+ double dist = player.distanceToSqr(x, y, z); -+ if (dist >= nearestDist) { -+ continue; -+ } -+ -+ if (targetPredicate == null || targetPredicate.test(player)) { -+ nearest = player; -+ nearestDist = dist; -+ } -+ } -+ -+ return nearest; -+ } -+ } -+ -+ @Override -+ public Player getNearestPlayer(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, LivingEntity entity) { -+ return this.getNearestPlayer(targetPredicate, entity, entity.getX(), entity.getY(), entity.getZ()); -+ } -+ -+ @Override -+ public Player getNearestPlayer(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, LivingEntity entity, -+ double x, double y, double z) { -+ double range = targetPredicate.range; -+ if (range > 0.0D) { -+ io.papermc.paper.util.player.NearbyPlayers players = this.chunkSource.chunkMap.getNearbyPlayers(); -+ -+ com.destroystokyo.paper.util.maplist.ReferenceList nearby = players.getPlayersByBlock( -+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(x), -+ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(z), -+ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL -+ ); -+ -+ if (nearby == null) { -+ return null; -+ } -+ -+ ServerPlayer nearest = null; -+ double nearestDist = Double.MAX_VALUE; -+ Object[] rawData = nearby.getRawData(); -+ for (int i = 0, len = nearby.size(); i < len; ++i) { -+ ServerPlayer player = (ServerPlayer)rawData[i]; -+ double dist = player.distanceToSqr(x, y, z); -+ if (dist >= nearestDist) { -+ continue; -+ } -+ -+ if (targetPredicate.test(entity, player)) { -+ nearest = player; -+ nearestDist = dist; -+ } -+ } -+ -+ return nearest; -+ } else { -+ return this.getNearestEntity(this.players(), targetPredicate, entity, x, y, z); -+ } -+ } -+ -+ @Nullable -+ public Player getNearestPlayer(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, double x, double y, double z) { -+ return this.getNearestPlayer(targetPredicate, null, x, y, z); -+ } -+ // Paper end - optimise nearby player retrieval - - // Add env and gen to constructor, IWorldDataServer -> WorldDataServer - public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { -diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -index 2e887e426dcd79e2dda401f127d0e01ca537e80e..65cd42ce9f553e0aa5bf248bdbf902f9d1f55460 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java -@@ -21,17 +21,50 @@ public class PlayerSensor extends Sensor { - - @Override - protected void doTick(ServerLevel world, LivingEntity entity) { -- List list = world.players() -- .stream() -- .filter(EntitySelector.NO_SPECTATORS) -- .filter(player -> entity.closerThan(player, 16.0)) -- .sorted(Comparator.comparingDouble(entity::distanceToSqr)) -- .collect(Collectors.toList()); -+ // Paper start - Perf: optimise nearby player retrieval & remove streams from hot code -+ io.papermc.paper.util.player.NearbyPlayers nearbyPlayers = world.chunkSource.chunkMap.getNearbyPlayers(); -+ net.minecraft.world.phys.Vec3 entityPos = entity.position(); -+ com.destroystokyo.paper.util.maplist.ReferenceList nearby = nearbyPlayers.getPlayersByChunk( -+ entity.chunkPosition().x, -+ entity.chunkPosition().z, -+ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL_REALLY_SMALL -+ ); -+ -+ List players = new java.util.ArrayList<>(nearby == null ? 0 : nearby.size()); -+ if (nearby != null) { -+ Object[] rawData = nearby.getRawData(); -+ for (int index = 0, len = nearby.size(); index < len; ++index) { -+ net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) rawData[index]; -+ if (player.isSpectator()) { -+ continue; -+ } -+ if (player.distanceToSqr(entityPos.x, entityPos.y, entityPos.z) >= (16.0 * 16.0)) { -+ continue; -+ } -+ players.add(player); -+ } -+ } -+ players.sort(Comparator.comparingDouble(entity::distanceToSqr)); - Brain brain = entity.getBrain(); -- brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, list); -- List list2 = list.stream().filter(player -> isEntityTargetable(entity, player)).collect(Collectors.toList()); -- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, list2.isEmpty() ? null : list2.get(0)); -- Optional optional = list2.stream().filter(player -> isEntityAttackable(entity, player)).findFirst(); -- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, optional); -+ -+ brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); -+ -+ Player firstTargetable = null; -+ Player firstAttackable = null; -+ for (Player player : players) { -+ if (firstTargetable == null && Sensor.isEntityTargetable(entity, player)) { -+ firstTargetable = player; -+ } -+ if (firstAttackable == null && Sensor.isEntityAttackable(entity, player)) { -+ firstAttackable = player; -+ } -+ -+ if (firstAttackable != null && firstTargetable != null) { -+ break; -+ } -+ } -+ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, firstTargetable); -+ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, Optional.ofNullable(firstAttackable)); -+ // Paper end - Perf: optimise nearby player retrieval & remove streams from hot code - } - } -diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -index aecb0ad814586bfc5e56755ee14379a69388b38c..d2f0c3b26d4beedb49d86e0242d843590d469d02 100644 ---- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -+++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java -@@ -10,7 +10,7 @@ public class TargetingConditions { - public static final TargetingConditions DEFAULT = forCombat(); - private static final double MIN_VISIBILITY_DISTANCE_FOR_INVISIBLE_TARGET = 2.0; - private final boolean isCombat; -- private double range = -1.0; -+ public double range = -1.0; // Paper - public - private boolean checkLineOfSight = true; - private boolean testInvisible = true; - @Nullable -diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java -index 21843501355a0c0c8d594e3e5312e97861c9a777..ea0aee88c7d901034427db201c1b2430f8a1d522 100644 ---- a/src/main/java/net/minecraft/world/level/EntityGetter.java -+++ b/src/main/java/net/minecraft/world/level/EntityGetter.java -@@ -233,9 +233,13 @@ public interface EntityGetter { - T livingEntity = null; - - for (T livingEntity2 : entityList) { -+ // Paper start - optimise nearby player retrieval; move up -+ // don't check entities outside closest range -+ double e = livingEntity2.distanceToSqr(x, y, z); -+ if (d == -1.0 || e < d) { -+ // Paper end - move up - if (targetPredicate.test(entity, livingEntity2)) { -- double e = livingEntity2.distanceToSqr(x, y, z); -- if (d == -1.0 || e < d) { -+ // Paper - optimise nearby player retrieval; move up - d = e; - livingEntity = livingEntity2; - } diff --git a/patches/unapplied/server/1027-Optimise-collision-checking-in-player-move-packet-ha.patch b/patches/unapplied/server/1027-Optimise-collision-checking-in-player-move-packet-ha.patch new file mode 100644 index 0000000000..1e3006e3e6 --- /dev/null +++ b/patches/unapplied/server/1027-Optimise-collision-checking-in-player-move-packet-ha.patch @@ -0,0 +1,170 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Thu, 2 Jul 2020 12:02:43 -0700 +Subject: [PATCH] Optimise collision checking in player move packet handling + +Move collision logic to just the hasNewCollision call instead of getCubes + hasNewCollision + +CHECK ME + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 7796e191747be545e744564a2b0b65790f69114d..2b94b2dc3f29e7005b1a30c83f4a68e1263780b4 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -572,7 +572,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + return; + } + +- boolean flag = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); ++ AABB oldBox = entity.getBoundingBox(); // Paper - copy from player movement packet + + d6 = d3 - this.vehicleLastGoodX; // Paper - diff on change, used for checking large move vectors above + d7 = d4 - this.vehicleLastGoodY - 1.0E-6D; // Paper - diff on change, used for checking large move vectors above +@@ -588,6 +588,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + } + + entity.move(MoverType.PLAYER, new Vec3(d6, d7, d8)); ++ boolean didCollide = toX != entity.getX() || toY != entity.getY() || toZ != entity.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... + double d11 = d7; + + d6 = d3 - entity.getX(); +@@ -601,15 +602,23 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + boolean flag2 = false; + + if (d10 > org.spigotmc.SpigotConfig.movedWronglyThreshold) { // Spigot +- flag2 = true; ++ flag2 = true; // Paper - diff on change, this should be moved wrongly + ServerGamePacketListenerImpl.LOGGER.warn("{} (vehicle of {}) moved wrongly! {}", new Object[]{entity.getName().getString(), this.player.getName().getString(), Math.sqrt(d10)}); + } + + entity.absMoveTo(d3, d4, d5, f, f1); + this.player.absMoveTo(d3, d4, d5, this.player.getYRot(), this.player.getXRot()); // CraftBukkit +- boolean flag3 = worldserver.noCollision(entity, entity.getBoundingBox().deflate(0.0625D)); + +- if (flag && (flag2 || !flag3)) { ++ // Paper start - optimise out extra getCubes ++ boolean teleportBack = flag2; // violating this is always a fail ++ if (!teleportBack) { ++ // note: only call after setLocation, or else getBoundingBox is wrong ++ AABB newBox = entity.getBoundingBox(); ++ if (didCollide || !oldBox.equals(newBox)) { ++ teleportBack = this.hasNewCollision(worldserver, entity, oldBox, newBox); ++ } // else: no collision at all detected, why do we care? ++ } ++ if (teleportBack) { // Paper end - optimise out extra getCubes + entity.absMoveTo(d0, d1, d2, f, f1); + this.player.absMoveTo(d0, d1, d2, this.player.getYRot(), this.player.getXRot()); // CraftBukkit + this.send(new ClientboundMoveVehiclePacket(entity)); +@@ -691,7 +700,32 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + } + + private boolean noBlocksAround(Entity entity) { +- return entity.level().getBlockStates(entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D)).allMatch(BlockBehaviour.BlockStateBase::isAir); ++ // Paper start - stop using streams, this is already a known fixed problem in Entity#move ++ AABB box = entity.getBoundingBox().inflate(0.0625D).expandTowards(0.0D, -0.55D, 0.0D); ++ int minX = Mth.floor(box.minX); ++ int minY = Mth.floor(box.minY); ++ int minZ = Mth.floor(box.minZ); ++ int maxX = Mth.floor(box.maxX); ++ int maxY = Mth.floor(box.maxY); ++ int maxZ = Mth.floor(box.maxZ); ++ ++ Level world = entity.level(); ++ BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos(); ++ ++ for (int y = minY; y <= maxY; ++y) { ++ for (int z = minZ; z <= maxZ; ++z) { ++ for (int x = minX; x <= maxX; ++x) { ++ pos.set(x, y, z); ++ BlockState type = world.getBlockStateIfLoaded(pos); ++ if (type != null && !type.isAir()) { ++ return false; ++ } ++ } ++ } ++ } ++ ++ return true; ++ // Paper end - stop using streams, this is already a known fixed problem in Entity#move + } + + @Override +@@ -1387,7 +1421,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + } + } + +- AABB axisalignedbb = this.player.getBoundingBox(); ++ AABB axisalignedbb = this.player.getBoundingBox(); // Paper - diff on change, should be old AABB + + d6 = d0 - this.lastGoodX; // Paper - diff on change, used for checking large move vectors above + d7 = d1 - this.lastGoodY; // Paper - diff on change, used for checking large move vectors above +@@ -1429,6 +1463,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + + this.player.move(MoverType.PLAYER, new Vec3(d6, d7, d8)); + this.player.onGround = packet.isOnGround(); // CraftBukkit - SPIGOT-5810, SPIGOT-5835, SPIGOT-6828: reset by this.player.move ++ boolean didCollide = toX != this.player.getX() || toY != this.player.getY() || toZ != this.player.getZ(); // Paper - needed here as the difference in Y can be reset - also note: this is only a guess at whether collisions took place, floating point errors can make this true when it shouldn't be... + // Paper start - prevent position desync + if (this.awaitingPositionFromClient != null) { + return; // ... thanks Mojang for letting move calls teleport across dimensions. +@@ -1459,7 +1494,17 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + } + + // Paper start - Add fail move event +- boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && (movedWrongly && worldserver.noCollision(this.player, axisalignedbb) || this.isPlayerCollidingWithAnythingNew(worldserver, axisalignedbb, d0, d1, d2)); ++ // Paper start - optimise out extra getCubes ++ boolean teleportBack = !this.player.noPhysics && !this.player.isSleeping() && movedWrongly; ++ this.player.absMoveTo(d0, d1, d2, f, f1); // prevent desync by tping to the set position, dropped for unknown reasons by mojang ++ if (!this.player.noPhysics && !this.player.isSleeping() && !teleportBack) { ++ AABB newBox = this.player.getBoundingBox(); ++ if (didCollide || !axisalignedbb.equals(newBox)) { ++ // note: only call after setLocation, or else getBoundingBox is wrong ++ teleportBack = this.hasNewCollision(worldserver, this.player, axisalignedbb, newBox); ++ } // else: no collision at all detected, why do we care? ++ } ++ // Paper end - optimise out extra getCubes + if (teleportBack) { + io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.CLIPPED_INTO_BLOCK, + toX, toY, toZ, toYaw, toPitch, false); +@@ -1570,7 +1615,7 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + + private boolean updateAwaitingTeleport() { + if (this.awaitingPositionFromClient != null) { +- if (this.tickCount - this.awaitingTeleportTime > 20) { ++ if (false && this.tickCount - this.awaitingTeleportTime > 20) { // Paper - this will greatly screw with clients with > 1000ms RTT + this.awaitingTeleportTime = this.tickCount; + this.teleport(this.awaitingPositionFromClient.x, this.awaitingPositionFromClient.y, this.awaitingPositionFromClient.z, this.player.getYRot(), this.player.getXRot()); + } +@@ -1583,6 +1628,33 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + } + } + ++ // Paper start - optimise out extra getCubes ++ private boolean hasNewCollision(final ServerLevel world, final Entity entity, final AABB oldBox, final AABB newBox) { ++ final List collisionsBB = new java.util.ArrayList<>(); ++ final List collisionsVoxel = new java.util.ArrayList<>(); ++ io.papermc.paper.util.CollisionUtil.getCollisions( ++ world, entity, newBox, collisionsVoxel, collisionsBB, ++ io.papermc.paper.util.CollisionUtil.COLLISION_FLAG_COLLIDE_WITH_UNLOADED_CHUNKS | io.papermc.paper.util.CollisionUtil.COLLISION_FLAG_CHECK_BORDER, ++ null, null ++ ); ++ ++ for (int i = 0, len = collisionsBB.size(); i < len; ++i) { ++ final AABB box = collisionsBB.get(i); ++ if (!io.papermc.paper.util.CollisionUtil.voxelShapeIntersect(box, oldBox)) { ++ return true; ++ } ++ } ++ ++ for (int i = 0, len = collisionsVoxel.size(); i < len; ++i) { ++ final VoxelShape voxel = collisionsVoxel.get(i); ++ if (!io.papermc.paper.util.CollisionUtil.voxelShapeIntersectNoEmpty(voxel, oldBox)) { ++ return true; ++ } ++ } ++ ++ return false; ++ } ++ // Paper end - optimise out extra getCubes + private boolean isPlayerCollidingWithAnythingNew(LevelReader world, AABB box, double newX, double newY, double newZ) { + AABB axisalignedbb1 = this.player.getBoundingBox().move(newX - this.player.getX(), newY - this.player.getY(), newZ - this.player.getZ()); + Iterable iterable = world.getCollisions(this.player, axisalignedbb1.deflate(9.999999747378752E-6D)); diff --git a/patches/unapplied/server/1036-Optimise-nearby-player-retrieval.patch b/patches/unapplied/server/1036-Optimise-nearby-player-retrieval.patch new file mode 100644 index 0000000000..eae5d781cc --- /dev/null +++ b/patches/unapplied/server/1036-Optimise-nearby-player-retrieval.patch @@ -0,0 +1,228 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf +Date: Sat, 23 Sep 2023 23:15:52 -0700 +Subject: [PATCH] Optimise nearby player retrieval + +Instead of searching/testing every player online on the server, +we can instead use the nearby player tracking system to reduce +the number of tests per search. + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index d4376ed215d97066a21e462fae2a0e25ad8a16a1..aab652174a8175765cad548f7c61ce353ca74803 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -581,6 +581,115 @@ public class ServerLevel extends Level implements WorldGenLevel { + this.lagCompensationTick = (System.nanoTime() - net.minecraft.server.MinecraftServer.SERVER_INIT) / (java.util.concurrent.TimeUnit.MILLISECONDS.toNanos(50L)); + } + // Paper end - lag compensation ++ // Paper start - optimise nearby player retrieval ++ @Override ++ public java.util.List getNearbyPlayers(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, ++ net.minecraft.world.entity.LivingEntity entity, ++ net.minecraft.world.phys.AABB box) { ++ return this.getNearbyEntities(Player.class, targetPredicate, entity, box); ++ } ++ ++ @Override ++ public Player getNearestPlayer(double x, double y, double z, double maxDistance, @Nullable Predicate targetPredicate) { ++ if (maxDistance > 0.0D) { ++ io.papermc.paper.util.player.NearbyPlayers players = this.chunkSource.chunkMap.getNearbyPlayers(); ++ ++ com.destroystokyo.paper.util.maplist.ReferenceList nearby = players.getPlayersByBlock( ++ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(x), ++ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(z), ++ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL ++ ); ++ ++ if (nearby == null) { ++ return null; ++ } ++ ++ ServerPlayer nearest = null; ++ double nearestDist = maxDistance * maxDistance; ++ Object[] rawData = nearby.getRawData(); ++ for (int i = 0, len = nearby.size(); i < len; ++i) { ++ ServerPlayer player = (ServerPlayer)rawData[i]; ++ double dist = player.distanceToSqr(x, y, z); ++ if (dist >= nearestDist) { ++ continue; ++ } ++ ++ if (targetPredicate == null || targetPredicate.test(player)) { ++ nearest = player; ++ nearestDist = dist; ++ } ++ } ++ ++ return nearest; ++ } else { ++ ServerPlayer nearest = null; ++ double nearestDist = Double.MAX_VALUE; ++ ++ for (ServerPlayer player : this.players()) { ++ double dist = player.distanceToSqr(x, y, z); ++ if (dist >= nearestDist) { ++ continue; ++ } ++ ++ if (targetPredicate == null || targetPredicate.test(player)) { ++ nearest = player; ++ nearestDist = dist; ++ } ++ } ++ ++ return nearest; ++ } ++ } ++ ++ @Override ++ public Player getNearestPlayer(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, LivingEntity entity) { ++ return this.getNearestPlayer(targetPredicate, entity, entity.getX(), entity.getY(), entity.getZ()); ++ } ++ ++ @Override ++ public Player getNearestPlayer(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, LivingEntity entity, ++ double x, double y, double z) { ++ double range = targetPredicate.range; ++ if (range > 0.0D) { ++ io.papermc.paper.util.player.NearbyPlayers players = this.chunkSource.chunkMap.getNearbyPlayers(); ++ ++ com.destroystokyo.paper.util.maplist.ReferenceList nearby = players.getPlayersByBlock( ++ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(x), ++ io.papermc.paper.util.CoordinateUtils.getBlockCoordinate(z), ++ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL ++ ); ++ ++ if (nearby == null) { ++ return null; ++ } ++ ++ ServerPlayer nearest = null; ++ double nearestDist = Double.MAX_VALUE; ++ Object[] rawData = nearby.getRawData(); ++ for (int i = 0, len = nearby.size(); i < len; ++i) { ++ ServerPlayer player = (ServerPlayer)rawData[i]; ++ double dist = player.distanceToSqr(x, y, z); ++ if (dist >= nearestDist) { ++ continue; ++ } ++ ++ if (targetPredicate.test(entity, player)) { ++ nearest = player; ++ nearestDist = dist; ++ } ++ } ++ ++ return nearest; ++ } else { ++ return this.getNearestEntity(this.players(), targetPredicate, entity, x, y, z); ++ } ++ } ++ ++ @Nullable ++ public Player getNearestPlayer(net.minecraft.world.entity.ai.targeting.TargetingConditions targetPredicate, double x, double y, double z) { ++ return this.getNearestPlayer(targetPredicate, null, x, y, z); ++ } ++ // Paper end - optimise nearby player retrieval + + // Add env and gen to constructor, IWorldDataServer -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, @Nullable RandomSequences randomsequences, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { +diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +index 2e887e426dcd79e2dda401f127d0e01ca537e80e..65cd42ce9f553e0aa5bf248bdbf902f9d1f55460 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java ++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/PlayerSensor.java +@@ -21,17 +21,50 @@ public class PlayerSensor extends Sensor { + + @Override + protected void doTick(ServerLevel world, LivingEntity entity) { +- List list = world.players() +- .stream() +- .filter(EntitySelector.NO_SPECTATORS) +- .filter(player -> entity.closerThan(player, 16.0)) +- .sorted(Comparator.comparingDouble(entity::distanceToSqr)) +- .collect(Collectors.toList()); ++ // Paper start - Perf: optimise nearby player retrieval & remove streams from hot code ++ io.papermc.paper.util.player.NearbyPlayers nearbyPlayers = world.chunkSource.chunkMap.getNearbyPlayers(); ++ net.minecraft.world.phys.Vec3 entityPos = entity.position(); ++ com.destroystokyo.paper.util.maplist.ReferenceList nearby = nearbyPlayers.getPlayersByChunk( ++ entity.chunkPosition().x, ++ entity.chunkPosition().z, ++ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL_REALLY_SMALL ++ ); ++ ++ List players = new java.util.ArrayList<>(nearby == null ? 0 : nearby.size()); ++ if (nearby != null) { ++ Object[] rawData = nearby.getRawData(); ++ for (int index = 0, len = nearby.size(); index < len; ++index) { ++ net.minecraft.server.level.ServerPlayer player = (net.minecraft.server.level.ServerPlayer) rawData[index]; ++ if (player.isSpectator()) { ++ continue; ++ } ++ if (player.distanceToSqr(entityPos.x, entityPos.y, entityPos.z) >= (16.0 * 16.0)) { ++ continue; ++ } ++ players.add(player); ++ } ++ } ++ players.sort(Comparator.comparingDouble(entity::distanceToSqr)); + Brain brain = entity.getBrain(); +- brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, list); +- List list2 = list.stream().filter(player -> isEntityTargetable(entity, player)).collect(Collectors.toList()); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, list2.isEmpty() ? null : list2.get(0)); +- Optional optional = list2.stream().filter(player -> isEntityAttackable(entity, player)).findFirst(); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, optional); ++ ++ brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, players); ++ ++ Player firstTargetable = null; ++ Player firstAttackable = null; ++ for (Player player : players) { ++ if (firstTargetable == null && Sensor.isEntityTargetable(entity, player)) { ++ firstTargetable = player; ++ } ++ if (firstAttackable == null && Sensor.isEntityAttackable(entity, player)) { ++ firstAttackable = player; ++ } ++ ++ if (firstAttackable != null && firstTargetable != null) { ++ break; ++ } ++ } ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, firstTargetable); ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, Optional.ofNullable(firstAttackable)); ++ // Paper end - Perf: optimise nearby player retrieval & remove streams from hot code + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +index aecb0ad814586bfc5e56755ee14379a69388b38c..d2f0c3b26d4beedb49d86e0242d843590d469d02 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java ++++ b/src/main/java/net/minecraft/world/entity/ai/targeting/TargetingConditions.java +@@ -10,7 +10,7 @@ public class TargetingConditions { + public static final TargetingConditions DEFAULT = forCombat(); + private static final double MIN_VISIBILITY_DISTANCE_FOR_INVISIBLE_TARGET = 2.0; + private final boolean isCombat; +- private double range = -1.0; ++ public double range = -1.0; // Paper - public + private boolean checkLineOfSight = true; + private boolean testInvisible = true; + @Nullable +diff --git a/src/main/java/net/minecraft/world/level/EntityGetter.java b/src/main/java/net/minecraft/world/level/EntityGetter.java +index 21843501355a0c0c8d594e3e5312e97861c9a777..ea0aee88c7d901034427db201c1b2430f8a1d522 100644 +--- a/src/main/java/net/minecraft/world/level/EntityGetter.java ++++ b/src/main/java/net/minecraft/world/level/EntityGetter.java +@@ -233,9 +233,13 @@ public interface EntityGetter { + T livingEntity = null; + + for (T livingEntity2 : entityList) { ++ // Paper start - optimise nearby player retrieval; move up ++ // don't check entities outside closest range ++ double e = livingEntity2.distanceToSqr(x, y, z); ++ if (d == -1.0 || e < d) { ++ // Paper end - move up + if (targetPredicate.test(entity, livingEntity2)) { +- double e = livingEntity2.distanceToSqr(x, y, z); +- if (d == -1.0 || e < d) { ++ // Paper - optimise nearby player retrieval; move up + d = e; + livingEntity = livingEntity2; + } -- cgit v1.2.3