mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-19 15:09:25 +00:00
194 lines
9.4 KiB
Diff
194 lines
9.4 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: hayanesuru <hayanesuru@outlook.jp>
|
|
Date: Fri, 15 Aug 2025 15:02:27 +0900
|
|
Subject: [PATCH] optimize goal selector
|
|
|
|
|
|
diff --git a/net/minecraft/world/entity/ai/goal/Goal.java b/net/minecraft/world/entity/ai/goal/Goal.java
|
|
index f54bbe2e65b18f214266769c7a64144baafa9a58..40d53e4469a71b33949ee2bd7b01783d343d4134 100644
|
|
--- a/net/minecraft/world/entity/ai/goal/Goal.java
|
|
+++ b/net/minecraft/world/entity/ai/goal/Goal.java
|
|
@@ -100,10 +100,12 @@ public abstract class Goal {
|
|
// Paper end - Mob goal api
|
|
|
|
public static enum Flag {
|
|
+ // Leaf - optimize goal selector - diff on change
|
|
UNKNOWN_BEHAVIOR, // Paper - add UNKNOWN_BEHAVIOR
|
|
MOVE,
|
|
LOOK,
|
|
JUMP,
|
|
TARGET;
|
|
+ // Leaf - optimize goal selector - diff on change
|
|
}
|
|
}
|
|
diff --git a/net/minecraft/world/entity/ai/goal/GoalSelector.java b/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
|
index 653c58c7637c46c8b46a5082f671324a2221d431..15b6781d110b7dc95c6dfb576e5258e7457b5e2f 100644
|
|
--- a/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
|
+++ b/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
|
@@ -20,10 +20,12 @@ public class GoalSelector {
|
|
}
|
|
};
|
|
private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap<>(Goal.Flag.class);
|
|
- private final Set<WrappedGoal> availableGoals = new ObjectLinkedOpenHashSet<>();
|
|
+ private final org.dreeam.leaf.util.map.BinaryGoalSet leaf$availableGoals = new org.dreeam.leaf.util.map.BinaryGoalSet(); // Leaf - optimize goal selector
|
|
+ private final Set<WrappedGoal> availableGoals = leaf$availableGoals; // Leaf - optimize goal selector
|
|
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
|
|
+ private final int[] lockedPriorities = new int[GOAL_FLAG_VALUES.length]; // Leaf - optimize goal selector
|
|
|
|
public void addGoal(int priority, Goal goal) {
|
|
this.availableGoals.add(new WrappedGoal(priority, goal));
|
|
@@ -40,7 +42,12 @@ public class GoalSelector {
|
|
}
|
|
|
|
public boolean hasTasks() {
|
|
- for (WrappedGoal task : this.availableGoals) {
|
|
+ // Leaf start - optimize goal selector
|
|
+ org.dreeam.leaf.util.map.BinaryGoalSet availableGoals = this.leaf$availableGoals;
|
|
+ WrappedGoal[] elements = availableGoals.elements();
|
|
+ for (int i = 0, j = availableGoals.size(); i < j; i++) {
|
|
+ WrappedGoal task = elements[i];
|
|
+ // Leaf end - optimize goal selector
|
|
if (task.isRunning()) {
|
|
return true;
|
|
}
|
|
@@ -50,7 +57,12 @@ public class GoalSelector {
|
|
// Paper end - EAR 2
|
|
|
|
public void removeGoal(Goal goal) {
|
|
- for (WrappedGoal wrappedGoal : this.availableGoals) {
|
|
+ // Leaf start - optimize goal selector
|
|
+ org.dreeam.leaf.util.map.BinaryGoalSet availableGoals = this.leaf$availableGoals;
|
|
+ WrappedGoal[] elements = availableGoals.elements();
|
|
+ for (int i = 0, j = availableGoals.size(); i < j; i++) {
|
|
+ WrappedGoal wrappedGoal = elements[i];
|
|
+ // Leaf end - optimize goal selector
|
|
if (wrappedGoal.getGoal() == goal && wrappedGoal.isRunning()) {
|
|
wrappedGoal.stop();
|
|
}
|
|
@@ -80,37 +92,81 @@ public class GoalSelector {
|
|
}
|
|
|
|
public void tick() {
|
|
- for (WrappedGoal wrappedGoal : this.availableGoals) {
|
|
- if (wrappedGoal.isRunning() && (goalContainsAnyFlags(wrappedGoal, this.goalTypes) || !wrappedGoal.canContinueToUse())) { // Paper - Perf: optimize goal types by removing streams
|
|
- wrappedGoal.stop();
|
|
+ // Leaf start - optimize goal selector
|
|
+ final org.dreeam.leaf.util.map.BinaryGoalSet availableGoals = this.leaf$availableGoals;
|
|
+ final WrappedGoal[] elements = availableGoals.elements();
|
|
+ final long disabled = this.goalTypes.getBackingSet();
|
|
+ final int elemSize = availableGoals.size();
|
|
+ final Map<Goal.Flag, WrappedGoal> lockedFlags = this.lockedFlags;
|
|
+ final int[] lockedPriorities = this.lockedPriorities;
|
|
+ long mask = 0L;
|
|
+
|
|
+ for (int i = 0; i < elemSize; i++) {
|
|
+ final WrappedGoal goal = elements[i];
|
|
+ if (goal.isRunning() && ((disabled & goal.goal.getFlags().getBackingSet()) != 0 || !goal.canContinueToUse())) {
|
|
+ goal.stop();
|
|
}
|
|
}
|
|
-
|
|
- this.lockedFlags.entrySet().removeIf(entry -> !entry.getValue().isRunning());
|
|
-
|
|
- for (WrappedGoal wrappedGoalx : this.availableGoals) {
|
|
- // 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);
|
|
+ for (int i = 0; i < GOAL_FLAG_VALUES.length; i++) {
|
|
+ final Goal.Flag flag = GOAL_FLAG_VALUES[i];
|
|
+ final WrappedGoal locked = lockedFlags.get(flag);
|
|
+ if (locked == null) {
|
|
+ lockedPriorities[i] = Integer.MAX_VALUE;
|
|
+ } else if (!locked.isRunning()) {
|
|
+ lockedFlags.remove(flag);
|
|
+ lockedPriorities[i] = Integer.MAX_VALUE;
|
|
+ } else {
|
|
+ lockedPriorities[i] = locked.isInterruptable()
|
|
+ ? locked.getPriority()
|
|
+ : Integer.MIN_VALUE;
|
|
+ mask |= (1L << i);
|
|
+ }
|
|
+ }
|
|
+ for (int i = 0; i < elemSize; i++) {
|
|
+ final WrappedGoal goal = elements[i];
|
|
+ if (goal.isRunning()) {
|
|
+ continue;
|
|
+ }
|
|
+ final long f = goal.goal.getFlags().getBackingSet();
|
|
+ final int p = goal.getPriority();
|
|
+ if ((disabled & f) != 0L
|
|
+ || (f & mask) != 0L
|
|
+ && ((f & 1L) != 0L && p >= lockedPriorities[0]
|
|
+ || (f & 2L) != 0L && p >= lockedPriorities[1]
|
|
+ || (f & 4L) != 0L && p >= lockedPriorities[2]
|
|
+ || (f & 8L) != 0L && p >= lockedPriorities[3]
|
|
+ || (f & 16L) != 0L && p >= lockedPriorities[4])) {
|
|
+ continue;
|
|
+ } else if (!goal.canUse()) {
|
|
+ continue;
|
|
+ }
|
|
+ for (long iter = f; iter != 0L; iter &= iter - 1) {
|
|
+ final int j = Long.numberOfTrailingZeros(iter);
|
|
+ final Goal.Flag flag = GOAL_FLAG_VALUES[j];
|
|
+ final WrappedGoal locked = lockedFlags.get(flag);
|
|
+ if (locked != null) {
|
|
+ locked.stop();
|
|
}
|
|
-
|
|
- wrappedGoalx.start();
|
|
+ lockedFlags.put(flag, goal);
|
|
+ lockedPriorities[j] = goal.isInterruptable()
|
|
+ ? goal.getPriority()
|
|
+ : Integer.MIN_VALUE;
|
|
+ mask |= (1L << j);
|
|
}
|
|
+ goal.start();
|
|
}
|
|
+ // Leaf end - optimize goal selector
|
|
|
|
this.tickRunningGoals(true);
|
|
}
|
|
|
|
public void tickRunningGoals(boolean tickAllRunning) {
|
|
- for (WrappedGoal wrappedGoal : this.availableGoals) {
|
|
+ // Leaf start - optimize goal selector
|
|
+ org.dreeam.leaf.util.map.BinaryGoalSet availableGoals = this.leaf$availableGoals;
|
|
+ WrappedGoal[] elements = availableGoals.elements();
|
|
+ for (int i = 0, j = availableGoals.size(); i < j; i++) {
|
|
+ WrappedGoal wrappedGoal = elements[i];
|
|
+ // Leaf end - optimize goal selector
|
|
if (wrappedGoal.isRunning() && (tickAllRunning || wrappedGoal.requiresUpdateEveryTick())) {
|
|
wrappedGoal.tick();
|
|
}
|
|
diff --git a/net/minecraft/world/entity/ai/goal/WrappedGoal.java b/net/minecraft/world/entity/ai/goal/WrappedGoal.java
|
|
index 2c2ab6a1df9d3d23773e44ce4041cc1c21b55163..f5ef2e26ff4f9207fc56abe95fe68b3f166499bd 100644
|
|
--- a/net/minecraft/world/entity/ai/goal/WrappedGoal.java
|
|
+++ b/net/minecraft/world/entity/ai/goal/WrappedGoal.java
|
|
@@ -4,7 +4,7 @@ import java.util.EnumSet;
|
|
import javax.annotation.Nullable;
|
|
|
|
public class WrappedGoal extends Goal {
|
|
- private final Goal goal;
|
|
+ public final Goal goal; // Leaf - optimize goal selector - private -> public
|
|
private final int priority;
|
|
private boolean isRunning;
|
|
|
|
@@ -70,6 +70,7 @@ public class WrappedGoal extends Goal {
|
|
|
|
@Override
|
|
public ca.spottedleaf.moonrise.common.set.OptimizedSmallEnumSet<Goal.Flag> getFlags() { // Paper - remove streams from GoalSelector
|
|
+ // Leaf - optimize goal selector - diff on change
|
|
return this.goal.getFlags();
|
|
}
|
|
|