aboutsummaryrefslogtreecommitdiffhomepage
path: root/paper-server/patches/features/0010-Optimize-GoalSelector-Goal.Flag-Set-operations.patch
blob: 8d68059b7468c71dcd1a5843b043c317ea38a2a5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
Date: Mon, 6 Apr 2020 17:53:29 -0700
Subject: [PATCH] Optimize GoalSelector Goal.Flag Set operations

Optimise the stream.anyMatch statement to move to a bitset
where we can replace the call with a single bitwise operation.

diff --git a/net/minecraft/world/entity/ai/goal/Goal.java b/net/minecraft/world/entity/ai/goal/Goal.java
index d4f8387254a65b25fc808932a069298d0f8da091..5f5bf0e710ecff09a571091e5a923332be70cb74 100644
--- a/net/minecraft/world/entity/ai/goal/Goal.java
+++ b/net/minecraft/world/entity/ai/goal/Goal.java
@@ -7,7 +7,15 @@ import net.minecraft.world.entity.Entity;
 import net.minecraft.world.level.Level;
 
 public abstract class Goal {
-    private final EnumSet<Goal.Flag> flags = EnumSet.noneOf(Goal.Flag.class);
+    private final ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<net.minecraft.world.entity.ai.goal.Goal.Flag> goalTypes = new ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from GoalSelector
+
+    // Paper start - remove streams from GoalSelector; make sure types are not empty
+    protected Goal() {
+        if (this.goalTypes.size() == 0) {
+            this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR);
+        }
+    }
+    // Paper end - remove streams from GoalSelector
 
     public abstract boolean canUse();
 
@@ -33,8 +41,13 @@ public abstract class Goal {
     }
 
     public void setFlags(EnumSet<Goal.Flag> flagSet) {
-        this.flags.clear();
-        this.flags.addAll(flagSet);
+        // Paper start - remove streams from GoalSelector
+        this.goalTypes.clear();
+        this.goalTypes.addAllUnchecked(flagSet);
+        if (this.goalTypes.size() == 0) {
+            this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR);
+        }
+        // Paper end - remove streams from GoalSelector
     }
 
     @Override
@@ -42,18 +55,20 @@ public abstract class Goal {
         return this.getClass().getSimpleName();
     }
 
