diff options
Diffstat (limited to 'patches/server/0774-Remove-streams-for-villager-AI.patch')
-rw-r--r-- | patches/server/0774-Remove-streams-for-villager-AI.patch | 220 |
1 files changed, 220 insertions, 0 deletions
diff --git a/patches/server/0774-Remove-streams-for-villager-AI.patch b/patches/server/0774-Remove-streams-for-villager-AI.patch new file mode 100644 index 0000000000..8257c2de40 --- /dev/null +++ b/patches/server/0774-Remove-streams-for-villager-AI.patch @@ -0,0 +1,220 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Spottedleaf <[email protected]> +Date: Thu, 27 Aug 2020 20:51:40 -0700 +Subject: [PATCH] Remove streams for villager AI + + +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +index e644bdd3a6f7c09a44149da03587b796674fa568..c67c448e0d8bdd788b94189651304110694c95da 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/GateBehavior.java +@@ -30,11 +30,19 @@ public class GateBehavior<E extends LivingEntity> extends Behavior<E> { + + @Override + protected boolean canStillUse(ServerLevel world, E entity, long time) { +- return this.behaviors.stream().filter((task) -> { +- return task.getStatus() == Behavior.Status.RUNNING; +- }).anyMatch((task) -> { +- return task.canStillUse(world, entity, time); +- }); ++ // Paper start - remove streams ++ List<ShufflingList.WeightedEntry<Behavior<? super E>>> entries = this.behaviors.entries; ++ for (int i = 0; i < entries.size(); i++) { ++ ShufflingList.WeightedEntry<Behavior<? super E>> entry = entries.get(i); ++ Behavior<? super E> behavior = entry.getData(); ++ if (behavior.getStatus() == Status.RUNNING) { ++ if (behavior.canStillUse(world, entity, time)) { ++ return true; ++ } ++ } ++ } ++ return false; ++ // Paper end - remove streams + } + + @Override +@@ -45,25 +53,35 @@ public class GateBehavior<E extends LivingEntity> extends Behavior<E> { + @Override + protected void start(ServerLevel world, E entity, long time) { + this.orderPolicy.apply(this.behaviors); +- this.runningPolicy.apply(this.behaviors.stream(), world, entity, time); ++ this.runningPolicy.apply(this.behaviors.entries, world, entity, time); // Paper - remove streams + } + + @Override + protected void tick(ServerLevel world, E entity, long time) { +- this.behaviors.stream().filter((task) -> { +- return task.getStatus() == Behavior.Status.RUNNING; +- }).forEach((task) -> { +- task.tickOrStop(world, entity, time); +- }); ++ // Paper start - remove streams ++ List<ShufflingList.WeightedEntry<Behavior<? super E>>> entries = this.behaviors.entries; ++ for (int i = 0; i < entries.size(); i++) { ++ ShufflingList.WeightedEntry<Behavior<? super E>> entry = entries.get(i); ++ Behavior<? super E> behavior = entry.getData(); ++ if (behavior.getStatus() == Status.RUNNING) { ++ behavior.tickOrStop(world, entity, time); ++ } ++ } ++ // Paper end - remove streams + } + + @Override + protected void stop(ServerLevel world, E entity, long time) { +- this.behaviors.stream().filter((task) -> { +- return task.getStatus() == Behavior.Status.RUNNING; +- }).forEach((task) -> { +- task.doStop(world, entity, time); +- }); ++ // Paper start - remove streams ++ List<ShufflingList.WeightedEntry<Behavior<? super E>>> entries = this.behaviors.entries; ++ for (int i = 0; i < entries.size(); i++) { ++ ShufflingList.WeightedEntry<Behavior<? super E>> entry = entries.get(i); ++ Behavior<? super E> behavior = entry.getData(); ++ if (behavior.getStatus() == Status.RUNNING) { ++ behavior.doStop(world, entity, time); ++ } ++ } ++ // Paper end - remove streams + this.exitErasedMemories.forEach(entity.getBrain()::eraseMemory); + } + +@@ -94,25 +112,33 @@ public class GateBehavior<E extends LivingEntity> extends Behavior<E> { + public static enum RunningPolicy { + RUN_ONE { + @Override +- public <E extends LivingEntity> void apply(Stream<Behavior<? super E>> tasks, ServerLevel world, E entity, long time) { +- tasks.filter((task) -> { +- return task.getStatus() == Behavior.Status.STOPPED; +- }).filter((task) -> { +- return task.tryStart(world, entity, time); +- }).findFirst(); ++ // Paper start - remove streams ++ public <E extends LivingEntity> void apply(List<ShufflingList.WeightedEntry<Behavior<? super E>>> tasks, ServerLevel world, E entity, long time) { ++ for (int i = 0; i < tasks.size(); i++) { ++ ShufflingList.WeightedEntry<Behavior<? super E>> task = tasks.get(i); ++ Behavior<? super E> behavior = task.getData(); ++ if (behavior.getStatus() == Status.STOPPED && behavior.tryStart(world, entity, time)) { ++ break; ++ } ++ } ++ // Paper end - remove streams + } + }, + TRY_ALL { + @Override +- public <E extends LivingEntity> void apply(Stream<Behavior<? super E>> tasks, ServerLevel world, E entity, long time) { +- tasks.filter((task) -> { +- return task.getStatus() == Behavior.Status.STOPPED; +- }).forEach((task) -> { +- task.tryStart(world, entity, time); +- }); ++ // Paper start - remove streams ++ public <E extends LivingEntity> void apply(List<ShufflingList.WeightedEntry<Behavior<? super E>>> tasks, ServerLevel world, E entity, long time) { ++ for (int i = 0; i < tasks.size(); i++) { ++ ShufflingList.WeightedEntry<Behavior<? super E>> task = tasks.get(i); ++ Behavior<? super E> behavior = task.getData(); ++ if (behavior.getStatus() == Status.STOPPED) { ++ behavior.tryStart(world, entity, time); ++ } ++ } ++ // Paper end - remove streams + } + }; + +- public abstract <E extends LivingEntity> void apply(Stream<Behavior<? super E>> tasks, ServerLevel world, E entity, long time); ++ public abstract <E extends LivingEntity> void apply(List<ShufflingList.WeightedEntry<Behavior<? super E>>> tasks, ServerLevel world, E entity, long time); // Paper - remove streams + } + } +diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java +index 1bc34453933bc7590af45a5559a4fc75eb3e0c5c..204ca4fbd89bdadd902529f1f191df46fce3cace 100644 +--- a/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java ++++ b/src/main/java/net/minecraft/world/entity/ai/behavior/ShufflingList.java +@@ -12,7 +12,7 @@ import java.util.Random; + import java.util.stream.Stream; + + public class ShufflingList<U> { +- protected final List<ShufflingList.WeightedEntry<U>> entries; ++ public final List<ShufflingList.WeightedEntry<U>> entries; // Paper - public + private final Random random = new Random(); + private final boolean isUnsafe; // Paper + +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 49f3b25d28072b61f5cc97260df61df892a58714..71f2692c83feafbb31f45427e6c738cb3881c82c 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 +@@ -25,17 +25,20 @@ public class NearestItemSensor extends Sensor<Mob> { + protected void doTick(ServerLevel world, Mob entity) { + Brain<?> brain = entity.getBrain(); + List<ItemEntity> list = world.getEntitiesOfClass(ItemEntity.class, entity.getBoundingBox().inflate(8.0D, 4.0D, 8.0D), (itemEntity) -> { +- return true; ++ return itemEntity.closerThan(entity, 9.0D) && entity.wantsToPickUp(itemEntity.getItem()); // Paper - move predicate into getEntities + }); +- list.sort(Comparator.comparingDouble(entity::distanceToSqr)); ++ list.sort((e1, e2) -> Double.compare(entity.distanceToSqr(e1), entity.distanceToSqr(e2))); // better to take the sort perf hit than using line of sight more than we need to. ++ // Paper start - remove streams + // 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)) { ++ for (int i = 0; i < list.size(); i++) { ++ ItemEntity entityItem = list.get(i); ++ if (entity.hasLineOfSight(entityItem)) { + nearest = entityItem; + break; + } + } ++ // Paper end - remove streams + 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 312775d0430f793720211dc29bb293503e799d11..75d9c4f011b5a97def215784c92bb57bbb35d06b 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,25 +21,30 @@ public class PlayerSensor extends Sensor<LivingEntity> { + + @Override + protected void doTick(ServerLevel world, LivingEntity entity) { +- 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)); ++ // Paper start - remove streams ++ List<Player> players = (List)world.getNearbyPlayers(entity, entity.getX(), entity.getY(), entity.getZ(), 16.0D, EntitySelector.NO_SPECTATORS); ++ players.sort((e1, e2) -> Double.compare(entity.distanceToSqr(e1), entity.distanceToSqr(e2))); + Brain<?> brain = entity.getBrain(); + + 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 +- } ++ Player firstTargetable = null; ++ Player firstAttackable = null; ++ for (int index = 0, len = players.size(); index < len; ++index) { ++ Player player = players.get(index); ++ if (firstTargetable == null && isEntityTargetable(entity, player)) { ++ firstTargetable = player; ++ } ++ if (firstAttackable == null && isEntityAttackable(entity, player)) { ++ firstAttackable = player; ++ } ++ ++ if (firstAttackable != null && firstTargetable != null) { ++ break; + } + } +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, nearest); +- brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, nearestTargetable); +- // Paper end ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_PLAYER, firstTargetable); ++ brain.setMemory(MemoryModuleType.NEAREST_VISIBLE_ATTACKABLE_PLAYER, Optional.ofNullable(firstAttackable)); ++ // Paper end - remove streams + } + } |