--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
@@ -25,7 +25,9 @@
     private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap<>(Goal.Flag.class);
     private final Set<WrappedGoal> availableGoals = new ObjectLinkedOpenHashSet<>();
     private final Supplier<ProfilerFiller> profiler;
-    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 pathfindergoalselector
+    private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<net.minecraft.world.entity.ai.goal.Goal.Flag> goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector
+    private int curRate;
 
     public GoalSelector(Supplier<ProfilerFiller> profiler) {
         this.profiler = profiler;
@@ -40,6 +42,20 @@
         this.availableGoals.removeIf(goal -> predicate.test(goal.getGoal()));
     }
 
+    // Paper start
+    public boolean inactiveTick() {
+        this.curRate++;
+        return this.curRate % 3 == 0; // TODO newGoalRate was already unused in 1.20.4, check if this is correct
+    }
+    public boolean hasTasks() {
+        for (WrappedGoal task : this.availableGoals) {
+            if (task.isRunning()) {
+                return true;
+            }
+        }
+        return false;
+    }
+    // Paper end
     public void removeGoal(Goal goal) {
         for (WrappedGoal wrappedGoal : this.availableGoals) {
             if (wrappedGoal.getGoal() == goal && wrappedGoal.isRunning()) {
@@ -50,18 +66,18 @@
         this.availableGoals.removeIf(wrappedGoalx -> wrappedGoalx.getGoal() == goal);
     }
 
-    private static boolean goalContainsAnyFlags(WrappedGoal goal, EnumSet<Goal.Flag> controls) {
-        for (Goal.Flag flag : goal.getFlags()) {
-            if (controls.contains(flag)) {
-                return true;
-            }
-        }
-
-        return false;
+    // Paper start
+    private static boolean goalContainsAnyFlags(WrappedGoal goal, com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<Goal.Flag> controls) {
+        return goal.getFlags().hasCommonElements(controls);
     }
 
     private static boolean goalCanBeReplacedForAllFlags(WrappedGoal goal, Map<Goal.Flag, WrappedGoal> goalsByControl) {
-        for (Goal.Flag flag : goal.getFlags()) {
+        long flagIterator = goal.getFlags().getBackingSet();
+        int wrappedGoalSize = goal.getFlags().size();
+        for (int i = 0; i < wrappedGoalSize; ++i) {
+            final Goal.Flag flag = GOAL_FLAG_VALUES[Long.numberOfTrailingZeros(flagIterator)];
+            flagIterator ^= io.papermc.paper.util.IntegerUtil.getTrailingBit(flagIterator);
+            // Paper end
             if (!goalsByControl.getOrDefault(flag, NO_GOAL).canBeReplacedBy(goal)) {
                 return false;
             }
@@ -75,7 +91,7 @@
         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();
             }
         }
@@ -85,11 +101,14 @@
         profilerFiller.push("goalUpdate");
 
         for (WrappedGoal wrappedGoal2 : this.availableGoals) {
-            if (!wrappedGoal2.isRunning()
-                && !goalContainsAnyFlags(wrappedGoal2, this.disabledFlags)
-                && goalCanBeReplacedForAllFlags(wrappedGoal2, this.lockedFlags)
-                && wrappedGoal2.canUse()) {
-                for (Goal.Flag flag : wrappedGoal2.getFlags()) {
+            // Paper start
+            if (!wrappedGoal2.isRunning() && !goalContainsAnyFlags(wrappedGoal2, this.goalTypes) && goalCanBeReplacedForAllFlags(wrappedGoal2, this.lockedFlags) && wrappedGoal2.canUse()) {
+                long flagIterator = wrappedGoal2.getFlags().getBackingSet();
+                int wrappedGoalSize = wrappedGoal2.getFlags().size();
+                for (int i = 0; i < wrappedGoalSize; ++i) {
+                    final Goal.Flag flag = GOAL_FLAG_VALUES[Long.numberOfTrailingZeros(flagIterator)];
+                    flagIterator ^= io.papermc.paper.util.IntegerUtil.getTrailingBit(flagIterator);
+                    // Paper end
                     WrappedGoal wrappedGoal3 = this.lockedFlags.getOrDefault(flag, NO_GOAL);
                     wrappedGoal3.stop();
                     this.lockedFlags.put(flag, wrappedGoal2);
@@ -121,11 +140,11 @@
     }
 
     public void disableControlFlag(Goal.Flag control) {
-        this.disabledFlags.add(control);
+        this.goalTypes.add(control); // Paper - remove streams from pathfindergoalselector
     }
 
     public void enableControlFlag(Goal.Flag control) {
-        this.disabledFlags.remove(control);
+        this.goalTypes.remove(control); // Paper - remove streams from pathfindergoalselector
     }
 
     public void setControlFlag(Goal.Flag control, boolean enabled) {