-    public EnumSet<Goal.Flag> getFlags() {
-        return this.flags;
+    // Paper start - remove streams from GoalSelector
+    public ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() {
+        return this.goalTypes;
+        // Paper end - remove streams from GoalSelector
     }
 
 
     // Paper start - Mob Goal API
     public boolean hasFlag(final Goal.Flag flag) {
-        return this.flags.contains(flag);
+        return this.goalTypes.hasElement(flag);
     }
 
     public void addFlag(final Goal.Flag flag) {
-        this.flags.add(flag);
+        this.goalTypes.addUnchecked(flag);
     }
     // Paper end - Mob Goal API
 
diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java
index eeba224bd575451ba6023df65ef9d9b97f7f1c71..a927c2790c8ab9ccaa7161b970e10b0b44817dd8 100644
--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
@@ -24,7 +24,8 @@ public class GoalSelector {
     };
     private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap<>(Goal.Flag.class);
     private final Set<WrappedGoal> availableGoals = new ObjectLinkedOpenHashSet<>();
-    private final EnumSet<Goal.Flag> disabledFlags = EnumSet.noneOf(Goal.Flag.class);
+    private static final Goal.Flag[] GOAL_FLAG_VALUES = Goal.Flag.values(); // Paper - remove streams from GoalSelector
+    private final ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<net.minecraft.world.entity.ai.goal.Goal.Flag> goalTypes = new ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from GoalSelector
     private int curRate; // Paper - EAR 2
 
     public void addGoal(int priority, Goal goal) {
@@ -62,18 +63,18 @@ public class GoalSelector {
         this.availableGoals.removeIf(wrappedGoal1 -> wrappedGoal1.getGoal() == goal);
     }
 
-    private static boolean goalContainsAnyFlags(WrappedGoal goal, EnumSet<Goal.Flag> flag) {
-        for (Goal.Flag flag1 : goal.getFlags()) {
-            if (flag.contains(flag1)) {
-                return true;
-            }
-        }
-
-        return false;
+    // Paper start - Perf: optimize goal types
+    private static boolean goalContainsAnyFlags(WrappedGoal goal, ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> flags) {
+        return goal.getFlags().hasCommonElements(flags);
     }
 
     private static boolean goalCanBeReplacedForAllFlags(WrappedGoal goal, Map<Goal.Flag, WrappedGoal> flag) {
-        for (Goal.Flag flag1 : goal.getFlags()) {
+        long flagIterator = goal.getFlags().getBackingSet();
+        int wrappedGoalSize = goal.getFlags().size();
+        for (int i = 0; i < wrappedGoalSize; ++i) {
+            final Goal.Flag flag1 = GOAL_FLAG_VALUES[Long.numberOfTrailingZeros(flagIterator)];
+            flagIterator ^= ca.spottedleaf.concurrentutil.util.IntegerUtil.getTrailingBit(flagIterator);
+            // Paper end - Perf: optimize goal types
             if (!flag.getOrDefault(flag1, NO_GOAL).canBeReplacedBy(goal)) {
                 return false;
             }
@@ -87,7 +88,7 @@ public class GoalSelector {
         profilerFiller.push("goalCleanup");
 
         for (WrappedGoal wrappedGoal : this.availableGoals) {
-            if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.disabledFlags) || !wrappedGoal.canContinueToUse())) {
+            if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.goalTypes) || !wrappedGoal.canContinueToUse())) { // Paper - Perf: optimize goal types by removing streams
                 wrappedGoal.stop();
             }
         }
@@ -97,11 +98,14 @@ public class GoalSelector {
         profilerFiller.push("goalUpdate");
 
         for (WrappedGoal wrappedGoalx : this.availableGoals) {
-            if (!wrappedGoalx.isRunning()
-                && !goalContainsAnyFlags(wrappedGoalx, this.disabledFlags)
-                && goalCanBeReplacedForAllFlags(wrappedGoalx, this.lockedFlags)
-                && wrappedGoalx.canUse()) {
-                for (Goal.Flag flag : wrappedGoalx.getFlags()) {
+            // Paper start
+            if (!wrappedGoalx.isRunning() && !goalContainsAnyFlags(wrappedGoalx, this.goalTypes) && goalCanBeReplacedForAllFlags(wrappedGoalx, this.lockedFlags) && wrappedGoalx.canUse()) {
+                long flagIterator = wrappedGoalx.getFlags().getBackingSet();
+                int wrappedGoalSize = wrappedGoalx.getFlags().size();
+                for (int i = 0; i < wrappedGoalSize; ++i) {
+                    final Goal.Flag flag = GOAL_FLAG_VALUES[Long.numberOfTrailingZeros(flagIterator)];
+                    flagIterator ^= ca.spottedleaf.concurrentutil.util.IntegerUtil.getTrailingBit(flagIterator);
+                    // Paper end
                     WrappedGoal wrappedGoal1 = this.lockedFlags.getOrDefault(flag, NO_GOAL);
                     wrappedGoal1.stop();
                     this.lockedFlags.put(flag, wrappedGoalx);
@@ -133,11 +137,11 @@ public class GoalSelector {
     }
 
     public void disableControlFlag(Goal.Flag flag) {
-        this.disabledFlags.add(flag);
+        this.goalTypes.addUnchecked(flag); // Paper - remove streams from GoalSelector
     }
 
     public void enableControlFlag(Goal.Flag flag) {
-        this.disabledFlags.remove(flag);
+        this.goalTypes.removeUnchecked(flag); // Paper - remove streams from GoalSelector
     }
 
     public void setControlFlag(Goal.Flag flag, boolean enabled) {
diff --git a/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/net/minecraft/world/entity/ai/goal/WrappedGoal.java
index 4bdbd323b642ed3422948fe24780be8b503602dc..2c2ab6a1df9d3d23773e44ce4041cc1c21b55163 100644
--- a/net/minecraft/world/entity/ai/goal/WrappedGoal.java
+++ b/net/minecraft/world/entity/ai/goal/WrappedGoal.java
@@ -69,7 +69,7 @@ public class WrappedGoal extends Goal {
     }
 
     @Override
-    public EnumSet<Goal.Flag> getFlags() {
+    public ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() { // Paper - remove streams from GoalSelector
         return this.goal.getFlags();
     }