aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0555-Remove-streams-from-SensorNearest.patch
diff options
context:
space:
mode:
authorSpottedleaf <[email protected]>2023-09-23 22:10:40 -0700
committerSpottedleaf <[email protected]>2023-09-23 22:31:42 -0700
commit84556f3cdae93799d34df9b9ad495fe59061b060 (patch)
treed78ff563dc71f3427eb486cf966edb7fbf40fcf0 /patches/server/0555-Remove-streams-from-SensorNearest.patch
parent38dc3b25d8d7ff5a14fbcc70ef16541ed396db4f (diff)
downloadPaper-84556f3cdae93799d34df9b9ad495fe59061b060.tar.gz
Paper-84556f3cdae93799d34df9b9ad495fe59061b060.zip
Add lag compensation for breaking blocks
Diffstat (limited to 'patches/server/0555-Remove-streams-from-SensorNearest.patch')
-rw-r--r--patches/server/0555-Remove-streams-from-SensorNearest.patch88
1 files changed, 88 insertions, 0 deletions
diff --git a/patches/server/0555-Remove-streams-from-SensorNearest.patch b/patches/server/0555-Remove-streams-from-SensorNearest.patch
new file mode 100644
index 0000000000..a7ae5d1a98
--- /dev/null
+++ b/patches/server/0555-Remove-streams-from-SensorNearest.patch
@@ -0,0 +1,88 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Bjarne Koll <[email protected]>
+Date: Wed, 3 Mar 2021 12:48:48 +0100
+Subject: [PATCH] Remove streams from SensorNearest
+
+The behavioural nearby sensors are validated every tick on the entities
+that registered the respective sensors and are therefore a good subject
+to performance improvements.
+
+More specifically this commit replaces the Stream#filter usage with
+ArrayList#removeIf as the removeIf method on an array list is heavily
+optimized towards a single internal array re-allocation without any
+further overhead on the removeIf call.
+
+The only negative of this change is the rather agressive diff these
+patches introduce as the methods are basically being reimplemented
+compared to the previous stream-based implementation.
+
+See: https://nipafx.dev/java-stream-performance/
+
+diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java
+index a41c3365db8e9999b686f5bf4bd888458cee43a5..1dfcc5cba6ffb463acf161a23fff1ca452184290 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java
++++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestItemSensor.java
+@@ -28,11 +28,15 @@ public class NearestItemSensor extends Sensor<Mob> {
+ return true;
+ });
+ list.sort(Comparator.comparingDouble(entity::distanceToSqr));
+- Optional<ItemEntity> optional = list.stream().filter((itemEntity) -> {
+- return entity.wantsToPickUp(itemEntity.getItem());
+- }).filter((itemEntity) -> {
+- return itemEntity.closerThan(entity, 32.0D);
+- }).filter(entity::hasLineOfSight).findFirst();
+- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, optional);
++ // Paper start - remove streams in favour of lists
++ ItemEntity nearest = null;
++ for (ItemEntity entityItem : list) {
++ if (entity.wantsToPickUp(entityItem.getItem()) && entityItem.closerThan(entity, 32.0D) && entity.hasLineOfSight(entityItem)) {
++ nearest = entityItem;
++ break;
++ }
++ }
++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_WANTED_ITEM, Optional.ofNullable(nearest));
++ // Paper end
+ }
+ }
+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 ed1b95ec694b0fe8b647964b18b8c33707fc0b47..312775d0430f793720211dc29bb293503e799d11 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,18 +21,25 @@ public class PlayerSensor extends Sensor<LivingEntity> {
+
+ @Override
+ protected void doTick(ServerLevel world, LivingEntity entity) {
+- List<Player> list = world.players().stream().filter(EntitySelector.NO_SPECTATORS).filter((player) -> {
+- return entity.closerThan(player, 16.0D);
+- }).sorted(Comparator.comparingDouble(entity::distanceToSqr)).collect(Collectors.toList());
++ List<Player> players = new java.util.ArrayList<>(world.players());
++ players.removeIf(player -> !EntitySelector.NO_SPECTATORS.test(player) || !entity.closerThan(player, 16.0D));
++ players.sort(Comparator.comparingDouble(entity::distanceTo));
+ Brain<?> brain = entity.getBrain();
+- brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, list);
+- List<Player> list2 = list.stream().filter((player) -> {
+- return isEntityTargetable(entity, player);
+- }).collect(Collectors.toList());
+- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, list2.isEmpty() ? null : list2.get(0));
+- Optional<Player> optional = list2.stream().filter((player) -> {
+- return isEntityAttackable(entity, player);
+- }).findFirst();
+- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, optional);
++
++ brain.setMemory(MemoryModuleType.NEAREST_PLAYERS, players);
++
++ Player nearest = null, nearestTargetable = null;
++ for (Player player : players) {
++ if (Sensor.isEntityTargetable(entity, player)) {
++ if (nearest == null) nearest = player;
++ if (Sensor.isEntityAttackable(entity, player)) {
++ nearestTargetable = player;
++ break; // Both variables are assigned, no reason to loop further
++ }
++ }
++ }
++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest);
++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, nearestTargetable);
++ // Paper end
+ }
+ }