aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches-Unmapped/0435-Remove-streams-from-Mob-AI-System.patch
diff options
context:
space:
mode:
Diffstat (limited to 'Spigot-Server-Patches-Unmapped/0435-Remove-streams-from-Mob-AI-System.patch')
-rw-r--r--Spigot-Server-Patches-Unmapped/0435-Remove-streams-from-Mob-AI-System.patch253
1 files changed, 253 insertions, 0 deletions
diff --git a/Spigot-Server-Patches-Unmapped/0435-Remove-streams-from-Mob-AI-System.patch b/Spigot-Server-Patches-Unmapped/0435-Remove-streams-from-Mob-AI-System.patch
new file mode 100644
index 0000000000..4937798620
--- /dev/null
+++ b/Spigot-Server-Patches-Unmapped/0435-Remove-streams-from-Mob-AI-System.patch
@@ -0,0 +1,253 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Spottedleaf <[email protected]>
+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.
+
+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
+index b505c23c57a4b84faf5906c6295455b4720c4426..5c32cbe81c47fcb9ae347faa6fc007c5d28d79bf 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java
++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoal.java
+@@ -1,10 +1,12 @@
+ package net.minecraft.world.entity.ai.goal;
+
++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);
++ 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.
++ private final OptimizedSmallEnumSet<Type> goalTypes = new OptimizedSmallEnumSet<>(PathfinderGoal.Type.class); // Paper - remove streams from pathfindergoalselector
+
+ public PathfinderGoal() {}
+
+@@ -28,16 +30,20 @@ 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 {
+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
+index 8c234c09a4d9ada83e36e3cdbcc1f2f5c6202f28..385cd079e264a7e66e91ab3b70b90afb59688dcd 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java
++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalSelector.java
+@@ -1,8 +1,10 @@
+ package net.minecraft.world.entity.ai.goal;
+
++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;
+ import java.util.function.Supplier;
+@@ -28,7 +30,8 @@ public class PathfinderGoalSelector {
+ private final Map<PathfinderGoal.Type, PathfinderGoalWrapped> c = new EnumMap(PathfinderGoal.Type.class);
+ private final Set<PathfinderGoalWrapped> d = Sets.newLinkedHashSet(); private Set<PathfinderGoalWrapped> getTasks() { return d; }// Paper - OBFHELPER
+ private final Supplier<GameProfilerFiller> e;
+- private final EnumSet<PathfinderGoal.Type> f = EnumSet.noneOf(PathfinderGoal.Type.class);
++ 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.
++ 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
+
+@@ -56,35 +59,38 @@ 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() {
+ GameProfilerFiller gameprofilerfiller = (GameProfilerFiller) this.e.get();
+
+ gameprofilerfiller.enter("goalCleanup");
+- this.d().filter((pathfindergoalwrapped) -> {
+- 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);
+@@ -93,30 +99,58 @@ public class PathfinderGoalSelector {
+ });
+ gameprofilerfiller.exit();
+ gameprofilerfiller.enter("goalUpdate");
+- 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
+ gameprofilerfiller.exit();
+ gameprofilerfiller.enter("goalTick");
+- this.d().forEach(PathfinderGoalWrapped::e);
++ // 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
+ gameprofilerfiller.exit();
+ }
+
+@@ -125,11 +159,11 @@ 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) {
+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
+index 7bb531e47668cf445083c4dedb03ccafe6a9c96b..8c8e39d35fb56aa6cf7d456adab01dff5d13a60d 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java
++++ b/src/main/java/net/minecraft/world/entity/ai/goal/PathfinderGoalWrapped.java
+@@ -59,9 +59,10 @@ 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