mirror of
https://github.com/PaperMC/Paper.git
synced 2024-10-30 23:39:58 +01:00
aa52bf9e33
Mojang made some changes to priorities in 1.17 and it seems that these changes conflict with the changes made in this patch, which in some cases appears to cause excessive rescheduling of tasks. This, however, is not confirmed as such but seems to be the behavior that we're seeing to cause this issue, if mojang has adopted the changes we suggested, then a good chunk of this patch may be unneeded, but, this needs a much better look than I'm currently able to do
218 lines
10 KiB
Diff
218 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 b9cdbf8acccfd6b207a0116f068168f3b8c8e17d..8c883d2f88acc731734a121ebb76821e66658cc9 100644
|
|
--- a/src/main/java/co/aikar/timings/MinecraftTimings.java
|
|
+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java
|
|
@@ -114,6 +114,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 0e7d29dbbdb862dd5876adee26fbba02267e5276..c334f29c69c1e6e3fe55cd6695e7df400cf36058 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
|
|
@@ -3,14 +3,19 @@ package com.destroystokyo.paper;
|
|
import java.util.Arrays;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
+import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.stream.Collectors;
|
|
+
|
|
+import com.google.common.collect.HashBasedTable;
|
|
+import com.google.common.collect.Table;
|
|
import net.minecraft.world.Difficulty;
|
|
import net.minecraft.world.entity.EntityType;
|
|
import net.minecraft.world.entity.monster.Vindicator;
|
|
import net.minecraft.world.entity.monster.Zombie;
|
|
import com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray.EngineMode;
|
|
import org.bukkit.Bukkit;
|
|
+import org.bukkit.configuration.ConfigurationSection;
|
|
import org.bukkit.configuration.file.YamlConfiguration;
|
|
import org.spigotmc.SpigotWorldConfig;
|
|
|
|
@@ -847,5 +852,58 @@ public class PaperWorldConfig {
|
|
private void playerCrammingDamage() {
|
|
allowPlayerCrammingDamage = getBoolean("allow-player-cramming-damage", allowPlayerCrammingDamage);
|
|
}
|
|
+
|
|
+ private Table<String, String, Integer> sensorTickRates;
|
|
+ private 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 Table<String, String, Integer> loadTickRates(String type) {
|
|
+ log(" " + type + ":");
|
|
+ Table<String, String, Integer> table = 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.toUpperCase(Locale.ROOT), typeName.toUpperCase(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(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 f94aa5147c52d2e36d6018f51b85e9dac7a6208a..87f804e35e2f124f5ee73d9d9a4fd4b3069b00d0 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
|
|
}
|
|
|
|
}
|