From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Spottedleaf 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 extends Behavior { @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>> entries = this.behaviors.entries; + for (int i = 0; i < entries.size(); i++) { + ShufflingList.WeightedEntry> entry = entries.get(i); + Behavior 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 extends Behavior { @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>> entries = this.behaviors.entries; + for (int i = 0; i < entries.size(); i++) { + ShufflingList.WeightedEntry> entry = entries.get(i); + Behavior 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>> entries = this.behaviors.entries; + for (int i = 0; i < entries.size(); i++) { + ShufflingList.WeightedEntry> entry = entries.get(i); + Behavior 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 extends Behavior { public static enum RunningPolicy { RUN_ONE { @Override - public void apply(Stream> 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 void apply(List>> tasks, ServerLevel world, E entity, long time) { + for (int i = 0; i < tasks.size(); i++) { + ShufflingList.WeightedEntry> task = tasks.get(i); + Behavior behavior = task.getData(); + if (behavior.getStatus() == Status.STOPPED && behavior.tryStart(world, entity, time)) { + break; + } + } + // Paper end - remove streams } }, TRY_ALL { @Override - public void apply(Stream> 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 void apply(List>> tasks, ServerLevel world, E entity, long time) { + for (int i = 0; i < tasks.size(); i++) { + ShufflingList.WeightedEntry> task = tasks.get(i); + Behavior behavior = task.getData(); + if (behavior.getStatus() == Status.STOPPED) { + behavior.tryStart(world, entity, time); + } + } + // Paper end - remove streams } }; - public abstract void apply(Stream> tasks, ServerLevel world, E entity, long time); + public abstract void apply(List>> 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 { - protected final List> entries; + public final List> 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 { protected void doTick(ServerLevel world, Mob entity) { Brain brain = entity.getBrain(); List 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 { @Override protected void doTick(ServerLevel world, LivingEntity entity) { - List 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 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 } }