aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/1005-Optimize-GoalSelector-Goal.Flag-Set-operations.patch
diff options
context:
space:
mode:
authorNassim Jahnke <[email protected]>2024-01-26 20:17:06 +0100
committerNassim Jahnke <[email protected]>2024-01-26 20:19:17 +0100
commitfe53b0e76fc640072ff7866da496b439032c1684 (patch)
tree7867a2f4807e34c896052ce6d8294d8edcfe9218 /patches/server/1005-Optimize-GoalSelector-Goal.Flag-Set-operations.patch
parentbd2fd615ceb7c65f6837317bc83bf9cbfc425b42 (diff)
downloadPaper-fe53b0e76fc640072ff7866da496b439032c1684.tar.gz
Paper-fe53b0e76fc640072ff7866da496b439032c1684.zip
Updated Upstream (Bukkit/CraftBukkit/Spigot)
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: 1d522878 PR-966: Introduce getRespawnLocation as a replacement for getBedSpawnLocation cc01b745 PR-965: Add DragonBattle#setPreviouslyKilled 28e3702f SPIGOT-6921, PR-957: Add methods to remove all enchantments on an ItemStack 8872404e PR-961: Add BlockData#copyTo 4054cc7b PR-956: Add method to get an offline player's location CraftBukkit Changes: 292ec79e0 SPIGOT-7568: Call EntityChangeBlockEvent for DecoratedPot b44bf5aa8 SPIGOT-7575: SuspiciousStewMeta creates invalid PotionEffect data 161784713 PR-1340: Centralize the conversion from and to Minecraft / Bukkit registry items even more and add a test case for them b93c5a30d PR-1338: Introduce getRespawnLocation as a replacement for getBedSpawnLocation fb973486c SPIGOT-7570: PrepareItemCraftEvent#isRepair() always returns false c9c24535e PR-1337: Add DragonBattle#setPreviouslyKilled c8b4da803 SPIGOT-6921, PR-1330: Add methods to remove all enchantments on an ItemStack 95bc1c4f5 PR-1333: Add BlockData#copyTo 36e2f9ce1 PR-1329: Add method to get an offline player's location Spigot Changes: c198da22 SPIGOT-7563: Update to latest release of bungeecord-chat
Diffstat (limited to 'patches/server/1005-Optimize-GoalSelector-Goal.Flag-Set-operations.patch')
-rw-r--r--patches/server/1005-Optimize-GoalSelector-Goal.Flag-Set-operations.patch180
1 files changed, 180 insertions, 0 deletions
diff --git a/patches/server/1005-Optimize-GoalSelector-Goal.Flag-Set-operations.patch b/patches/server/1005-Optimize-GoalSelector-Goal.Flag-Set-operations.patch
new file mode 100644
index 0000000000..8e879a28af
--- /dev/null
+++ b/patches/server/1005-Optimize-GoalSelector-Goal.Flag-Set-operations.patch
@@ -0,0 +1,180 @@
+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 e5995d0db5dcfba59a873ff439601894fdacd556..676f5485a4ca9252e911213dcda8d51776b637b6 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
+@@ -30,10 +30,12 @@ public class GoalSelector {
+ private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap<>(Goal.Flag.class);
+ private final Set<WrappedGoal> availableGoals = Sets.newLinkedHashSet();
+ private final Supplier<ProfilerFiller> profiler;
+- private final EnumSet<Goal.Flag> disabledFlags = EnumSet.noneOf(Goal.Flag.class);
++ private final EnumSet<Goal.Flag> disabledFlags = 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
+ private int tickCount;
+ private int newGoalRate = 3;
+ private int curRate;
++ private static final Goal.Flag[] GOAL_FLAG_VALUES = Goal.Flag.values(); // Paper - remove streams from pathfindergoalselector
+
+ public GoalSelector(Supplier<ProfilerFiller> profiler) {
+ this.profiler = profiler;
+@@ -65,26 +67,32 @@ public class GoalSelector {
+ }
+ // Paper end
+ public void removeGoal(Goal goal) {
+- this.availableGoals.stream().filter((wrappedGoal) -> {
+- return wrappedGoal.getGoal() == goal;
+- }).filter(WrappedGoal::isRunning).forEach(WrappedGoal::stop);
+- this.availableGoals.removeIf((wrappedGoal) -> {
+- return wrappedGoal.getGoal() == goal;
+- });
+- }
+-
+- private static boolean goalContainsAnyFlags(WrappedGoal goal, EnumSet<Goal.Flag> controls) {
+- for(Goal.Flag flag : goal.getFlags()) {
+- if (controls.contains(flag)) {
+- return true;
++ // Paper start - remove streams from pathfindergoalselector
++ for (java.util.Iterator<WrappedGoal> iterator = this.availableGoals.iterator(); iterator.hasNext();) {
++ WrappedGoal goalWrapped = iterator.next();
++ if (goalWrapped.getGoal() != goal) {
++ continue;
+ }
++ if (goalWrapped.isRunning()) {
++ goalWrapped.stop();
++ }
++ iterator.remove();
+ }
++ // Paper end - remove streams from pathfindergoalselector
++ }
+
+- return false;
++ private static boolean goalContainsAnyFlags(WrappedGoal goal, com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<Goal.Flag> controls) {
++ return goal.getFlags().hasCommonElements(controls); // Paper
+ }
+
+ private static boolean goalCanBeReplacedForAllFlags(WrappedGoal goal, Map<Goal.Flag, WrappedGoal> goalsByControl) {
+- for(Goal.Flag flag : goal.getFlags()) {
++ // Paper start
++ 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;
+ }
+@@ -98,7 +106,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())) {
+ wrappedGoal.stop();
+ }
+ }
+@@ -116,8 +124,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);
+@@ -157,11 +171,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 6665ce5f48316e626907e6937d5ef1bc398a7ebd..51deb4455cac055ffa455e4f34aa30858d2fb448 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() {