From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ivan Pekov <ivan@mrivanplays.com>
Date: Sun, 27 Sep 2020 18:30:10 +0300
Subject: [PATCH] Add last tick time API

Original patch by:
Co-authored-by: tr7zw <tr7zw@live.de>

diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index e9c0556af0a8ffd4d85e87bcccf2908444d967eb..dcb757ff80885ead374750a6b9d2247cfd12d70c 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -943,6 +943,8 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
     // Paper End
     // Spigot End
 
+    public static java.time.Duration lastTickTime = java.time.Duration.ZERO; // Yatopia
+
     protected void w() {
         try {
             long serverStartTime = SystemUtils.getMonotonicNanos(); // Paper
@@ -1014,7 +1016,9 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
                     this.a(gameprofilertick);
                     this.methodProfiler.a();
                     this.methodProfiler.enter("tick");
+                    long tickStart = System.nanoTime(); // Yatopia
                     this.a(this::canSleepForTick);
+                    lastTickTime = java.time.Duration.ofNanos(System.nanoTime() - tickStart); // Yatopia
                     this.methodProfiler.exitEnter("nextTickWait");
                     this.X = true;
                     // Purpur start - tps catchup
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index d5c2fa2363ec898e6fdf16699c3e3e3fef98410c..e9d3883f5c322ad8437c87aa2ccc0ecaa6f01bae 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -2535,4 +2535,6 @@ public final class CraftServer implements Server {
         return getServer().lagging;
     }
     // Purpur end
+
+    @Override public java.time.Duration getLastTickTime() { return net.minecraft.server.MinecraftServer.lastTickTime; } // Yatopia
 }
diff --git a/src/main/java/org/spigotmc/TicksPerSecondCommand.java b/src/main/java/org/spigotmc/TicksPerSecondCommand.java
index 312248b5c6febc6a3c10940714fac7fbc3c53b7f..abc9b7aa53e554ef2196dceafe8db8ba65f34e84 100644
--- a/src/main/java/org/spigotmc/TicksPerSecondCommand.java
+++ b/src/main/java/org/spigotmc/TicksPerSecondCommand.java
@@ -32,6 +32,10 @@ public class TicksPerSecondCommand extends Command
             tpsAvg[i] = format( tps[i] );
         }
         sender.sendMessage(ChatColor.GOLD + "TPS from last 5s, 1m, 5m, 15m: " + org.apache.commons.lang.StringUtils.join(tpsAvg, ", ")); // Purpur
+        // Yatopia start
+        java.time.Duration lastTickTime = org.bukkit.Bukkit.getLastTickTime();
+        sender.sendMessage(ChatColor.GOLD + "Last tick: " + formatTo( lastTickTime, java.util.concurrent.TimeUnit.MILLISECONDS ) + " (" + formatTo( lastTickTime, java.util.concurrent.TimeUnit.NANOSECONDS ) + ")");
+        // Yatopia end
         if (args.length > 0 && args[0].equals("mem") && sender.hasPermission("bukkit.command.tpsmemory")) {
             sender.sendMessage(ChatColor.GOLD + "Current Memory Usage: " + ChatColor.GREEN + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / (1024 * 1024)) + "/" + (Runtime.getRuntime().totalMemory() / (1024 * 1024)) + " mb (Max: " + (Runtime.getRuntime().maxMemory() / (1024 * 1024)) + " mb)");
             if (!hasShownMemoryWarning) {
@@ -50,4 +54,16 @@ public class TicksPerSecondCommand extends Command
         return ( ( tps > 18.0 ) ? ChatColor.GREEN : ( tps > 16.0 ) ? ChatColor.YELLOW : ChatColor.RED ).toString()
                 + ( ( tps > 21.0 ) ? "*" : "" ) + Math.min( Math.round( tps * 100.0 ) / 100.0, 20.0 ); // Paper - only print * at 21, we commonly peak to 20.02 as the tick sleep is not accurate enough, stop the noise
     }
+
+    // Yatopia start
+    public static String formatTo(java.time.Duration duration, java.util.concurrent.TimeUnit unit)
+    {
+        java.util.concurrent.TimeUnit nanosUnit = java.util.concurrent.TimeUnit.NANOSECONDS;
+        long nanos = duration.toNanos();
+        long toAskedUnit = unit.convert( nanos, nanosUnit );
+        long ms = nanosUnit.toMillis( nanos );
+        ChatColor startingColor = ms < 40 ? ChatColor.GREEN : ( ms < 50 ) ? ChatColor.YELLOW : ChatColor.RED;
+        return startingColor.toString() + toAskedUnit + ChatColor.GOLD + org.yatopiamc.yatopia.server.util.TimeUtils.getFriendlyName( unit );
+    }
+    // Yatopia end
 }
