mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-26 20:46:59 +01:00
211 lines
12 KiB
Diff
211 lines
12 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
|
|
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 b45c4f50705f80163d44d9e588f86a5770f5be38..64165fed12c6c76d4ceb36d69f47a1235c1e8e44 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
|
|
@@ -52,7 +52,7 @@ public class GateBehavior<E extends LivingEntity> implements BehaviorControl<E>
|
|
if (this.hasRequiredMemories(entity)) {
|
|
this.status = Behavior.Status.RUNNING;
|
|
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
|
|
return true;
|
|
} else {
|
|
return false;
|
|
@@ -61,11 +61,13 @@ public class GateBehavior<E extends LivingEntity> implements BehaviorControl<E>
|
|
|
|
@Override
|
|
public final void tickOrStop(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
|
|
+ for (BehaviorControl<? super E> task : this.behaviors) {
|
|
+ if (task.getStatus() == Behavior.Status.RUNNING) {
|
|
+ task.tickOrStop(world, entity, time);
|
|
+ }
|
|
+ }
|
|
+ // Paper end - Remove streams
|
|
if (this.behaviors.stream().noneMatch((task) -> {
|
|
return task.getStatus() == Behavior.Status.RUNNING;
|
|
})) {
|
|
@@ -77,11 +79,13 @@ public class GateBehavior<E extends LivingEntity> implements BehaviorControl<E>
|
|
@Override
|
|
public final void doStop(ServerLevel world, E entity, long time) {
|
|
this.status = Behavior.Status.STOPPED;
|
|
- this.behaviors.stream().filter((task) -> {
|
|
- return task.getStatus() == Behavior.Status.RUNNING;
|
|
- }).forEach((task) -> {
|
|
- task.doStop(world, entity, time);
|
|
- });
|
|
+ // Paper start - Remove streams
|
|
+ for (BehaviorControl<? super E> behavior : this.behaviors) {
|
|
+ if (behavior.getStatus() == Behavior.Status.RUNNING) {
|
|
+ behavior.doStop(world, entity, time);
|
|
+ }
|
|
+ }
|
|
+ // Paper end - Remove streams
|
|
this.exitErasedMemories.forEach(entity.getBrain()::eraseMemory);
|
|
}
|
|
|
|
@@ -117,25 +121,31 @@ public class GateBehavior<E extends LivingEntity> implements BehaviorControl<E>
|
|
public static enum RunningPolicy {
|
|
RUN_ONE {
|
|
@Override
|
|
- public <E extends LivingEntity> void apply(Stream<BehaviorControl<? 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<BehaviorControl<? super E>>> tasks, ServerLevel world, E entity, long time) {
|
|
+ for (ShufflingList.WeightedEntry<BehaviorControl<? super E>> task : tasks) {
|
|
+ final BehaviorControl<? super E> behavior = task.getData();
|
|
+ if (behavior.getStatus() == Behavior.Status.STOPPED && behavior.tryStart(world, entity, time)) {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ // Paper end - Remove streams
|
|
}
|
|
},
|
|
TRY_ALL {
|
|
@Override
|
|
- public <E extends LivingEntity> void apply(Stream<BehaviorControl<? 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<BehaviorControl<? super E>>> tasks, ServerLevel world, E entity, long time) {
|
|
+ for (ShufflingList.WeightedEntry<BehaviorControl<? super E>> task : tasks) {
|
|
+ final BehaviorControl<? super E> behavior = task.getData();
|
|
+ if (behavior.getStatus() == Behavior.Status.STOPPED) {
|
|
+ behavior.tryStart(world, entity, time);
|
|
+ }
|
|
+ }
|
|
+ // Paper end - Remove streams
|
|
}
|
|
};
|
|
|
|
- public abstract <E extends LivingEntity> void apply(Stream<BehaviorControl<? super E>> tasks, ServerLevel world, E entity, long time);
|
|
+ public abstract <E extends LivingEntity> void apply(List<ShufflingList.WeightedEntry<BehaviorControl<? 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 731ef21dbbd25d6924717de42f4569a9b5935643..fe3ab3d388f0481fb0db06b7f730f868dbf8e8a5 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
|
|
@@ -14,7 +14,7 @@ import java.util.stream.Stream;
|
|
import net.minecraft.util.RandomSource;
|
|
|
|
public class ShufflingList<U> implements Iterable<U> {
|
|
- protected final List<ShufflingList.WeightedEntry<U>> entries;
|
|
+ public final List<ShufflingList.WeightedEntry<U>> entries; // Paper - public
|
|
private final RandomSource random = RandomSource.create();
|
|
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 1dfcc5cba6ffb463acf161a23fff1ca452184290..9958690971a2f14bfdb8841e466fa783452c5b0c 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,13 +25,16 @@ 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(32.0D, 16.0D, 32.0D), (itemEntity) -> {
|
|
- return true;
|
|
+ return itemEntity.closerThan(entity, MAX_DISTANCE_TO_WANTED_ITEM) && 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, 32.0D) && entity.hasLineOfSight(entityItem)) {
|
|
+ for (int i = 0; i < list.size(); i++) {
|
|
+ ItemEntity entityItem = list.get(i);
|
|
+ if (entity.hasLineOfSight(entityItem)) {
|
|
+ // Paper end - Remove streams
|
|
nearest = entityItem;
|
|
break;
|
|
}
|
|
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..9c6b1027dcda0ff4fd357d3cb70fcf5b9f6127a0 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,51 @@ 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
|
|
+ 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<net.minecraft.server.level.ServerPlayer> nearby = nearbyPlayers.getPlayersByChunk(
|
|
+ entity.chunkPosition().x,
|
|
+ entity.chunkPosition().z,
|
|
+ io.papermc.paper.util.player.NearbyPlayers.NearbyMapType.GENERAL_REALLY_SMALL
|
|
+ );
|
|
+
|
|
+ List<Player> 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)player);
|
|
+ }
|
|
+ }
|
|
+ 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
|
|
}
|
|
}
|