PaperMC/patches/server/0372-Add-tick-times-API-and-mspt-command.patch
Nassim Jahnke fb2c24b36d
Updated Upstream (Bukkit/CraftBukkit) (#8015)
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:
05ae036c PR-746: Add option to use cached map color palette
57849c1b PR-759: Add preview chat option in ServerListPingEvent
0169e65d PR-758: Add missing server properties methods from 1.19

CraftBukkit Changes:
622dbe6c2 SPIGOT-7068: SKULK and SKULK_VEIN BlockSpreadEvents Still do not reference the correct source (SKULK_CATALYST)
6c61b73f3 PR-1052: Add option to use cached map color palette
c882f38ea SPIGOT-7066: Fix custom END worlds not generating DragonBattle
6866aab59 SPIGOT-2420: Can't set exp drops for EnderDragon death
9dcd46530 PR-1067: Add preview chat option in ServerListPingEvent
36c2681af PR-1066: Add missing server properties methods from 1.19
031eaadd0 Increase outdated build delay
8fda4b12f SPIGOT-7060: SCULK and SCULK_VEIN BlockSpreadEvents do not reference the correct source
2022-06-20 19:12:05 +02:00

211 lines
8.1 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: William Blake Galbreath <Blake.Galbreath@GMail.com>
Date: Sun, 5 Apr 2020 22:23:14 -0500
Subject: [PATCH] Add tick times API and /mspt command
diff --git a/src/main/java/com/destroystokyo/paper/MSPTCommand.java b/src/main/java/com/destroystokyo/paper/MSPTCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..874f0c2a071994c2145848886caa385e0e0bfb9b
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/MSPTCommand.java
@@ -0,0 +1,99 @@
+package com.destroystokyo.paper;
+
+import net.kyori.adventure.text.Component;
+import net.minecraft.server.MinecraftServer;
+import org.bukkit.Location;
+import org.bukkit.command.Command;
+import org.bukkit.command.CommandSender;
+
+import java.text.DecimalFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static net.kyori.adventure.text.Component.text;
+import static net.kyori.adventure.text.format.NamedTextColor.GOLD;
+import static net.kyori.adventure.text.format.NamedTextColor.GRAY;
+import static net.kyori.adventure.text.format.NamedTextColor.GREEN;
+import static net.kyori.adventure.text.format.NamedTextColor.RED;
+import static net.kyori.adventure.text.format.NamedTextColor.YELLOW;
+
+public class MSPTCommand extends Command {
+ private static final DecimalFormat DF = new DecimalFormat("########0.0");
+ private static final Component SLASH = text("/");
+
+ public MSPTCommand(String name) {
+ super(name);
+ this.description = "View server tick times";
+ this.usageMessage = "/mspt";
+ this.setPermission("bukkit.command.mspt");
+ }
+
+ @Override
+ public List<String> tabComplete(CommandSender sender, String alias, String[] args, Location location) throws IllegalArgumentException {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean execute(CommandSender sender, String commandLabel, String[] args) {
+ if (!testPermission(sender)) return true;
+
+ MinecraftServer server = MinecraftServer.getServer();
+
+ List<Component> times = new ArrayList<>();
+ times.addAll(eval(server.tickTimes5s.getTimes()));
+ times.addAll(eval(server.tickTimes10s.getTimes()));
+ times.addAll(eval(server.tickTimes60s.getTimes()));
+
+ sender.sendMessage(text().content("Server tick times ").color(GOLD)
+ .append(text().color(YELLOW)
+ .append(
+ text("("),
+ text("avg", GRAY),
+ text("/"),
+ text("min", GRAY),
+ text("/"),
+ text("max", GRAY),
+ text(")")
+ )
+ ).append(
+ text(" from last 5s"),
+ text(",", GRAY),
+ text(" 10s"),
+ text(",", GRAY),
+ text(" 1m"),
+ text(":", YELLOW)
+ )
+ );
+ sender.sendMessage(text().content("◴ ").color(GOLD)
+ .append(text().color(GRAY)
+ .append(
+ times.get(0), SLASH, times.get(1), SLASH, times.get(2), text(", ", YELLOW),
+ times.get(3), SLASH, times.get(4), SLASH, times.get(5), text(", ", YELLOW),
+ times.get(6), SLASH, times.get(7), SLASH, times.get(8)
+ )
+ )
+ );
+ return true;
+ }
+
+ private static List<Component> eval(long[] times) {
+ long min = Integer.MAX_VALUE;
+ long max = 0L;
+ long total = 0L;
+ for (long value : times) {
+ if (value > 0L && value < min) min = value;
+ if (value > max) max = value;
+ total += value;
+ }
+ double avgD = ((double) total / (double) times.length) * 1.0E-6D;
+ double minD = ((double) min) * 1.0E-6D;
+ double maxD = ((double) max) * 1.0E-6D;
+ return Arrays.asList(getColor(avgD), getColor(minD), getColor(maxD));
+ }
+
+ private static Component getColor(double avg) {
+ return text(DF.format(avg), avg >= 50 ? RED : avg >= 40 ? YELLOW : GREEN);
+ }
+}
diff --git a/src/main/java/io/papermc/paper/command/PaperCommands.java b/src/main/java/io/papermc/paper/command/PaperCommands.java
index 82bce89dc174c8c4a4ab8efeffaaf22ddeb377fb..37d28625b9528bbe0cd6d9623e702bbbc2b07883 100644
--- a/src/main/java/io/papermc/paper/command/PaperCommands.java
+++ b/src/main/java/io/papermc/paper/command/PaperCommands.java
@@ -1,5 +1,6 @@
package io.papermc.paper.command;
+import com.destroystokyo.paper.MSPTCommand;
import com.destroystokyo.paper.PaperCommand;
import net.minecraft.server.MinecraftServer;
import org.bukkit.command.Command;
@@ -15,6 +16,7 @@ public final class PaperCommands {
private static final Map<String, Command> COMMANDS = new HashMap<>();
static {
COMMANDS.put("paper", new PaperCommand("paper"));
+ COMMANDS.put("mspt", new MSPTCommand("mspt"));
}
public static void registerCommands(final MinecraftServer server) {
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index f7427ea6bf11ef837dd38d25cd3abed57de5e8de..ce7b96819bf8d7e992c2aafd3013e8a9478e500d 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -234,6 +234,11 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
private String motd;
private int playerIdleTimeout;
public final long[] tickTimes;
+ // Paper start
+ public final TickTimes tickTimes5s = new TickTimes(100);
+ public final TickTimes tickTimes10s = new TickTimes(200);
+ public final TickTimes tickTimes60s = new TickTimes(1200);
+ // Paper end
@Nullable
private KeyPair keyPair;
@Nullable
@@ -1359,6 +1364,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
this.averageTickTime = this.averageTickTime * 0.8F + (float) l / 1000000.0F * 0.19999999F;
long i1 = Util.getNanos();
+ // Paper start
+ tickTimes5s.add(this.tickCount, l);
+ tickTimes10s.add(this.tickCount, l);
+ tickTimes60s.add(this.tickCount, l);
+ // Paper end
+
this.frameTimer.logFrameDuration(i1 - i);
this.profiler.pop();
org.spigotmc.WatchdogThread.tick(); // Spigot
@@ -2494,4 +2505,30 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
public static record ServerResourcePackInfo(String url, String hash, boolean isRequired, @Nullable Component prompt) {
}
+
+ // Paper start
+ public static class TickTimes {
+ private final long[] times;
+
+ public TickTimes(int length) {
+ times = new long[length];
+ }
+
+ void add(int index, long time) {
+ times[index % times.length] = time;
+ }
+
+ public long[] getTimes() {
+ return times.clone();
+ }
+
+ public double getAverage() {
+ long total = 0L;
+ for (long value : times) {
+ total += value;
+ }
+ return ((double) total / (double) times.length) * 1.0E-6D;
+ }
+ }
+ // Paper end
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index de114eda44d475c50f25f8dfedf17c41e783c5d9..9e2a90b2b5173667f336d64da111221d0093a7d4 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2471,6 +2471,16 @@ public final class CraftServer implements Server {
net.minecraft.server.MinecraftServer.getServer().tps15.getAverage()
};
}
+
+ @Override
+ public long[] getTickTimes() {
+ return getServer().tickTimes5s.getTimes();
+ }
+
+ @Override
+ public double getAverageTickTime() {
+ return getServer().tickTimes5s.getAverage();
+ }
// Paper end
// Spigot start