mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-11 09:23:42 +01:00
108 lines
6.1 KiB
Diff
108 lines
6.1 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Bjarne Koll <lynxplay101@gmail.com>
|
||
|
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 7680c269c2fe0cf2a51d0ebeb34624181826d578..49f3b25d28072b61f5cc97260df61df892a58714 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, 9.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, 9.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/NearestLivingEntitySensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java
|
||
|
index 66c90013e52170a657b1a5dbdb99748a19fe55e8..ffd83db0a419ab589e89feeddd3fb038d6ed5839 100644
|
||
|
--- a/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java
|
||
|
+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/NearestLivingEntitySensor.java
|
||
|
@@ -21,9 +21,11 @@ public class NearestLivingEntitySensor extends Sensor<LivingEntity> {
|
||
|
list.sort(Comparator.comparingDouble(entity::distanceToSqr));
|
||
|
Brain<?> brain = entity.getBrain();
|
||
|
brain.setMemory(MemoryModuleType.NEAREST_LIVING_ENTITIES, list);
|
||
|
- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, list.stream().filter((livingEntity2) -> {
|
||
|
- return isEntityTargetable(entity, livingEntity2);
|
||
|
- }).collect(Collectors.toList()));
|
||
|
+ // Paper start - remove streams in favour of lists
|
||
|
+ List<LivingEntity> visibleMobs = new java.util.ArrayList<>(list);
|
||
|
+ visibleMobs.removeIf(otherEntityLiving -> !Sensor.isEntityTargetable(entity, otherEntityLiving));
|
||
|
+ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_LIVING_ENTITIES, visibleMobs);
|
||
|
+ // Paper end
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
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 b51574548b370f8a86d27835e9888ce1cd1d18be..457ea75137b8b02dc32bf1769ae8d57c470da470 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((serverPlayer) -> {
|
||
|
- return entity.closerThan(serverPlayer, 16.0D);
|
||
|
- }).sorted(Comparator.comparingDouble(entity::distanceToSqr)).collect(Collectors.toList());
|
||
|
+ // Paper start - remove streams in favour of lists
|
||
|
+ List<Player> players = new java.util.ArrayList<>(world.players());
|
||
|
+ players.removeIf(player -> !EntitySelector.NO_SPECTATORS.test(player) || !entity.closerThan(player, 16.0D)); // Paper - removeIf only re-allocates once compared to iterator
|
||
|
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
|
||
|
}
|
||
|
}
|