1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
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 4bd813161a5d76a83cdbd0a9209b9ea9e60ffe1b..e2764186bd6b838ed5cd86c15597a08d079ef984 100644
--- a/src/main/java/co/aikar/timings/MinecraftTimings.java
+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java
@@ -115,6 +115,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/net/minecraft/world/entity/ai/behavior/Behavior.java b/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java
index db231b1353a1d5ca4fb217f5ebf8d7584706478d..0a2e894d8bd1268fcbd4460745304816be46beff 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> implements BehaviorContro
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 - configurable behavior tick rate and timings
public Behavior(Map<MemoryModuleType<?>, MemoryStatus> requiredMemoryState) {
this(requiredMemoryState, 60);
@@ -27,6 +31,15 @@ public abstract class Behavior<E extends LivingEntity> implements BehaviorContro
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 - configurable behavior tick rate and timings
}
@Override
@@ -36,11 +49,19 @@ public abstract class Behavior<E extends LivingEntity> implements BehaviorContro
@Override
public final boolean tryStart(ServerLevel world, E entity, long time) {
+ // Paper start - configurable behavior tick rate and timings
+ int tickRate = java.util.Objects.requireNonNullElse(world.paperConfig().tickRates.behavior.get(entity.getType(), this.configKey), -1);
+ if (tickRate > -1 && time < this.endTimestamp + tickRate) {
+ return false;
+ }
+ // Paper end - configurable behavior tick rate and timings
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 + i;
+ this.timing.startTiming(); // Paper - behavior timings
this.start(world, entity, time);
+ this.timing.stopTiming(); // Paper - behavior timings
return true;
} else {
return false;
@@ -52,11 +73,13 @@ public abstract class Behavior<E extends LivingEntity> implements BehaviorContro
@Override
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
}
protected void tick(ServerLevel world, E entity, long time) {
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 eebe5d721a6cea42013f5293586865deb39fe9d2..de2dfaf3cb41bafd48fa4699096a0a7304cd3201 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
@@ -26,8 +26,21 @@ public abstract class Sensor<E extends LivingEntity> {
.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 = RANDOM.nextInt(senseInterval);
}
@@ -38,8 +51,12 @@ public abstract class Sensor<E extends LivingEntity> {
public final void tick(ServerLevel world, E entity) {
if (--this.timeToTick <= 0L) {
- this.timeToTick = this.scanRate;
+ // Paper start - configurable sensor tick rate and timings
+ this.timeToTick = java.util.Objects.requireNonNullElse(world.paperConfig().tickRates.sensor.get(entity.getType(), this.configKey), this.scanRate);
+ this.timing.startTiming();
+ // Paper end
this.doTick(world, entity);
+ this.timing.stopTiming(); // Paper - sensor timings
}
}
|