mirror of
https://github.com/PaperMC/Paper.git
synced 2024-09-12 06:58:11 +02:00
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: 881e06e5 PR-725: Add Item Unlimited Lifetime APIs CraftBukkit Changes: 74c08312 SPIGOT-6962: Call EntityChangeBlockEvent when when FallingBlockEntity starts to fall 64db5126 SPIGOT-6959: Make /loot command ignore empty items for spawn 2d760831 Increase outdated build delay 9ed7e4fb SPIGOT-6138, SPIGOT-6415: Don't call CreatureSpawnEvent after cross-dimensional travel fc4ad813 SPIGOT-6895: Trees grown with applyBoneMeal() don't fire the StructureGrowthEvent 59733a2e SPIGOT-6961: Actually return a copy of the ItemMeta Spigot Changes: ffceeae3 SPIGOT-6956: Drop unload queue patch as attempt at fixing stop issue e19ddabd PR-1011: Add Item Unlimited Lifetime APIs 34d40b0e SPIGOT-2942: give command fires PlayerDropItemEvent, cancelling it causes Item Duplication
208 lines
10 KiB
Diff
208 lines
10 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Phoenix616 <max@themoep.de>
|
|
Date: Mon, 28 Jun 2021 22:38:29 +0100
|
|
Subject: [PATCH] Rate options and timings for sensors and behaviors
|
|
|
|
This adds config options to specify the tick rate for sensors
|
|
and behaviors of different entity types as well as timings
|
|
for those in order to be able to have some metrics as to which
|
|
ones might need tweaking.
|
|
|
|
diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java
|
|
index b47b7dce26805badd422c1867733ff4bfd00e9f4..b27021a42cbed3f0648a8d0903d00d03922ae221 100644
|
|
--- a/src/main/java/co/aikar/timings/MinecraftTimings.java
|
|
+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java
|
|
@@ -113,6 +113,14 @@ public final class MinecraftTimings {
|
|
return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType + " - " + type, tickEntityTimer);
|
|
}
|
|
|
|
+ public static Timing getBehaviorTimings(String type) {
|
|
+ return Timings.ofSafe("## Behavior - " + type);
|
|
+ }
|
|
+
|
|
+ public static Timing getSensorTimings(String type, int rate) {
|
|
+ return Timings.ofSafe("## Sensor - " + type + " (Default rate: " + rate + ")");
|
|
+ }
|
|
+
|
|
/**
|
|
* Get a named timer for the specified tile entity type to track type specific timings.
|
|
* @param entity
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
index 960240240d76d408489f5c0274d56b0496c69928..5ad05615e4dc1cc14112ab40e435a72672eedb87 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
@@ -9,8 +9,10 @@ import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
|
|
import net.minecraft.world.entity.MobCategory;
|
|
import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode;
|
|
import java.util.HashMap;
|
|
+import java.util.Locale;
|
|
import java.util.Map;
|
|
import org.bukkit.Bukkit;
|
|
+import org.bukkit.configuration.ConfigurationSection;
|
|
import org.bukkit.configuration.file.YamlConfiguration;
|
|
import org.spigotmc.SpigotWorldConfig;
|
|
|
|
@@ -883,4 +885,57 @@ public class PaperWorldConfig {
|
|
private void playerCrammingDamage() {
|
|
allowPlayerCrammingDamage = getBoolean("allow-player-cramming-damage", allowPlayerCrammingDamage);
|
|
}
|
|
+
|
|
+ private com.google.common.collect.Table<String, String, Integer> sensorTickRates;
|
|
+ private com.google.common.collect.Table<String, String, Integer> behaviorTickRates;
|
|
+ private void tickRates() {
|
|
+ config.addDefault("world-settings.default.tick-rates.sensor.villager.secondarypoisensor", 40);
|
|
+ config.addDefault("world-settings.default.tick-rates.behavior.villager.validatenearbypoi", -1); // Example
|
|
+ log("Tick rates:");
|
|
+ sensorTickRates = loadTickRates("sensor");
|
|
+ behaviorTickRates = loadTickRates("behavior");
|
|
+ }
|
|
+
|
|
+ private com.google.common.collect.Table<String, String, Integer> loadTickRates(String type) {
|
|
+ log(" " + type + ":");
|
|
+ com.google.common.collect.Table<String, String, Integer> table = com.google.common.collect.HashBasedTable.create();
|
|
+
|
|
+ ConfigurationSection typeSection = config.getConfigurationSection("world-settings." + worldName + ".tick-rates." + type);
|
|
+ if (typeSection == null) {
|
|
+ typeSection = config.getConfigurationSection("world-settings.default.tick-rates." + type);
|
|
+ }
|
|
+ if (typeSection != null) {
|
|
+ for (String entity : typeSection.getKeys(false)) {
|
|
+ ConfigurationSection entitySection = typeSection.getConfigurationSection(entity);
|
|
+ if (entitySection != null) {
|
|
+ log(" " + entity + ":");
|
|
+ for (String typeName : entitySection.getKeys(false)) {
|
|
+ if (entitySection.isInt(typeName)) {
|
|
+ int tickRate = entitySection.getInt(typeName);
|
|
+ table.put(entity.toLowerCase(Locale.ROOT), typeName.toLowerCase(Locale.ROOT), tickRate);
|
|
+ log(" " + typeName + ": " + tickRate);
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (table.isEmpty()) {
|
|
+ log(" None configured");
|
|
+ }
|
|
+ return table;
|
|
+ }
|
|
+
|
|
+ public int getBehaviorTickRate(String typeName, String entityType, int def) {
|
|
+ return getIntOrDefault(behaviorTickRates, typeName, entityType, def);
|
|
+ }
|
|
+
|
|
+ public int getSensorTickRate(String typeName, String entityType, int def) {
|
|
+ return getIntOrDefault(sensorTickRates, typeName, entityType, def);
|
|
+ }
|
|
+
|
|
+ private int getIntOrDefault(com.google.common.collect.Table<String, String, Integer> table, String rowKey, String columnKey, int def) {
|
|
+ Integer rate = table.get(columnKey, rowKey);
|
|
+ return rate != null && rate > -1 ? rate : def;
|
|
+ }
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java
|
|
index b1212e162ba938b3abe0df747a633ba9cbbe57c8..c24ff2ef1054523e58892c2b35080cffb6ab744a 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java
|
|
@@ -14,6 +14,10 @@ public abstract class Behavior<E extends LivingEntity> {
|
|
private long endTimestamp;
|
|
private final int minDuration;
|
|
private final int maxDuration;
|
|
+ // Paper start - configurable behavior tick rate and timings
|
|
+ private final String configKey;
|
|
+ private final co.aikar.timings.Timing timing;
|
|
+ // Paper end
|
|
|
|
public Behavior(Map<MemoryModuleType<?>, MemoryStatus> requiredMemoryState) {
|
|
this(requiredMemoryState, 60);
|
|
@@ -27,6 +31,15 @@ public abstract class Behavior<E extends LivingEntity> {
|
|
this.minDuration = minRunTime;
|
|
this.maxDuration = maxRunTime;
|
|
this.entryCondition = requiredMemoryState;
|
|
+ // Paper start - configurable behavior tick rate and timings
|
|
+ String key = io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(this.getClass().getName());
|
|
+ int lastSeparator = key.lastIndexOf('.');
|
|
+ if (lastSeparator != -1) {
|
|
+ key = key.substring(lastSeparator + 1);
|
|
+ }
|
|
+ this.configKey = key.toLowerCase(java.util.Locale.ROOT);
|
|
+ this.timing = co.aikar.timings.MinecraftTimings.getBehaviorTimings(configKey);
|
|
+ // Paper end
|
|
}
|
|
|
|
public Behavior.Status getStatus() {
|
|
@@ -34,11 +47,19 @@ public abstract class Behavior<E extends LivingEntity> {
|
|
}
|
|
|
|
public final boolean tryStart(ServerLevel world, E entity, long time) {
|
|
+ // Paper start - behavior tick rate
|
|
+ int tickRate = world.paperConfig.getBehaviorTickRate(this.configKey, entity.getType().id, -1);
|
|
+ if (tickRate > -1 && time < this.endTimestamp + tickRate) {
|
|
+ return false;
|
|
+ }
|
|
+ // Paper end
|
|
if (this.hasRequiredMemories(entity) && this.checkExtraStartConditions(world, entity)) {
|
|
this.status = Behavior.Status.RUNNING;
|
|
int i = this.minDuration + world.getRandom().nextInt(this.maxDuration + 1 - this.minDuration);
|
|
this.endTimestamp = time + (long)i;
|
|
+ this.timing.startTiming(); // Paper - behavior timings
|
|
this.start(world, entity, time);
|
|
+ this.timing.stopTiming(); // Paper - behavior timings
|
|
return true;
|
|
} else {
|
|
return false;
|
|
@@ -49,11 +70,13 @@ public abstract class Behavior<E extends LivingEntity> {
|
|
}
|
|
|
|
public final void tickOrStop(ServerLevel world, E entity, long time) {
|
|
+ this.timing.startTiming(); // Paper - behavior timings
|
|
if (!this.timedOut(time) && this.canStillUse(world, entity, time)) {
|
|
this.tick(world, entity, time);
|
|
} else {
|
|
this.doStop(world, entity, time);
|
|
}
|
|
+ this.timing.stopTiming(); // Paper - behavior timings
|
|
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java
|
|
index c940a910a435b20297eca493c7b27fd69be54e86..f3b8e253a5bfc3f68121dbe656ae7e2ac0f0eb1c 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java
|
|
@@ -19,8 +19,21 @@ public abstract class Sensor<E extends LivingEntity> {
|
|
private static final TargetingConditions ATTACK_TARGET_CONDITIONS_IGNORE_INVISIBILITY_AND_LINE_OF_SIGHT = TargetingConditions.forCombat().range(16.0D).ignoreLineOfSight().ignoreInvisibilityTesting();
|
|
private final int scanRate;
|
|
private long timeToTick;
|
|
+ // Paper start - configurable sensor tick rate and timings
|
|
+ private final String configKey;
|
|
+ private final co.aikar.timings.Timing timing;
|
|
+ // Paper end
|
|
|
|
public Sensor(int senseInterval) {
|
|
+ // Paper start - configurable sensor tick rate and timings
|
|
+ String key = io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(this.getClass().getName());
|
|
+ int lastSeparator = key.lastIndexOf('.');
|
|
+ if (lastSeparator != -1) {
|
|
+ key = key.substring(lastSeparator + 1);
|
|
+ }
|
|
+ this.configKey = key.toLowerCase(java.util.Locale.ROOT);
|
|
+ this.timing = co.aikar.timings.MinecraftTimings.getSensorTimings(configKey, senseInterval);
|
|
+ // Paper end
|
|
this.scanRate = senseInterval;
|
|
this.timeToTick = (long)RANDOM.nextInt(senseInterval);
|
|
}
|
|
@@ -31,8 +44,12 @@ public abstract class Sensor<E extends LivingEntity> {
|
|
|
|
public final void tick(ServerLevel world, E entity) {
|
|
if (--this.timeToTick <= 0L) {
|
|
- this.timeToTick = (long)this.scanRate;
|
|
+ // Paper start - configurable sensor tick rate and timings
|
|
+ this.timeToTick = world.paperConfig.getSensorTickRate(this.configKey, entity.getType().id, this.scanRate);
|
|
+ this.timing.startTiming();
|
|
+ // Paper end
|
|
this.doTick(world, entity);
|
|
+ this.timing.stopTiming(); // Paper - sensor timings
|
|
}
|
|
|
|
}
|