2021-06-11 14:02:28 +02:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2022-09-26 10:02:51 +02:00
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
2021-06-11 14:02:28 +02:00
Date: Mon, 6 Apr 2020 17:53:29 -0700
2021-11-24 12:06:34 +01:00
Subject: [PATCH] Optimize GoalSelector Goal.Flag Set operations
2021-06-11 14:02:28 +02:00
2021-11-24 12:06:34 +01:00
Optimise the stream.anyMatch statement to move to a bitset
2021-06-11 14:02:28 +02:00
where we can replace the call with a single bitwise operation.
2024-12-16 12:25:25 +01:00
diff --git a/net/minecraft/world/entity/ai/goal/Goal.java b/net/minecraft/world/entity/ai/goal/Goal.java
2024-12-16 18:07:41 +01:00
index d4f8387254a65b25fc808932a069298d0f8da091..5f5bf0e710ecff09a571091e5a923332be70cb74 100644
2024-12-16 12:25:25 +01:00
--- 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;
2024-10-24 22:29:29 +02:00
import net.minecraft.world.level.Level;
2021-06-11 14:02:28 +02:00
public abstract class Goal {
- private final EnumSet<Goal.Flag> flags = EnumSet.noneOf(Goal.Flag.class);
2024-12-16 18:07:41 +01:00
+ 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
2024-01-23 12:06:27 +01:00
+
2024-12-16 18:07:41 +01:00
+ // Paper start - remove streams from GoalSelector; make sure types are not empty
2024-12-16 12:25:25 +01:00
+ protected Goal() {
2024-01-23 12:06:27 +01:00
+ if (this.goalTypes.size() == 0) {
2024-07-17 19:24:53 +02:00
+ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR);
2024-01-23 12:06:27 +01:00
+ }
+ }
2024-12-16 18:07:41 +01:00
+ // Paper end - remove streams from GoalSelector
2021-06-11 14:02:28 +02:00
2021-06-14 03:06:38 +02:00
public abstract boolean canUse();
2021-06-11 14:02:28 +02:00
2024-12-16 12:25:25 +01:00
@@ -33,8 +41,13 @@ public abstract class Goal {
2021-06-14 03:06:38 +02:00
}
2021-06-11 14:02:28 +02:00
2024-12-16 12:25:25 +01:00
public void setFlags(EnumSet<Goal.Flag> flagSet) {
2021-06-11 14:02:28 +02:00
- this.flags.clear();
2024-12-16 12:25:25 +01:00
- this.flags.addAll(flagSet);
2024-12-16 18:07:41 +01:00
+ // Paper start - remove streams from GoalSelector
2021-06-11 14:02:28 +02:00
+ this.goalTypes.clear();
2024-12-16 12:25:25 +01:00
+ this.goalTypes.addAllUnchecked(flagSet);
2024-01-23 12:06:27 +01:00
+ if (this.goalTypes.size() == 0) {
2024-07-17 19:24:53 +02:00
+ this.goalTypes.addUnchecked(Flag.UNKNOWN_BEHAVIOR);
2024-01-23 12:06:27 +01:00
+ }
2024-12-16 18:07:41 +01:00
+ // Paper end - remove streams from GoalSelector
2021-06-11 14:02:28 +02:00
}
2021-06-14 03:06:38 +02:00
@Override
2024-12-16 12:25:25 +01:00
@@ -42,18 +55,20 @@ public abstract class Goal {
2021-06-11 14:02:28 +02:00
return this.getClass().getSimpleName();
}
- public EnumSet<Goal.Flag> getFlags() {
- return this.flags;
2024-12-16 18:07:41 +01:00
+ // Paper start - remove streams from GoalSelector
2024-07-17 19:24:53 +02:00
+ public ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() {
2021-06-11 14:02:28 +02:00
+ return this.goalTypes;
2024-12-16 18:07:41 +01:00
+ // Paper end - remove streams from GoalSelector
2021-06-11 14:02:28 +02:00
}
2024-12-16 12:25:25 +01:00
2024-12-05 11:18:29 +01:00
// 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);
}
2024-12-16 12:25:25 +01:00
// Paper end - Mob Goal API
2024-12-16 18:07:41 +01:00
2024-12-16 12:25:25 +01:00
diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java
2024-12-16 18:07:41 +01:00
index eeba224bd575451ba6023df65ef9d9b97f7f1c71..a927c2790c8ab9ccaa7161b970e10b0b44817dd8 100644
2024-12-16 12:25:25 +01:00
--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
2024-12-16 15:17:46 +01:00
@@ -24,7 +24,8 @@ public class GoalSelector {
2024-10-24 22:29:29 +02:00
};
2021-06-14 03:06:38 +02:00
private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap<>(Goal.Flag.class);
2024-04-25 11:42:10 +02:00
private final Set<WrappedGoal> availableGoals = new ObjectLinkedOpenHashSet<>();
2021-06-11 14:02:28 +02:00
- private final EnumSet<Goal.Flag> disabledFlags = EnumSet.noneOf(Goal.Flag.class);
2024-12-16 18:07:41 +01:00
+ 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
2024-12-16 15:17:46 +01:00
private int curRate; // Paper - EAR 2
2021-06-11 14:02:28 +02:00
2024-10-24 22:29:29 +02:00
public void addGoal(int priority, Goal goal) {
2024-12-16 15:17:46 +01:00
@@ -62,18 +63,18 @@ public class GoalSelector {
2024-12-16 12:25:25 +01:00
this.availableGoals.removeIf(wrappedGoal1 -> wrappedGoal1.getGoal() == goal);
2021-06-14 03:06:38 +02:00
}
2024-04-25 11:42:10 +02:00
2024-12-16 12:25:25 +01:00
- private static boolean goalContainsAnyFlags(WrappedGoal goal, EnumSet<Goal.Flag> flag) {
- for (Goal.Flag flag1 : goal.getFlags()) {
- if (flag.contains(flag1)) {
2023-03-23 22:57:03 +01:00
- return true;
2024-04-25 11:42:10 +02:00
- }
- }
-
2021-11-24 12:06:34 +01:00
- return false;
2024-12-16 12:25:25 +01:00
+ // Paper start - Perf: optimize goal types
+ private static boolean goalContainsAnyFlags(WrappedGoal goal, ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> flags) {
2024-12-16 15:44:33 +01:00
+ return goal.getFlags().hasCommonElements(flags);
2021-11-24 12:06:34 +01:00
}
2024-12-16 12:25:25 +01:00
private static boolean goalCanBeReplacedForAllFlags(WrappedGoal goal, Map<Goal.Flag, WrappedGoal> flag) {
- for (Goal.Flag flag1 : goal.getFlags()) {
2021-11-30 09:36:30 +01:00
+ long flagIterator = goal.getFlags().getBackingSet();
+ int wrappedGoalSize = goal.getFlags().size();
+ for (int i = 0; i < wrappedGoalSize; ++i) {
2024-12-16 12:25:25 +01:00
+ final Goal.Flag flag1 = GOAL_FLAG_VALUES[Long.numberOfTrailingZeros(flagIterator)];
2024-07-17 19:24:53 +02:00
+ flagIterator ^= ca.spottedleaf.concurrentutil.util.IntegerUtil.getTrailingBit(flagIterator);
2024-12-16 12:25:25 +01:00
+ // Paper end - Perf: optimize goal types
if (!flag.getOrDefault(flag1, NO_GOAL).canBeReplacedBy(goal)) {
2021-11-30 09:36:30 +01:00
return false;
2021-11-24 12:06:34 +01:00
}
2024-12-16 15:17:46 +01:00
@@ -87,7 +88,7 @@ public class GoalSelector {
2021-06-14 03:06:38 +02:00
profilerFiller.push("goalCleanup");
2024-04-12 21:14:06 +02:00
for (WrappedGoal wrappedGoal : this.availableGoals) {
2021-11-24 12:06:34 +01:00
- if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.disabledFlags) || !wrappedGoal.canContinueToUse())) {
2024-04-12 21:14:06 +02:00
+ if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.goalTypes) || !wrappedGoal.canContinueToUse())) { // Paper - Perf: optimize goal types by removing streams
2021-11-24 12:06:34 +01:00
wrappedGoal.stop();
}
}
2024-12-16 15:17:46 +01:00
@@ -97,11 +98,14 @@ public class GoalSelector {
2021-06-14 03:06:38 +02:00
profilerFiller.push("goalUpdate");
2021-06-11 14:02:28 +02:00
2024-12-16 12:25:25 +01:00
for (WrappedGoal wrappedGoalx : this.availableGoals) {
- if (!wrappedGoalx.isRunning()
- && !goalContainsAnyFlags(wrappedGoalx, this.disabledFlags)
- && goalCanBeReplacedForAllFlags(wrappedGoalx, this.lockedFlags)
- && wrappedGoalx.canUse()) {
- for (Goal.Flag flag : wrappedGoalx.getFlags()) {
2021-11-24 12:06:34 +01:00
+ // Paper start
2024-12-16 12:25:25 +01:00
+ if (!wrappedGoalx.isRunning() && !goalContainsAnyFlags(wrappedGoalx, this.goalTypes) && goalCanBeReplacedForAllFlags(wrappedGoalx, this.lockedFlags) && wrappedGoalx.canUse()) {
+ long flagIterator = wrappedGoalx.getFlags().getBackingSet();
+ int wrappedGoalSize = wrappedGoalx.getFlags().size();
2021-11-30 09:36:30 +01:00
+ for (int i = 0; i < wrappedGoalSize; ++i) {
+ final Goal.Flag flag = GOAL_FLAG_VALUES[Long.numberOfTrailingZeros(flagIterator)];
2024-07-17 19:24:53 +02:00
+ flagIterator ^= ca.spottedleaf.concurrentutil.util.IntegerUtil.getTrailingBit(flagIterator);
2021-11-24 12:06:34 +01:00
+ // Paper end
2024-12-16 12:25:25 +01:00
WrappedGoal wrappedGoal1 = this.lockedFlags.getOrDefault(flag, NO_GOAL);
wrappedGoal1.stop();
this.lockedFlags.put(flag, wrappedGoalx);
2024-12-16 15:17:46 +01:00
@@ -133,11 +137,11 @@ public class GoalSelector {
2021-06-11 14:02:28 +02:00
}
2024-12-16 12:25:25 +01:00
public void disableControlFlag(Goal.Flag flag) {
- this.disabledFlags.add(flag);
2024-12-16 18:07:41 +01:00
+ this.goalTypes.addUnchecked(flag); // Paper - remove streams from GoalSelector
2021-06-11 14:02:28 +02:00
}
2024-12-16 12:25:25 +01:00
public void enableControlFlag(Goal.Flag flag) {
- this.disabledFlags.remove(flag);
2024-12-16 18:07:41 +01:00
+ this.goalTypes.removeUnchecked(flag); // Paper - remove streams from GoalSelector
2021-06-11 14:02:28 +02:00
}
2024-12-16 12:25:25 +01:00
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
2024-12-16 18:07:41 +01:00
index 4bdbd323b642ed3422948fe24780be8b503602dc..2c2ab6a1df9d3d23773e44ce4041cc1c21b55163 100644
2024-12-16 12:25:25 +01:00
--- 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 {
2021-06-11 14:02:28 +02:00
}
2021-11-24 12:06:34 +01:00
@Override
2021-06-11 14:02:28 +02:00
- public EnumSet<Goal.Flag> getFlags() {
2024-12-16 18:07:41 +01:00
+ public ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() { // Paper - remove streams from GoalSelector
2021-09-09 19:12:22 +02:00
return this.goal.getFlags();
2021-06-11 14:02:28 +02:00
}