mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2025-12-27 02:49:19 +00:00
Paper PR: Optimise temptation lookups (#464)
This commit is contained in:
@@ -0,0 +1,484 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: okx-code <okx@okx.sh>
|
||||
Date: Thu, 6 Feb 2025 19:05:00 +0100
|
||||
Subject: [PATCH] Paper PR: Optimise temptation lookups
|
||||
|
||||
Both TemptGoal and TemptingSensor recheck their validity each tick.
|
||||
For this, they iterate all online players, checking their main and
|
||||
offhand items against item tags.
|
||||
This logic quickly explodes as each brain/goal selector queries all
|
||||
players.
|
||||
|
||||
This patch attempts to optimise this behaviour by lazily caching the
|
||||
results of the non-entity specific checks in a single BitSet.
|
||||
Such cache is valid for a single tick but can be re-used by each tempt
|
||||
goal or sensor sharing the same non-entity specific selection
|
||||
predicates.
|
||||
|
||||
Original license: GPLv3
|
||||
Original project: https://github.com/PaperMC/Paper
|
||||
Paper pull request: https://github.com/PaperMC/Paper/pull/11942
|
||||
|
||||
diff --git a/io/papermc/paper/entity/temptation/GlobalTemptationLookup.java b/io/papermc/paper/entity/temptation/GlobalTemptationLookup.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5f5cdfc538ba9aa6666c019df6706015234d7bae
|
||||
--- /dev/null
|
||||
+++ b/io/papermc/paper/entity/temptation/GlobalTemptationLookup.java
|
||||
@@ -0,0 +1,91 @@
|
||||
+package io.papermc.paper.entity.temptation;
|
||||
+
|
||||
+import java.util.ArrayList;
|
||||
+import java.util.BitSet;
|
||||
+import java.util.List;
|
||||
+import java.util.function.Predicate;
|
||||
+import net.minecraft.tags.ItemTags;
|
||||
+import net.minecraft.world.entity.animal.HappyGhast;
|
||||
+import net.minecraft.world.entity.animal.armadillo.ArmadilloAi;
|
||||
+import net.minecraft.world.entity.animal.axolotl.AxolotlAi;
|
||||
+import net.minecraft.world.entity.animal.camel.CamelAi;
|
||||
+import net.minecraft.world.entity.animal.frog.FrogAi;
|
||||
+import net.minecraft.world.entity.animal.goat.GoatAi;
|
||||
+import net.minecraft.world.entity.animal.sniffer.SnifferAi;
|
||||
+import net.minecraft.world.item.ItemStack;
|
||||
+import net.minecraft.world.item.Items;
|
||||
+
|
||||
+/**
|
||||
+ * The tempt state lookup holds onto cached temptation flags of players in the world.
|
||||
+ */
|
||||
+public class GlobalTemptationLookup {
|
||||
+ private static int registeredPredicateCounter = 0;
|
||||
+
|
||||
+ public static final TemptationPredicate BEE_FOOD = register(stack -> stack.is(ItemTags.BEE_FOOD));
|
||||
+ public static final TemptationPredicate CHICKEN_FOOD = register(stack -> stack.is(ItemTags.CHICKEN_FOOD));
|
||||
+ public static final TemptationPredicate COW_FOOD = register(stack -> stack.is(ItemTags.COW_FOOD));
|
||||
+ public static final TemptationPredicate PANDA_FOOD = register(stack -> stack.is(ItemTags.PANDA_FOOD));
|
||||
+ public static final TemptationPredicate PIG_CARROT_ON_A_STICK = register(stack -> stack.is(Items.CARROT_ON_A_STICK));
|
||||
+ public static final TemptationPredicate PIG = register(stack -> stack.is(ItemTags.PIG_FOOD));
|
||||
+ public static final TemptationPredicate RABBIT_FOOD = register(stack -> stack.is(ItemTags.RABBIT_FOOD));
|
||||
+ public static final TemptationPredicate SHEEP_FOOD = register(stack -> stack.is(ItemTags.SHEEP_FOOD));
|
||||
+ public static final TemptationPredicate TURTLE_FOOD = register(stack -> stack.is(ItemTags.TURTLE_FOOD));
|
||||
+ public static final TemptationPredicate HORSE_FOOD = register(stack -> stack.is(ItemTags.HORSE_TEMPT_ITEMS));
|
||||
+ public static final TemptationPredicate LLAMA_TEMPT_ITEMS = register(stack -> stack.is(ItemTags.LLAMA_TEMPT_ITEMS));
|
||||
+ public static final TemptationPredicate STRIDER_TEMPT_ITEMS = register(stack -> stack.is(ItemTags.STRIDER_TEMPT_ITEMS));
|
||||
+ public static final TemptationPredicate CAT_FOOD = register(stack -> stack.is(ItemTags.CAT_FOOD));
|
||||
+ public static final TemptationPredicate OCELOT_FOOD = register(itemStack -> itemStack.is(ItemTags.OCELOT_FOOD));
|
||||
+ public static final TemptationPredicate AXOLOTL_TEMPTATIONS = register(AxolotlAi.getTemptations());
|
||||
+ public static final TemptationPredicate GOAT_TEMPTATIONS = register(GoatAi.getTemptations());
|
||||
+ public static final TemptationPredicate FROG_TEMPTATIONS = register(FrogAi.getTemptations());
|
||||
+ public static final TemptationPredicate CAMEL_TEMPTATIONS = register(CamelAi.getTemptations());
|
||||
+ public static final TemptationPredicate ARMADILLO_TEMPTATIONS = register(ArmadilloAi.getTemptations());
|
||||
+ public static final TemptationPredicate SNIFFER_TEMPTATIONS = register(SnifferAi.getTemptations());
|
||||
+ public static final TemptationPredicate HAPPY_GHAST_TEMPTATIONS = register(HappyGhast.IS_FOOD);
|
||||
+
|
||||
+ public record TemptationPredicate(int index, Predicate<ItemStack> predicate) implements Predicate<ItemStack> {
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean test(final ItemStack itemStack) {
|
||||
+ return this.predicate.test(itemStack);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static int indexFor(final Predicate<ItemStack> predicate) {
|
||||
+ return predicate instanceof final TemptationPredicate temptationPredicate ? temptationPredicate.index() : -1;
|
||||
+ }
|
||||
+
|
||||
+ private static TemptationPredicate register(final Predicate<ItemStack> predicate) {
|
||||
+ final TemptationPredicate val = new TemptationPredicate(registeredPredicateCounter, predicate);
|
||||
+ registeredPredicateCounter++;
|
||||
+ return val;
|
||||
+ }
|
||||
+
|
||||
+ private final List<BitSet> precalculatedTemptItems = new ArrayList<>();
|
||||
+ private final BitSet calculatedThisTick = new BitSet();
|
||||
+
|
||||
+ {
|
||||
+ for (int i = 0; i < registeredPredicateCounter; i++) {
|
||||
+ this.precalculatedTemptItems.add(new BitSet());
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public void reset() {
|
||||
+ for (int i = 0; i < registeredPredicateCounter; i++) {
|
||||
+ this.precalculatedTemptItems.get(i).clear();
|
||||
+ }
|
||||
+ this.calculatedThisTick.clear();
|
||||
+ }
|
||||
+
|
||||
+ public boolean isCalculated(final int index) {
|
||||
+ return this.calculatedThisTick.get(index);
|
||||
+ }
|
||||
+
|
||||
+ public void setCalculated(final int index) {
|
||||
+ this.calculatedThisTick.set(index);
|
||||
+ }
|
||||
+
|
||||
+ public BitSet getBitSet(final int index) {
|
||||
+ return this.precalculatedTemptItems.get(index);
|
||||
+ }
|
||||
+}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index a474a8bdda00c1dbea30f0981e38ea6188b84c7a..f839c1b040f51e536b575ed5906f85a0a374b37f 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -936,6 +936,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
}
|
||||
|
||||
io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR
|
||||
+ this.globalTemptationLookup.reset(); // Paper - optimise temptation lookups - reset global cache prior to next entity tick
|
||||
|
||||
if (org.dreeam.leaf.config.modules.opt.OptimizeDespawn.enabled && tickRateManager.runsNormally()) { despawnMap.tick(this, this.entityTickList); } // Leaf - optimize despawn
|
||||
this.entityTickList
|
||||
@@ -3038,4 +3039,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
this.lagCompensationTick = (System.nanoTime() - MinecraftServer.SERVER_INIT) / (java.util.concurrent.TimeUnit.MILLISECONDS.toNanos(50L));
|
||||
}
|
||||
// Paper end - lag compensation
|
||||
+
|
||||
+ // Paper start - optimise temptation lookups
|
||||
+ private final io.papermc.paper.entity.temptation.GlobalTemptationLookup globalTemptationLookup = new io.papermc.paper.entity.temptation.GlobalTemptationLookup(); // Paper - Optimise TemptGoal
|
||||
+ public final io.papermc.paper.entity.temptation.GlobalTemptationLookup getTemptGoalLookup() {
|
||||
+ return globalTemptationLookup;
|
||||
+ }
|
||||
+ // Paper end - optimise temptation lookups
|
||||
}
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/TemptGoal.java b/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
index a805c9426630c2c46db9d0dd536f1d16769395d3..0c9a355344463ea85a3b724d22d53638b1e42394 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
@@ -30,6 +30,7 @@ public class TemptGoal extends Goal {
|
||||
private final Predicate<ItemStack> items;
|
||||
private final boolean canScare;
|
||||
private final double stopDistance;
|
||||
+ private final int globalTemptationLookupIndex; // Paper - optimise temptation checks
|
||||
|
||||
public TemptGoal(PathfinderMob mob, double speedModifier, Predicate<ItemStack> items, boolean canScare) {
|
||||
this((Mob)mob, speedModifier, items, canScare, 2.5);
|
||||
@@ -40,13 +41,14 @@ public class TemptGoal extends Goal {
|
||||
}
|
||||
|
||||
TemptGoal(Mob mob, double speedModifier, Predicate<ItemStack> items, boolean canScare, double stopDistance) {
|
||||
+ this.globalTemptationLookupIndex = io.papermc.paper.entity.temptation.GlobalTemptationLookup.indexFor(items); // Paper - optimise temptation checks
|
||||
this.mob = mob;
|
||||
this.speedModifier = speedModifier;
|
||||
this.items = items;
|
||||
this.canScare = canScare;
|
||||
this.stopDistance = stopDistance;
|
||||
this.setFlags(EnumSet.of(Goal.Flag.MOVE, Goal.Flag.LOOK));
|
||||
- this.targetingConditions = TEMPT_TARGETING.copy().selector((entity, level) -> this.shouldFollow(entity));
|
||||
+ this.targetingConditions = globalTemptationLookupIndex >= 0 ? TEMPT_TARGETING.copy() : TEMPT_TARGETING.copy().selector((entity, level) -> this.shouldFollow(entity)); // Paper - optimise temptation checks - skip selector if we have a lookup index.
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,8 +57,41 @@ public class TemptGoal extends Goal {
|
||||
this.calmDown--;
|
||||
return false;
|
||||
} else {
|
||||
+ // Paper start - optimise temptation lookups
|
||||
+ final TargetingConditions rangeTargetingConditions = this.targetingConditions.range(this.mob.getAttributeValue(Attributes.TEMPT_RANGE));
|
||||
+
|
||||
+ if (this.globalTemptationLookupIndex != -1) {
|
||||
+ final net.minecraft.server.level.ServerLevel level = getServerLevel(this.mob);
|
||||
+ final io.papermc.paper.entity.temptation.GlobalTemptationLookup lookup = level.getTemptGoalLookup();
|
||||
+ final java.util.BitSet lookupBitSet = lookup.getBitSet(this.globalTemptationLookupIndex);
|
||||
+ final java.util.List<net.minecraft.server.level.ServerPlayer> players = level.players();
|
||||
+ // Check if the lookup needs to be computed this tick. Do so for all players if needed.
|
||||
+ if (!lookup.isCalculated(this.globalTemptationLookupIndex)) {
|
||||
+ for (int i = 0; i < players.size(); i++) {
|
||||
+ lookupBitSet.set(i, shouldFollow(players.get(i)));
|
||||
+ }
|
||||
+ lookup.setCalculated(this.globalTemptationLookupIndex);
|
||||
+ }
|
||||
+ double d = -1.0;
|
||||
+ net.minecraft.server.level.ServerPlayer nearestPlayer = null;
|
||||
+ // Only iterate over players that passed #shouldFollow either in the prior computation or another goals canUse check.
|
||||
+ for (int i = lookupBitSet.nextSetBit(0); i >= 0; i = lookupBitSet.nextSetBit(i + 1)) {
|
||||
+ final net.minecraft.server.level.ServerPlayer player = players.get(i);
|
||||
+ if (rangeTargetingConditions.test(level, this.mob, player)) {
|
||||
+ final double d1 = player.distanceToSqr(this.mob.getX(), this.mob.getY(), this.mob.getZ());
|
||||
+ if (d == -1.0 || d1 < d) {
|
||||
+ d = d1;
|
||||
+ nearestPlayer = player;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ this.player = nearestPlayer;
|
||||
+ } else {
|
||||
+ // Default case for non-optimized / non vanilla tempt goal predicates.
|
||||
+ // Paper end - optimise temptation lookups
|
||||
this.player = getServerLevel(this.mob)
|
||||
.getNearestPlayer(this.targetingConditions.range(this.mob.getAttributeValue(Attributes.TEMPT_RANGE)), this.mob);
|
||||
+ } // Paper - optimise temptation lookups
|
||||
// CraftBukkit start
|
||||
if (this.player != null) {
|
||||
org.bukkit.event.entity.EntityTargetLivingEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetLivingEvent(this.mob, this.player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TEMPT);
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/SensorType.java b/net/minecraft/world/entity/ai/sensing/SensorType.java
|
||||
index 817bcaa1c09d9bd0b9856d06a8969ef583de6778..884398702e7810490743bbe74aa42fac9c661147 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/SensorType.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/SensorType.java
|
||||
@@ -39,18 +39,18 @@ public class SensorType<U extends Sensor<?>> {
|
||||
public static final SensorType<AdultSensor> NEAREST_ADULT = register("nearest_adult", AdultSensor::new);
|
||||
public static final SensorType<AdultSensor> NEAREST_ADULT_ANY_TYPE = register("nearest_adult_any_type", AdultSensorAnyType::new);
|
||||
public static final SensorType<AxolotlAttackablesSensor> AXOLOTL_ATTACKABLES = register("axolotl_attackables", AxolotlAttackablesSensor::new);
|
||||
- public static final SensorType<TemptingSensor> AXOLOTL_TEMPTATIONS = register("axolotl_temptations", () -> new TemptingSensor(AxolotlAi.getTemptations()));
|
||||
- public static final SensorType<TemptingSensor> GOAT_TEMPTATIONS = register("goat_temptations", () -> new TemptingSensor(GoatAi.getTemptations()));
|
||||
- public static final SensorType<TemptingSensor> FROG_TEMPTATIONS = register("frog_temptations", () -> new TemptingSensor(FrogAi.getTemptations()));
|
||||
- public static final SensorType<TemptingSensor> CAMEL_TEMPTATIONS = register("camel_temptations", () -> new TemptingSensor(CamelAi.getTemptations()));
|
||||
+ public static final SensorType<TemptingSensor> AXOLOTL_TEMPTATIONS = register("axolotl_temptations", () -> new TemptingSensor(io.papermc.paper.entity.temptation.GlobalTemptationLookup.AXOLOTL_TEMPTATIONS)); // Paper - optimise temptation lookups
|
||||
+ public static final SensorType<TemptingSensor> GOAT_TEMPTATIONS = register("goat_temptations", () -> new TemptingSensor(io.papermc.paper.entity.temptation.GlobalTemptationLookup.GOAT_TEMPTATIONS)); // Paper - optimise temptation lookups
|
||||
+ public static final SensorType<TemptingSensor> FROG_TEMPTATIONS = register("frog_temptations", () -> new TemptingSensor(io.papermc.paper.entity.temptation.GlobalTemptationLookup.FROG_TEMPTATIONS)); // Paper - optimise temptation lookups
|
||||
+ public static final SensorType<TemptingSensor> CAMEL_TEMPTATIONS = register("camel_temptations", () -> new TemptingSensor(io.papermc.paper.entity.temptation.GlobalTemptationLookup.CAMEL_TEMPTATIONS)); // Paper - optimise temptation lookups
|
||||
public static final SensorType<TemptingSensor> ARMADILLO_TEMPTATIONS = register(
|
||||
- "armadillo_temptations", () -> new TemptingSensor(ArmadilloAi.getTemptations())
|
||||
+ "armadillo_temptations", () -> new TemptingSensor(io.papermc.paper.entity.temptation.GlobalTemptationLookup.ARMADILLO_TEMPTATIONS) // Paper - optimise temptation lookups
|
||||
);
|
||||
- public static final SensorType<TemptingSensor> HAPPY_GHAST_TEMPTATIONS = register("happy_ghast_temptations", () -> new TemptingSensor(HappyGhast.IS_FOOD));
|
||||
+ public static final SensorType<TemptingSensor> HAPPY_GHAST_TEMPTATIONS = register("happy_ghast_temptations", () -> new TemptingSensor(io.papermc.paper.entity.temptation.GlobalTemptationLookup.HAPPY_GHAST_TEMPTATIONS)); // Paper - optimise temptation lookups
|
||||
public static final SensorType<FrogAttackablesSensor> FROG_ATTACKABLES = register("frog_attackables", FrogAttackablesSensor::new);
|
||||
public static final SensorType<IsInWaterSensor> IS_IN_WATER = register("is_in_water", IsInWaterSensor::new);
|
||||
public static final SensorType<WardenEntitySensor> WARDEN_ENTITY_SENSOR = register("warden_entity_sensor", WardenEntitySensor::new);
|
||||
- public static final SensorType<TemptingSensor> SNIFFER_TEMPTATIONS = register("sniffer_temptations", () -> new TemptingSensor(SnifferAi.getTemptations()));
|
||||
+ public static final SensorType<TemptingSensor> SNIFFER_TEMPTATIONS = register("sniffer_temptations", () -> new TemptingSensor(io.papermc.paper.entity.temptation.GlobalTemptationLookup.SNIFFER_TEMPTATIONS)); // Paper - optimise temptation lookups
|
||||
public static final SensorType<BreezeAttackEntitySensor> BREEZE_ATTACK_ENTITY_SENSOR = register(
|
||||
"breeze_attack_entity_sensor", BreezeAttackEntitySensor::new
|
||||
);
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java
|
||||
index 5919192968d7272bbf119f248def7e96a1ea359b..a88b644c7480bfa66526c697455771eb7f86ad67 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java
|
||||
@@ -19,8 +19,10 @@ import net.minecraft.world.item.ItemStack;
|
||||
public class TemptingSensor extends Sensor<PathfinderMob> {
|
||||
private static final TargetingConditions TEMPT_TARGETING = TargetingConditions.forNonCombat().ignoreLineOfSight();
|
||||
private final Predicate<ItemStack> temptations;
|
||||
+ private final int globalTemptationLookupIndex; // Paper - optimise temptation lookups
|
||||
|
||||
public TemptingSensor(Predicate<ItemStack> temptations) {
|
||||
+ this.globalTemptationLookupIndex = io.papermc.paper.entity.temptation.GlobalTemptationLookup.indexFor(temptations); // Paper - optimise temptation lookups
|
||||
this.temptations = temptations;
|
||||
}
|
||||
|
||||
@@ -28,6 +30,38 @@ public class TemptingSensor extends Sensor<PathfinderMob> {
|
||||
protected void doTick(ServerLevel level, PathfinderMob entity) {
|
||||
Brain<?> brain = entity.getBrain();
|
||||
TargetingConditions targetingConditions = TEMPT_TARGETING.copy().range((float)entity.getAttributeValue(Attributes.TEMPT_RANGE));
|
||||
+ // Paper start - optimise temptation lookups - on update, ensure below diff filters correctly
|
||||
+ Player targetPlayer;
|
||||
+ if (this.globalTemptationLookupIndex != -1) {
|
||||
+ final io.papermc.paper.entity.temptation.GlobalTemptationLookup lookup = level.getTemptGoalLookup();
|
||||
+ final java.util.BitSet lookupBitSet = lookup.getBitSet(this.globalTemptationLookupIndex);
|
||||
+ final java.util.List<net.minecraft.server.level.ServerPlayer> players = level.players();
|
||||
+ // Check if the lookup needs to be computed this tick. Do so for all players if needed.
|
||||
+ if (!lookup.isCalculated(this.globalTemptationLookupIndex)) {
|
||||
+ for (int i = 0; i < players.size(); i++) {
|
||||
+ final net.minecraft.server.level.ServerPlayer serverPlayer = players.get(i);
|
||||
+ lookupBitSet.set(i, net.minecraft.world.entity.EntitySelector.NO_SPECTATORS.test(serverPlayer) && this.playerHoldingTemptation(serverPlayer)); // check on update
|
||||
+ }
|
||||
+ lookup.setCalculated(this.globalTemptationLookupIndex);
|
||||
+ }
|
||||
+ double d = -1.0;
|
||||
+ net.minecraft.server.level.ServerPlayer nearestPlayer = null;
|
||||
+ // Only iterate over players that passed #shouldFollow either in the prior computation or another goals canUse check.
|
||||
+ for (int i = lookupBitSet.nextSetBit(0); i >= 0; i = lookupBitSet.nextSetBit(i + 1)) {
|
||||
+ final net.minecraft.server.level.ServerPlayer player = players.get(i);
|
||||
+ if (targetingConditions.test(level, entity, player) && !entity.hasPassenger(player)) { // check on update - consider non passengers
|
||||
+ final double d1 = player.distanceToSqr(entity.getX(), entity.getY(), entity.getZ());
|
||||
+ if (d == -1.0 || d1 < d) {
|
||||
+ d = d1;
|
||||
+ nearestPlayer = player;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ targetPlayer = nearestPlayer;
|
||||
+ } else {
|
||||
+ // Default case for non-optimized / non vanilla tempt goal predicates. Sorting the entire list is completely useless, but none of the vanilla logic uses this path now so
|
||||
+ // less diff and easier for updates.
|
||||
+ // Paper end - optimise temptation lookups
|
||||
// Leaf start - Remove streams in TemptingSensor
|
||||
List<net.minecraft.server.level.ServerPlayer> allPlayers = level.players();
|
||||
List<Player> list = new java.util.ArrayList<>();
|
||||
@@ -40,10 +74,12 @@ public class TemptingSensor extends Sensor<PathfinderMob> {
|
||||
}
|
||||
}
|
||||
// Leaf end - Remove streams in TemptingSensor
|
||||
-
|
||||
- if (!list.isEmpty()) {
|
||||
- list.sort(Comparator.comparingDouble(entity::distanceToSqr)); // Leaf - Remove streams in TemptingSensor
|
||||
- Player player = list.get(0);
|
||||
+ // Paper start - optimise temptation lookups
|
||||
+ targetPlayer = list.isEmpty() ? null : list.getFirst();
|
||||
+ }
|
||||
+ if (targetPlayer != null) {
|
||||
+ Player player = targetPlayer;
|
||||
+ // Paper end - optimise temptation lookups
|
||||
// CraftBukkit start
|
||||
org.bukkit.event.entity.EntityTargetLivingEntityEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityTargetLivingEvent(
|
||||
entity, player, org.bukkit.event.entity.EntityTargetEvent.TargetReason.TEMPT
|
||||
diff --git a/net/minecraft/world/entity/animal/AbstractCow.java b/net/minecraft/world/entity/animal/AbstractCow.java
|
||||
index 61e7300bbf272398b2faebf5e537d9c2ddedc6d6..832a9a56fbf870e4242d4a59ab58ed43881fdccd 100644
|
||||
--- a/net/minecraft/world/entity/animal/AbstractCow.java
|
||||
+++ b/net/minecraft/world/entity/animal/AbstractCow.java
|
||||
@@ -40,7 +40,7 @@ public abstract class AbstractCow extends Animal {
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0));
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
||||
- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, itemStack -> level().purpurConfig.cowFeedMushrooms > 0 && (itemStack.is(net.minecraft.world.level.block.Blocks.RED_MUSHROOM.asItem()) || itemStack.is(net.minecraft.world.level.block.Blocks.BROWN_MUSHROOM.asItem())) || itemStack.is(ItemTags.COW_FOOD), false)); // Purpur - Cows eat mushrooms
|
||||
+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, io.papermc.paper.entity.temptation.GlobalTemptationLookup.COW_FOOD, false)); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25));
|
||||
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
diff --git a/net/minecraft/world/entity/animal/Bee.java b/net/minecraft/world/entity/animal/Bee.java
|
||||
index eadc64f497631c048cf6a7d72e6f692763c98c6c..fb3123dc9fb8a49d2ef85bcf622a59f3cd591a19 100644
|
||||
--- a/net/minecraft/world/entity/animal/Bee.java
|
||||
+++ b/net/minecraft/world/entity/animal/Bee.java
|
||||
@@ -240,7 +240,7 @@ public class Bee extends Animal implements NeutralMob, FlyingAnimal {
|
||||
this.goalSelector.addGoal(0, new Bee.BeeAttackGoal(this, 1.4F, true));
|
||||
this.goalSelector.addGoal(1, new Bee.BeeEnterHiveGoal());
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
||||
- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, stack -> stack.is(ItemTags.BEE_FOOD), false));
|
||||
+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, io.papermc.paper.entity.temptation.GlobalTemptationLookup.BEE_FOOD, false)); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(3, new Bee.ValidateHiveGoal());
|
||||
this.goalSelector.addGoal(3, new Bee.ValidateFlowerGoal());
|
||||
this.beePollinateGoal = new Bee.BeePollinateGoal();
|
||||
diff --git a/net/minecraft/world/entity/animal/Cat.java b/net/minecraft/world/entity/animal/Cat.java
|
||||
index 14dfac12438b02ca9172a494a5730b5bf094aef1..4c0292f725845bb30782fbb6297f0e943945480c 100644
|
||||
--- a/net/minecraft/world/entity/animal/Cat.java
|
||||
+++ b/net/minecraft/world/entity/animal/Cat.java
|
||||
@@ -148,7 +148,7 @@ public class Cat extends TamableAnimal {
|
||||
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
- this.temptGoal = new Cat.CatTemptGoal(this, 0.6, stack -> stack.is(ItemTags.CAT_FOOD), true);
|
||||
+ this.temptGoal = new Cat.CatTemptGoal(this, 0.6, io.papermc.paper.entity.temptation.GlobalTemptationLookup.CAT_FOOD, true); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(1, new FloatGoal(this));
|
||||
this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
this.goalSelector.addGoal(1, new TamableAnimal.TamableAnimalPanicGoal(1.5));
|
||||
diff --git a/net/minecraft/world/entity/animal/Chicken.java b/net/minecraft/world/entity/animal/Chicken.java
|
||||
index f908d57776c533b6d42b8f3cd4da088a7ec03ed1..a5821ab8eab48fc2cd29eba857c9a624eb59290d 100644
|
||||
--- a/net/minecraft/world/entity/animal/Chicken.java
|
||||
+++ b/net/minecraft/world/entity/animal/Chicken.java
|
||||
@@ -129,7 +129,7 @@ public class Chicken extends Animal {
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
//this.goalSelector.addGoal(1, new PanicGoal(this, 1.4)); // Purpur - Chickens can retaliate - moved down
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
||||
- this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, itemStack -> itemStack.is(ItemTags.CHICKEN_FOOD), false));
|
||||
+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, io.papermc.paper.entity.temptation.GlobalTemptationLookup.CHICKEN_FOOD, false)); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.1));
|
||||
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
diff --git a/net/minecraft/world/entity/animal/Ocelot.java b/net/minecraft/world/entity/animal/Ocelot.java
|
||||
index c83d47caf8572e7f1375829f7dcb1b3b4bbf9ed0..b30cdff64f6608f20dacf36d781b00a7ba55f093 100644
|
||||
--- a/net/minecraft/world/entity/animal/Ocelot.java
|
||||
+++ b/net/minecraft/world/entity/animal/Ocelot.java
|
||||
@@ -139,7 +139,7 @@ public class Ocelot extends Animal {
|
||||
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
- this.temptGoal = new Ocelot.OcelotTemptGoal(this, 0.6, itemStack -> itemStack.is(ItemTags.OCELOT_FOOD), true);
|
||||
+ this.temptGoal = new Ocelot.OcelotTemptGoal(this, 0.6, io.papermc.paper.entity.temptation.GlobalTemptationLookup.OCELOT_FOOD, true); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(1, new FloatGoal(this));
|
||||
this.goalSelector.addGoal(1, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
this.goalSelector.addGoal(3, this.temptGoal);
|
||||
diff --git a/net/minecraft/world/entity/animal/Panda.java b/net/minecraft/world/entity/animal/Panda.java
|
||||
index c4cfcab5be629e83c0418bcb9ef1062bc8459af9..92069cde887889e1fcb35d597445d6102512756a 100644
|
||||
--- a/net/minecraft/world/entity/animal/Panda.java
|
||||
+++ b/net/minecraft/world/entity/animal/Panda.java
|
||||
@@ -319,7 +319,7 @@ public class Panda extends Animal {
|
||||
this.goalSelector.addGoal(2, new Panda.PandaPanicGoal(this, 2.0));
|
||||
this.goalSelector.addGoal(2, new Panda.PandaBreedGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(3, new Panda.PandaAttackGoal(this, 1.2F, true));
|
||||
- this.goalSelector.addGoal(4, new TemptGoal(this, 1.0, stack -> stack.is(ItemTags.PANDA_FOOD), false));
|
||||
+ this.goalSelector.addGoal(4, new TemptGoal(this, 1.0, io.papermc.paper.entity.temptation.GlobalTemptationLookup.PANDA_FOOD, false)); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(6, new Panda.PandaAvoidGoal<>(this, Player.class, 8.0F, 2.0, 2.0));
|
||||
this.goalSelector.addGoal(6, new Panda.PandaAvoidGoal<>(this, Monster.class, 4.0F, 2.0, 2.0));
|
||||
this.goalSelector.addGoal(7, new Panda.PandaSitGoal());
|
||||
diff --git a/net/minecraft/world/entity/animal/Pig.java b/net/minecraft/world/entity/animal/Pig.java
|
||||
index fbda6b378f9fc8fe97f4282326f86ea9633a5c98..a5ad5c232c778baa76ce023daa497e8dce3aadf2 100644
|
||||
--- a/net/minecraft/world/entity/animal/Pig.java
|
||||
+++ b/net/minecraft/world/entity/animal/Pig.java
|
||||
@@ -118,8 +118,8 @@ public class Pig extends Animal implements ItemSteerable {
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
this.goalSelector.addGoal(1, new PanicGoal(this, 1.25));
|
||||
this.goalSelector.addGoal(3, new BreedGoal(this, 1.0));
|
||||
- this.goalSelector.addGoal(4, new TemptGoal(this, 1.2, itemStack -> itemStack.is(Items.CARROT_ON_A_STICK), false));
|
||||
- this.goalSelector.addGoal(4, new TemptGoal(this, 1.2, itemStack -> itemStack.is(ItemTags.PIG_FOOD), false));
|
||||
+ this.goalSelector.addGoal(4, new TemptGoal(this, 1.2, io.papermc.paper.entity.temptation.GlobalTemptationLookup.PIG_CARROT_ON_A_STICK, false)); // Paper - optimise temptation lookups
|
||||
+ this.goalSelector.addGoal(4, new TemptGoal(this, 1.2, io.papermc.paper.entity.temptation.GlobalTemptationLookup.PIG, false)); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.1));
|
||||
this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(7, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
diff --git a/net/minecraft/world/entity/animal/Rabbit.java b/net/minecraft/world/entity/animal/Rabbit.java
|
||||
index c0a63a8d1a3c33d9d151aaf3131ea583f4f48588..311dea7e2231e00ff439220a47dd4449b85d0d50 100644
|
||||
--- a/net/minecraft/world/entity/animal/Rabbit.java
|
||||
+++ b/net/minecraft/world/entity/animal/Rabbit.java
|
||||
@@ -181,7 +181,7 @@ public class Rabbit extends Animal {
|
||||
this.goalSelector.addGoal(1, new ClimbOnTopOfPowderSnowGoal(this, this.level()));
|
||||
this.goalSelector.addGoal(1, new Rabbit.RabbitPanicGoal(this, 2.2));
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 0.8));
|
||||
- this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, stack -> stack.is(ItemTags.RABBIT_FOOD), false));
|
||||
+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, io.papermc.paper.entity.temptation.GlobalTemptationLookup.RABBIT_FOOD, false)); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(4, new Rabbit.RabbitAvoidEntityGoal<>(this, Player.class, 8.0F, 2.2, 2.2));
|
||||
this.goalSelector.addGoal(4, new Rabbit.RabbitAvoidEntityGoal<>(this, Wolf.class, 10.0F, 2.2, 2.2));
|
||||
this.goalSelector.addGoal(4, new Rabbit.RabbitAvoidEntityGoal<>(this, Monster.class, 4.0F, 2.2, 2.2));
|
||||
diff --git a/net/minecraft/world/entity/animal/Turtle.java b/net/minecraft/world/entity/animal/Turtle.java
|
||||
index 0065a43871605c8d2a8b29d1aed174aeed8be3b2..59800c502c46c82cedde0f67e3848d7ba02cc479 100644
|
||||
--- a/net/minecraft/world/entity/animal/Turtle.java
|
||||
+++ b/net/minecraft/world/entity/animal/Turtle.java
|
||||
@@ -195,7 +195,7 @@ public class Turtle extends Animal {
|
||||
this.goalSelector.addGoal(0, new Turtle.TurtlePanicGoal(this, 1.2));
|
||||
this.goalSelector.addGoal(1, new Turtle.TurtleBreedGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(1, new Turtle.TurtleLayEggGoal(this, 1.0));
|
||||
- this.goalSelector.addGoal(2, new TemptGoal(this, 1.1, itemStack -> itemStack.is(ItemTags.TURTLE_FOOD), false));
|
||||
+ this.goalSelector.addGoal(2, new TemptGoal(this, 1.1, io.papermc.paper.entity.temptation.GlobalTemptationLookup.TURTLE_FOOD, false)); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(3, new Turtle.TurtleGoToWaterGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(4, new Turtle.TurtleGoHomeGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(7, new Turtle.TurtleTravelGoal(this, 1.0));
|
||||
diff --git a/net/minecraft/world/entity/animal/horse/AbstractHorse.java b/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
||||
index d3b21d7c54349045c29df09602bda9d7a7eaec52..3ce7e02b91d40170e040554cd601167b66ba602a 100644
|
||||
--- a/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
||||
+++ b/net/minecraft/world/entity/animal/horse/AbstractHorse.java
|
||||
@@ -199,7 +199,7 @@ public abstract class AbstractHorse extends Animal implements HasCustomInventory
|
||||
|
||||
protected void addBehaviourGoals() {
|
||||
this.goalSelector.addGoal(0, new FloatGoal(this));
|
||||
- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, stack -> stack.is(ItemTags.HORSE_TEMPT_ITEMS), false));
|
||||
+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, io.papermc.paper.entity.temptation.GlobalTemptationLookup.HORSE_FOOD, false)); // Paper - optimise temptation lookups
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/net/minecraft/world/entity/animal/horse/Llama.java b/net/minecraft/world/entity/animal/horse/Llama.java
|
||||
index 455a84ffa16152137409777e1fddbab5a21bd57d..36a0dcf58dd2e7c014c2d2924941a3773f3bd3a4 100644
|
||||
--- a/net/minecraft/world/entity/animal/horse/Llama.java
|
||||
+++ b/net/minecraft/world/entity/animal/horse/Llama.java
|
||||
@@ -222,7 +222,7 @@ public class Llama extends AbstractChestedHorse implements RangedAttackMob {
|
||||
this.goalSelector.addGoal(3, new RangedAttackGoal(this, 1.25, 40, 20.0F));
|
||||
this.goalSelector.addGoal(3, new PanicGoal(this, 1.2));
|
||||
this.goalSelector.addGoal(4, new BreedGoal(this, 1.0));
|
||||
- this.goalSelector.addGoal(5, new TemptGoal(this, 1.25, itemStack -> itemStack.is(ItemTags.LLAMA_TEMPT_ITEMS), false));
|
||||
+ this.goalSelector.addGoal(5, new TemptGoal(this, 1.25, io.papermc.paper.entity.temptation.GlobalTemptationLookup.LLAMA_TEMPT_ITEMS, false)); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(6, new FollowParentGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 0.7));
|
||||
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
diff --git a/net/minecraft/world/entity/animal/sheep/Sheep.java b/net/minecraft/world/entity/animal/sheep/Sheep.java
|
||||
index d0b40c1186328b501e1847f29283023b81eeddc3..96a71acbed44df67c7d0da36b601c8e54159fd3f 100644
|
||||
--- a/net/minecraft/world/entity/animal/sheep/Sheep.java
|
||||
+++ b/net/minecraft/world/entity/animal/sheep/Sheep.java
|
||||
@@ -115,7 +115,7 @@ public class Sheep extends Animal implements Shearable {
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
this.goalSelector.addGoal(1, new PanicGoal(this, 1.25));
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
||||
- this.goalSelector.addGoal(3, new TemptGoal(this, 1.1, stack -> stack.is(ItemTags.SHEEP_FOOD), false));
|
||||
+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.1, io.papermc.paper.entity.temptation.GlobalTemptationLookup.SHEEP_FOOD, false)); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.1));
|
||||
this.goalSelector.addGoal(5, this.eatBlockGoal);
|
||||
this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
||||
diff --git a/net/minecraft/world/entity/monster/Strider.java b/net/minecraft/world/entity/monster/Strider.java
|
||||
index 4a4f3ed5dbc6b1934b2901c3a21597ba783b1806..8fcdc4452360a1909b788eda8fe2509b0b4f6de8 100644
|
||||
--- a/net/minecraft/world/entity/monster/Strider.java
|
||||
+++ b/net/minecraft/world/entity/monster/Strider.java
|
||||
@@ -179,7 +179,7 @@ public class Strider extends Animal implements ItemSteerable {
|
||||
this.goalSelector.addGoal(1, new PanicGoal(this, 1.65));
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
||||
- this.temptGoal = new TemptGoal(this, 1.4, itemStack -> itemStack.is(ItemTags.STRIDER_TEMPT_ITEMS), false);
|
||||
+ this.temptGoal = new TemptGoal(this, 1.4, io.papermc.paper.entity.temptation.GlobalTemptationLookup.STRIDER_TEMPT_ITEMS, false); // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(3, this.temptGoal);
|
||||
this.goalSelector.addGoal(4, new Strider.StriderGoToLavaGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.0));
|
||||
@@ -0,0 +1,182 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: hayanesuru <hayanesuru@outlook.jp>
|
||||
Date: Fri, 15 Aug 2025 16:16:08 +0900
|
||||
Subject: [PATCH] fix temptation lookups
|
||||
|
||||
|
||||
diff --git a/io/papermc/paper/entity/temptation/GlobalTemptationLookup.java b/io/papermc/paper/entity/temptation/GlobalTemptationLookup.java
|
||||
index 5f5cdfc538ba9aa6666c019df6706015234d7bae..e7c0fd59b4b64b3e60887ddae63e2f1a4ddd752f 100644
|
||||
--- a/io/papermc/paper/entity/temptation/GlobalTemptationLookup.java
|
||||
+++ b/io/papermc/paper/entity/temptation/GlobalTemptationLookup.java
|
||||
@@ -1,9 +1,12 @@
|
||||
package io.papermc.paper.entity.temptation;
|
||||
|
||||
-import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
+
|
||||
+import it.unimi.dsi.fastutil.objects.ObjectArrays;
|
||||
+import net.minecraft.server.level.ServerLevel;
|
||||
+import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.tags.ItemTags;
|
||||
import net.minecraft.world.entity.animal.HappyGhast;
|
||||
import net.minecraft.world.entity.animal.armadillo.ArmadilloAi;
|
||||
@@ -24,6 +27,7 @@ public class GlobalTemptationLookup {
|
||||
public static final TemptationPredicate BEE_FOOD = register(stack -> stack.is(ItemTags.BEE_FOOD));
|
||||
public static final TemptationPredicate CHICKEN_FOOD = register(stack -> stack.is(ItemTags.CHICKEN_FOOD));
|
||||
public static final TemptationPredicate COW_FOOD = register(stack -> stack.is(ItemTags.COW_FOOD));
|
||||
+ public static final TemptationPredicate COW_FOOD_MUSHROOM = register(stack -> stack.is(Items.RED_MUSHROOM) || stack.is(Items.BROWN_MUSHROOM) || stack.is(ItemTags.COW_FOOD));
|
||||
public static final TemptationPredicate PANDA_FOOD = register(stack -> stack.is(ItemTags.PANDA_FOOD));
|
||||
public static final TemptationPredicate PIG_CARROT_ON_A_STICK = register(stack -> stack.is(Items.CARROT_ON_A_STICK));
|
||||
public static final TemptationPredicate PIG = register(stack -> stack.is(ItemTags.PIG_FOOD));
|
||||
@@ -61,20 +65,34 @@ public class GlobalTemptationLookup {
|
||||
return val;
|
||||
}
|
||||
|
||||
- private final List<BitSet> precalculatedTemptItems = new ArrayList<>();
|
||||
+ private final BitSet[] precalculatedTemptItems;
|
||||
private final BitSet calculatedThisTick = new BitSet();
|
||||
+ private static final ServerPlayer[] EMPTY_PLAYERS = {};
|
||||
+ private ServerPlayer[] players = EMPTY_PLAYERS;
|
||||
|
||||
{
|
||||
- for (int i = 0; i < registeredPredicateCounter; i++) {
|
||||
- this.precalculatedTemptItems.add(new BitSet());
|
||||
+ precalculatedTemptItems = new BitSet[registeredPredicateCounter];
|
||||
+ for (int i = 0; i < precalculatedTemptItems.length; i++) {
|
||||
+ this.precalculatedTemptItems[i] = new BitSet();
|
||||
}
|
||||
}
|
||||
|
||||
- public void reset() {
|
||||
+ public void tick(final ServerLevel world) {
|
||||
for (int i = 0; i < registeredPredicateCounter; i++) {
|
||||
- this.precalculatedTemptItems.get(i).clear();
|
||||
+ this.precalculatedTemptItems[i].clear();
|
||||
+ this.calculatedThisTick.clear();
|
||||
+ }
|
||||
+
|
||||
+ int j = 0;
|
||||
+ final ServerPlayer[] array = world.players().toArray(EMPTY_PLAYERS);
|
||||
+ for (int i = 0; i < array.length; i++) {
|
||||
+ final ServerPlayer p = array[i];
|
||||
+ if (!p.isSpectator() && p.isAlive()) {
|
||||
+ array[j] = p;
|
||||
+ j++;
|
||||
+ }
|
||||
}
|
||||
- this.calculatedThisTick.clear();
|
||||
+ this.players = ObjectArrays.setLength(array, j);
|
||||
}
|
||||
|
||||
public boolean isCalculated(final int index) {
|
||||
@@ -86,6 +104,10 @@ public class GlobalTemptationLookup {
|
||||
}
|
||||
|
||||
public BitSet getBitSet(final int index) {
|
||||
- return this.precalculatedTemptItems.get(index);
|
||||
+ return this.precalculatedTemptItems[index];
|
||||
+ }
|
||||
+
|
||||
+ public ServerPlayer[] players() {
|
||||
+ return this.players;
|
||||
}
|
||||
}
|
||||
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
|
||||
index f839c1b040f51e536b575ed5906f85a0a374b37f..03cedc642cccf9d92f5755bec367f53f084c81f6 100644
|
||||
--- a/net/minecraft/server/level/ServerLevel.java
|
||||
+++ b/net/minecraft/server/level/ServerLevel.java
|
||||
@@ -936,7 +936,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
|
||||
}
|
||||
|
||||
io.papermc.paper.entity.activation.ActivationRange.activateEntities(this); // Paper - EAR
|
||||
- this.globalTemptationLookup.reset(); // Paper - optimise temptation lookups - reset global cache prior to next entity tick
|
||||
+ this.globalTemptationLookup.tick(this); // Paper - optimise temptation lookups - reset global cache prior to next entity tick
|
||||
|
||||
if (org.dreeam.leaf.config.modules.opt.OptimizeDespawn.enabled && tickRateManager.runsNormally()) { despawnMap.tick(this, this.entityTickList); } // Leaf - optimize despawn
|
||||
this.entityTickList
|
||||
diff --git a/net/minecraft/world/entity/ai/goal/TemptGoal.java b/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
index 0c9a355344463ea85a3b724d22d53638b1e42394..7cb94eb75a1de0cef02d4953ee5896bd5e3c7abd 100644
|
||||
--- a/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
+++ b/net/minecraft/world/entity/ai/goal/TemptGoal.java
|
||||
@@ -64,21 +64,25 @@ public class TemptGoal extends Goal {
|
||||
final net.minecraft.server.level.ServerLevel level = getServerLevel(this.mob);
|
||||
final io.papermc.paper.entity.temptation.GlobalTemptationLookup lookup = level.getTemptGoalLookup();
|
||||
final java.util.BitSet lookupBitSet = lookup.getBitSet(this.globalTemptationLookupIndex);
|
||||
- final java.util.List<net.minecraft.server.level.ServerPlayer> players = level.players();
|
||||
+ final net.minecraft.server.level.ServerPlayer[] players = lookup.players();
|
||||
// Check if the lookup needs to be computed this tick. Do so for all players if needed.
|
||||
if (!lookup.isCalculated(this.globalTemptationLookupIndex)) {
|
||||
- for (int i = 0; i < players.size(); i++) {
|
||||
- lookupBitSet.set(i, shouldFollow(players.get(i)));
|
||||
+ for (int i = 0; i < players.length; i++) {
|
||||
+ lookupBitSet.set(i, shouldFollow(players[i]));
|
||||
}
|
||||
lookup.setCalculated(this.globalTemptationLookupIndex);
|
||||
}
|
||||
double d = -1.0;
|
||||
net.minecraft.server.level.ServerPlayer nearestPlayer = null;
|
||||
// Only iterate over players that passed #shouldFollow either in the prior computation or another goals canUse check.
|
||||
+ final Mob mob = this.mob;
|
||||
+ final double mobX = mob.getX();
|
||||
+ final double mobY = mob.getY();
|
||||
+ final double mobZ = mob.getZ();
|
||||
for (int i = lookupBitSet.nextSetBit(0); i >= 0; i = lookupBitSet.nextSetBit(i + 1)) {
|
||||
- final net.minecraft.server.level.ServerPlayer player = players.get(i);
|
||||
- if (rangeTargetingConditions.test(level, this.mob, player)) {
|
||||
- final double d1 = player.distanceToSqr(this.mob.getX(), this.mob.getY(), this.mob.getZ());
|
||||
+ final net.minecraft.server.level.ServerPlayer player = players[i];
|
||||
+ if (rangeTargetingConditions.test(level, mob, player)) {
|
||||
+ final double d1 = player.distanceToSqr(mobX, mobY, mobZ);
|
||||
if (d == -1.0 || d1 < d) {
|
||||
d = d1;
|
||||
nearestPlayer = player;
|
||||
diff --git a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java
|
||||
index a88b644c7480bfa66526c697455771eb7f86ad67..58c22828b62323ed99b7b1a9e3c1196aaf619786 100644
|
||||
--- a/net/minecraft/world/entity/ai/sensing/TemptingSensor.java
|
||||
+++ b/net/minecraft/world/entity/ai/sensing/TemptingSensor.java
|
||||
@@ -35,11 +35,11 @@ public class TemptingSensor extends Sensor<PathfinderMob> {
|
||||
if (this.globalTemptationLookupIndex != -1) {
|
||||
final io.papermc.paper.entity.temptation.GlobalTemptationLookup lookup = level.getTemptGoalLookup();
|
||||
final java.util.BitSet lookupBitSet = lookup.getBitSet(this.globalTemptationLookupIndex);
|
||||
- final java.util.List<net.minecraft.server.level.ServerPlayer> players = level.players();
|
||||
+ final net.minecraft.server.level.ServerPlayer[] players = lookup.players();
|
||||
// Check if the lookup needs to be computed this tick. Do so for all players if needed.
|
||||
if (!lookup.isCalculated(this.globalTemptationLookupIndex)) {
|
||||
- for (int i = 0; i < players.size(); i++) {
|
||||
- final net.minecraft.server.level.ServerPlayer serverPlayer = players.get(i);
|
||||
+ for (int i = 0; i < players.length; i++) {
|
||||
+ final net.minecraft.server.level.ServerPlayer serverPlayer = players[i];
|
||||
lookupBitSet.set(i, net.minecraft.world.entity.EntitySelector.NO_SPECTATORS.test(serverPlayer) && this.playerHoldingTemptation(serverPlayer)); // check on update
|
||||
}
|
||||
lookup.setCalculated(this.globalTemptationLookupIndex);
|
||||
@@ -47,10 +47,13 @@ public class TemptingSensor extends Sensor<PathfinderMob> {
|
||||
double d = -1.0;
|
||||
net.minecraft.server.level.ServerPlayer nearestPlayer = null;
|
||||
// Only iterate over players that passed #shouldFollow either in the prior computation or another goals canUse check.
|
||||
+ final double entityX = entity.getX();
|
||||
+ final double entityY = entity.getY();
|
||||
+ final double entityZ = entity.getZ();
|
||||
for (int i = lookupBitSet.nextSetBit(0); i >= 0; i = lookupBitSet.nextSetBit(i + 1)) {
|
||||
- final net.minecraft.server.level.ServerPlayer player = players.get(i);
|
||||
+ final net.minecraft.server.level.ServerPlayer player = players[i];
|
||||
if (targetingConditions.test(level, entity, player) && !entity.hasPassenger(player)) { // check on update - consider non passengers
|
||||
- final double d1 = player.distanceToSqr(entity.getX(), entity.getY(), entity.getZ());
|
||||
+ final double d1 = player.distanceToSqr(entityX, entityY, entityZ);
|
||||
if (d == -1.0 || d1 < d) {
|
||||
d = d1;
|
||||
nearestPlayer = player;
|
||||
diff --git a/net/minecraft/world/entity/animal/AbstractCow.java b/net/minecraft/world/entity/animal/AbstractCow.java
|
||||
index 832a9a56fbf870e4242d4a59ab58ed43881fdccd..48441154ff7cbfea714ba88ac31910d0419644a8 100644
|
||||
--- a/net/minecraft/world/entity/animal/AbstractCow.java
|
||||
+++ b/net/minecraft/world/entity/animal/AbstractCow.java
|
||||
@@ -40,7 +40,7 @@ public abstract class AbstractCow extends Animal {
|
||||
this.goalSelector.addGoal(0, new org.purpurmc.purpur.entity.ai.HasRider(this)); // Purpur - Ridables
|
||||
this.goalSelector.addGoal(1, new PanicGoal(this, 2.0));
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
||||
- this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, io.papermc.paper.entity.temptation.GlobalTemptationLookup.COW_FOOD, false)); // Paper - optimise temptation lookups
|
||||
+ this.goalSelector.addGoal(3, new TemptGoal(this, 1.25, level().purpurConfig.cowFeedMushrooms > 0 ? io.papermc.paper.entity.temptation.GlobalTemptationLookup.COW_FOOD_MUSHROOM : io.papermc.paper.entity.temptation.GlobalTemptationLookup.COW_FOOD, false)); // Purpur - Cows eat mushrooms // Paper - optimise temptation lookups
|
||||
this.goalSelector.addGoal(4, new FollowParentGoal(this, 1.25));
|
||||
this.goalSelector.addGoal(5, new WaterAvoidingRandomStrollGoal(this, 1.0));
|
||||
this.goalSelector.addGoal(6, new LookAtPlayerGoal(this, Player.class, 6.0F));
|
||||
Reference in New Issue
Block a user