aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/1007-Optimize-GoalSelector-Goal.Flag-Set-operations.patch
diff options
context:
space:
mode:
authorBjarne Koll <[email protected]>2024-06-16 17:21:14 +0200
committerBjarne Koll <[email protected]>2024-06-16 17:23:42 +0200
commite1c003355296d70ea50e80d1933aba34e00d0763 (patch)
tree728ab80298d566c824b32d0e4be332871faef9fb /patches/server/1007-Optimize-GoalSelector-Goal.Flag-Set-operations.patch
parentec4c712efa6c8eaeb514156357da679e540bfeda (diff)
downloadPaper-e1c003355296d70ea50e80d1933aba34e00d0763.tar.gz
Paper-e1c003355296d70ea50e80d1933aba34e00d0763.zip
Updated Upstream (Bukkit/CraftBukkit)
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: 2b4b6d14 PR-1023: Convert InventoryView to interface CraftBukkit Changes: 68603b1c1 Use expanded interaction ranges for traced interact events eae9f760c PR-1414: Convert InventoryView to interface ee9eafe67 Fix Implementation for DamageSource#isIndirect for internal custom causing entity
Diffstat (limited to 'patches/server/1007-Optimize-GoalSelector-Goal.Flag-Set-operations.patch')
-rw-r--r--patches/server/1007-Optimize-GoalSelector-Goal.Flag-Set-operations.patch160
1 files changed, 160 insertions, 0 deletions
diff --git a/patches/server/1007-Optimize-GoalSelector-Goal.Flag-Set-operations.patch b/patches/server/1007-Optimize-GoalSelector-Goal.Flag-Set-operations.patch
new file mode 100644
index 0000000000..1f46712639
--- /dev/null
+++ b/patches/server/1007-Optimize-GoalSelector-Goal.Flag-Set-operations.patch
@@ -0,0 +1,160 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Spottedleaf <[email protected]>
+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/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java
+index 16f9a98b8a939e5ca7e2dc04f87134a7ed66736b..dd423302b1baa64ef86ded87a29659342e28c142 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java
++++ b/src/main/java/net/minecraft/world/entity/ai/goal/Goal.java
+@@ -4,7 +4,16 @@ import java.util.EnumSet;
+ import net.minecraft.util.Mth;
+
+ public abstract class Goal {
+- private final EnumSet<Goal.Flag> flags = EnumSet.noneOf(Goal.Flag.class);
++ private final EnumSet<Goal.Flag> flags = EnumSet.noneOf(Goal.Flag.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 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
++
++ // Paper start - remove streams from pathfindergoalselector; make sure types are not empty
++ public Goal() {
++ if (this.goalTypes.size() == 0) {
++ this.goalTypes.add(Flag.UNKNOWN_BEHAVIOR);
++ }
++ }
++ // Paper end - remove streams from pathfindergoalselector
+
+ public abstract boolean canUse();
+
+@@ -30,8 +39,13 @@ public abstract class Goal {
+ }
+
+ public void setFlags(EnumSet<Goal.Flag> controls) {
+- this.flags.clear();
+- this.flags.addAll(controls);
++ // Paper start - remove streams from pathfindergoalselector
++ this.goalTypes.clear();
++ this.goalTypes.addAll(controls);
++ if (this.goalTypes.size() == 0) {
++ this.goalTypes.add(Flag.UNKNOWN_BEHAVIOR);
++ }
++ // Paper end - remove streams from pathfindergoalselector
+ }
+
+ @Override
+@@ -39,8 +53,10 @@ public abstract class Goal {
+ return this.getClass().getSimpleName();
+ }
+
+- public EnumSet<Goal.Flag> getFlags() {
+- return this.flags;
++ // Paper start - remove streams from pathfindergoalselector
++ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() {
++ return this.goalTypes;
++ // Paper end - remove streams from pathfindergoalselector
+ }
+
+ protected int adjustedTickDelay(int ticks) {
+diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
+index 074ef807258139f818e30494126585262c2f33c0..74d4f653d5c7f1923c59019effd78337402f7025 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
++++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
+@@ -25,7 +25,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 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) {
+@@ -65,18 +66,18 @@ public class GoalSelector {
+ 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;
+ }
+@@ -90,7 +91,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();
+ }
+ }
+@@ -100,11 +101,14 @@ public class GoalSelector {
+ 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);
+@@ -136,11 +140,11 @@ public class GoalSelector {
+ }
+
+ 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) {
+diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java
+index b02d3deb550830245c8945ef17d3073ea930fdda..65ccdbaa5230c02d44a5959bca0f6fc30237a6fd 100644
+--- a/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java
++++ b/src/main/java/net/minecraft/world/entity/ai/goal/WrappedGoal.java
+@@ -69,8 +69,10 @@ public class WrappedGoal extends Goal {
+ }
+
+ @Override
+- public EnumSet<Goal.Flag> getFlags() {
++ // Paper start - remove streams from pathfindergoalselector
++ public com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() {
+ return this.goal.getFlags();
++ // Paper end - remove streams from pathfindergoalselector
+ }
+
+ public boolean isRunning() {