2020-04-12 02:15:22 +02:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <spottedleaf@spottedleaf.dev>
Date: Mon, 6 Apr 2020 17:53:29 -0700
Subject: [PATCH] Remove streams from Mob AI System
The streams hurt performance and allocate tons of garbage, so
replace them with the standard iterator.
Also optimise the stream.anyMatch statement to move to a bitset
where we can replace the call with a single bitwise operation.
2021-03-16 08:19:45 +01:00
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java
2020-05-06 11:48:49 +02:00
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
2021-03-16 08:19:45 +01:00
--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java
2020-04-12 02:15:22 +02:00
@@ -0,0 +0,0 @@
2021-03-16 08:19:45 +01:00
package net.minecraft.world.entity.ai.goal;
2020-04-12 02:15:22 +02:00
+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector
import java.util.EnumSet;
public abstract class PathfinderGoal {
- private final EnumSet<PathfinderGoal.Type> a = EnumSet.noneOf(PathfinderGoal.Type.class);
2020-05-02 03:44:06 +02:00
+ private final EnumSet<PathfinderGoal.Type> a = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be.
2020-04-12 02:15:22 +02:00
+ private final OptimizedSmallEnumSet<Type> goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector
public PathfinderGoal() {}
@@ -0,0 +0,0 @@ public abstract class PathfinderGoal {
public void e() {}
public void a(EnumSet<PathfinderGoal.Type> enumset) {
- this.a.clear();
- this.a.addAll(enumset);
+ // Paper start - remove streams from pathfindergoalselector
+ this.goalTypes.clear();
+ this.goalTypes.addAllUnchecked(enumset);
+ // Paper end - remove streams from pathfindergoalselector
}
public String toString() {
return this.getClass().getSimpleName();
}
- public EnumSet<PathfinderGoal.Type> i() {
- return this.a;
+ // Paper start - remove streams from pathfindergoalselector
+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<PathfinderGoal.Type> getGoalTypes() {
+ return this.goalTypes;
+ // Paper end - remove streams from pathfindergoalselector
}
public static enum Type {
2021-03-16 08:19:45 +01:00
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java
2020-05-06 11:48:49 +02:00
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
2021-03-16 08:19:45 +01:00
--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java
2020-04-12 02:15:22 +02:00
@@ -0,0 +0,0 @@
2021-03-16 08:19:45 +01:00
package net.minecraft.world.entity.ai.goal;
2020-04-12 02:15:22 +02:00
+import com.destroystokyo.paper.util.set.OptimizedSmallEnumSet; // Paper - remove streams from pathfindergoalselector
import com.google.common.collect.Sets;
import java.util.EnumMap;
import java.util.EnumSet;
+import java.util.Iterator; // Paper - remove streams from pathfindergoalselector
import java.util.Map;
import java.util.Set;
2020-06-26 03:53:21 +02:00
import java.util.function.Supplier;
2020-04-12 02:15:22 +02:00
@@ -0,0 +0,0 @@ public class PathfinderGoalSelector {
private final Map<PathfinderGoal.Type, PathfinderGoalWrapped> c = new EnumMap(PathfinderGoal.Type.class);
2020-06-26 03:53:21 +02:00
private final Set<PathfinderGoalWrapped> d = Sets.newLinkedHashSet(); private Set<PathfinderGoalWrapped> getTasks() { return d; }// Paper - OBFHELPER
private final Supplier<GameProfilerFiller> e;
2020-04-12 02:15:22 +02:00
- private final EnumSet<PathfinderGoal.Type> f = EnumSet.noneOf(PathfinderGoal.Type.class);
2020-05-02 03:44:06 +02:00
+ private final EnumSet<PathfinderGoal.Type> f = EnumSet.noneOf(PathfinderGoal.Type.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be.
2020-04-12 02:15:22 +02:00
+ private final OptimizedSmallEnumSet<PathfinderGoal.Type> goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector
private int g = 3;private int getTickRate() { return g; } // Paper - OBFHELPER
private int curRate;private int getCurRate() { return curRate; } private void incRate() { this.curRate++; } // Paper TODO
@@ -0,0 +0,0 @@ public class PathfinderGoalSelector {
// Paper end
public void a(PathfinderGoal pathfindergoal) {
- this.d.stream().filter((pathfindergoalwrapped) -> {
- return pathfindergoalwrapped.j() == pathfindergoal;
- }).filter(PathfinderGoalWrapped::g).forEach(PathfinderGoalWrapped::d);
- this.d.removeIf((pathfindergoalwrapped) -> {
- return pathfindergoalwrapped.j() == pathfindergoal;
- });
+ // Paper start - remove streams from pathfindergoalselector
+ for (Iterator<PathfinderGoalWrapped> iterator = this.d.iterator(); iterator.hasNext();) {
+ PathfinderGoalWrapped goalWrapped = iterator.next();
+ if (goalWrapped.j() != pathfindergoal) {
+ continue;
+ }
+ if (goalWrapped.g()) {
+ goalWrapped.d();
+ }
+ iterator.remove();
+ }
+ // Paper end - remove streams from pathfindergoalselector
}
+ private static final PathfinderGoal.Type[] PATHFINDER_GOAL_TYPES = PathfinderGoal.Type.values(); // Paper - remove streams from pathfindergoalselector
+
public void doTick() {
2020-06-26 03:53:21 +02:00
GameProfilerFiller gameprofilerfiller = (GameProfilerFiller) this.e.get();
gameprofilerfiller.enter("goalCleanup");
- this.d().filter((pathfindergoalwrapped) -> {
2020-04-12 02:15:22 +02:00
- boolean flag;
-
- if (pathfindergoalwrapped.g()) {
- Stream stream = pathfindergoalwrapped.i().stream();
- EnumSet enumset = this.f;
-
- this.f.getClass();
- if (!stream.anyMatch(enumset::contains) && pathfindergoalwrapped.b()) {
- flag = false;
- return flag;
- }
+ // Paper start - remove streams from pathfindergoalselector
+ for (Iterator<PathfinderGoalWrapped> iterator = this.d.iterator(); iterator.hasNext();) {
+ PathfinderGoalWrapped wrappedGoal = iterator.next();
+ if (!wrappedGoal.g()) {
+ continue;
}
-
- flag = true;
- return flag;
- }).forEach(PathfinderGoal::d);
+ if (!this.goalTypes.hasCommonElements(wrappedGoal.getGoalTypes()) && wrappedGoal.b()) {
+ continue;
+ }
+ wrappedGoal.d();
+ }
+ // Paper end - remove streams from pathfindergoalselector
this.c.forEach((pathfindergoal_type, pathfindergoalwrapped) -> {
if (!pathfindergoalwrapped.g()) {
this.c.remove(pathfindergoal_type);
@@ -0,0 +0,0 @@ public class PathfinderGoalSelector {
});
2020-06-26 03:53:21 +02:00
gameprofilerfiller.exit();
gameprofilerfiller.enter("goalUpdate");
2020-04-12 02:15:22 +02:00
- this.d.stream().filter((pathfindergoalwrapped) -> {
- return !pathfindergoalwrapped.g();
- }).filter((pathfindergoalwrapped) -> {
- Stream stream = pathfindergoalwrapped.i().stream();
- EnumSet enumset = this.f;
-
- this.f.getClass();
- return stream.noneMatch(enumset::contains);
- }).filter((pathfindergoalwrapped) -> {
- return pathfindergoalwrapped.i().stream().allMatch((pathfindergoal_type) -> {
- return ((PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b)).a(pathfindergoalwrapped);
- });
- }).filter(PathfinderGoalWrapped::a).forEach((pathfindergoalwrapped) -> {
- pathfindergoalwrapped.i().forEach((pathfindergoal_type) -> {
- PathfinderGoalWrapped pathfindergoalwrapped1 = (PathfinderGoalWrapped) this.c.getOrDefault(pathfindergoal_type, PathfinderGoalSelector.b);
-
- pathfindergoalwrapped1.d();
- this.c.put(pathfindergoal_type, pathfindergoalwrapped);
- });
- pathfindergoalwrapped.c();
- });
+ // Paper start - remove streams from pathfindergoalselector
+ goal_update_loop: for (Iterator<PathfinderGoalWrapped> iterator = this.d.iterator(); iterator.hasNext();) {
+ PathfinderGoalWrapped wrappedGoal = iterator.next();
+ if (wrappedGoal.g()) {
+ continue;
+ }
+
+ OptimizedSmallEnumSet<PathfinderGoal.Type> wrappedGoalSet = wrappedGoal.getGoalTypes();
+
+ if (this.goalTypes.hasCommonElements(wrappedGoalSet)) {
+ continue;
+ }
+
+ long iterator1 = wrappedGoalSet.getBackingSet();
+ int wrappedGoalSize = wrappedGoalSet.size();
+ for (int i = 0; i < wrappedGoalSize; ++i) {
+ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)];
+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1);
+ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b);
+ if (!wrapped.a(wrappedGoal)) {
+ continue goal_update_loop;
+ }
+ }
+
+ if (!wrappedGoal.a()) {
+ continue;
+ }
+
+ iterator1 = wrappedGoalSet.getBackingSet();
+ wrappedGoalSize = wrappedGoalSet.size();
+ for (int i = 0; i < wrappedGoalSize; ++i) {
+ PathfinderGoal.Type type = PATHFINDER_GOAL_TYPES[Long.numberOfTrailingZeros(iterator1)];
+ iterator1 ^= com.destroystokyo.paper.util.math.IntegerUtil.getTrailingBit(iterator1);
+ PathfinderGoalWrapped wrapped = this.c.getOrDefault(type, PathfinderGoalSelector.b);
+
+ wrapped.d();
+ this.c.put(type, wrappedGoal);
+ }
+
+ wrappedGoal.c();
+ }
+ // Paper end - remove streams from pathfindergoalselector
2020-06-26 03:53:21 +02:00
gameprofilerfiller.exit();
gameprofilerfiller.enter("goalTick");
- this.d().forEach(PathfinderGoalWrapped::e);
2020-04-12 02:15:22 +02:00
+ // Paper start - remove streams from pathfindergoalselector
+ for (Iterator<PathfinderGoalWrapped> iterator = this.d.iterator(); iterator.hasNext();) {
+ PathfinderGoalWrapped wrappedGoal = iterator.next();
+ if (wrappedGoal.g()) {
+ wrappedGoal.e();
+ }
+ }
+ // Paper end - remove streams from pathfindergoalselector
2020-06-26 03:53:21 +02:00
gameprofilerfiller.exit();
2020-04-12 02:15:22 +02:00
}
@@ -0,0 +0,0 @@ public class PathfinderGoalSelector {
}
public void a(PathfinderGoal.Type pathfindergoal_type) {
- this.f.add(pathfindergoal_type);
+ this.goalTypes.addUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector
}
public void b(PathfinderGoal.Type pathfindergoal_type) {
- this.f.remove(pathfindergoal_type);
+ this.goalTypes.removeUnchecked(pathfindergoal_type); // Paper - remove streams from pathfindergoalselector
}
public void a(PathfinderGoal.Type pathfindergoal_type, boolean flag) {
2021-03-16 08:19:45 +01:00
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java
2020-05-06 11:48:49 +02:00
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
2021-03-16 08:19:45 +01:00
--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java
2020-04-12 02:15:22 +02:00
@@ -0,0 +0,0 @@ public class PathfinderGoalWrapped extends PathfinderGoal {
this.a.a(enumset);
}
- @Override
- public EnumSet<PathfinderGoal.Type> i() {
- return this.a.i();
+ // Paper start - remove streams from pathfindergoalselector
+ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<PathfinderGoal.Type> getGoalTypes() {
+ return this.a.getGoalTypes();
+ // Paper end - remove streams from pathfindergoalselector
}
public boolean isRunning() { return this.g(); } // Paper - OBFHELPER