diff --git a/patches/api/Expose-server-build-information.patch b/patches/api/Expose-server-build-information.patch index 26f5a90870..0ae49b5a8f 100644 --- a/patches/api/Expose-server-build-information.patch +++ b/patches/api/Expose-server-build-information.patch @@ -320,17 +320,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/UnsafeValues.java +++ b/src/main/java/org/bukkit/UnsafeValues.java @@ -0,0 +0,0 @@ public interface UnsafeValues { - */ - @Deprecated(forRemoval = true) - String getTimingsServerName(); + return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); + } + // Paper end + ++ // Paper start + /** + * Called once by the version command on first use, then cached. + */ + default com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { + return new com.destroystokyo.paper.util.VersionFetcher.DummyVersionFetcher(); + } - // Paper end ++ // Paper end } diff --git a/src/main/java/org/bukkit/command/defaults/VersionCommand.java b/src/main/java/org/bukkit/command/defaults/VersionCommand.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 diff --git a/patches/api/Timings-v2.patch b/patches/api/Timings-v2.patch index 32879399a1..5e9e28c2a4 100644 --- a/patches/api/Timings-v2.patch +++ b/patches/api/Timings-v2.patch @@ -94,7 +94,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + TimingsManager.HISTORY.add(new TimingHistory()); + TimingsManager.resetTimings(); + } -+ Bukkit.getUnsafe().reportTimings(); ++ //Bukkit.getUnsafe().reportTimings(); + } + + boolean isViolated() { @@ -1426,14 +1426,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + * @param enabled Should timings be reported + */ + public static void setTimingsEnabled(boolean enabled) { -+ timingsEnabled = enabled; -+ warnAboutDeprecationOnEnable(); -+ reset(); -+ } -+ -+ private static void warnAboutDeprecationOnEnable() { -+ if (timingsEnabled && !warnedAboutDeprecationOnEnable) { -+ Bukkit.getLogger().warning(PlainTextComponentSerializer.plainText().serialize(deprecationMessage())); ++ if (enabled && !warnedAboutDeprecationOnEnable) { ++ Bukkit.getLogger().severe(PlainTextComponentSerializer.plainText().serialize(deprecationMessage())); + warnedAboutDeprecationOnEnable = true; + } + } @@ -1441,7 +1435,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static Component deprecationMessage() { + return Component.text() + .color(TextColor.color(0xffc93a)) -+ .append(Component.text("[!] The timings profiler has been enabled but has been scheduled for removal from Paper in the future.")) ++ .append(Component.text("[!] The timings profiler is in no-op mode and will be fully removed in a later update.")) + .append(Component.newline()) + .append(Component.text(" We recommend migrating to the spark profiler.")) + .append(Component.newline()) @@ -1674,8 +1668,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (!testPermission(sender)) { + return true; + } -+ if (false) { ++ if (true) { + sender.sendMessage(Timings.deprecationMessage()); ++ return true; + } + if (args.length < 1) { + sender.sendMessage(text("Usage: " + this.usageMessage, NamedTextColor.RED)); @@ -2906,35 +2901,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 /** * Sends the component to the player * -diff --git a/src/main/java/org/bukkit/UnsafeValues.java b/src/main/java/org/bukkit/UnsafeValues.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/UnsafeValues.java -+++ b/src/main/java/org/bukkit/UnsafeValues.java -@@ -0,0 +0,0 @@ public interface UnsafeValues { - net.kyori.adventure.text.Component resolveWithContext(net.kyori.adventure.text.Component component, org.bukkit.command.CommandSender context, org.bukkit.entity.Entity scoreboardSubject, boolean bypassPermissions) throws java.io.IOException; - // Paper end - -+ /** -+ * @deprecated Timings will be removed in the future -+ */ -+ @Deprecated(forRemoval = true) -+ void reportTimings(); // Paper - Material toLegacy(Material material); - - Material fromLegacy(Material material); -@@ -0,0 +0,0 @@ public interface UnsafeValues { - return !Bukkit.getUnsafe().isSupportedApiVersion(plugin.getDescription().getAPIVersion()); - } - // Paper end -+ -+ // Paper start -+ /** -+ * @deprecated Timings will be removed in the future -+ */ -+ @Deprecated(forRemoval = true) -+ String getTimingsServerName(); -+ // Paper end - } diff --git a/src/main/java/org/bukkit/command/BufferedCommandSender.java b/src/main/java/org/bukkit/command/BufferedCommandSender.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -3560,8 +3526,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 /** @@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager { + * * @param use True if per event timing code should be used */ ++ @Deprecated(forRemoval = true) public void useTimings(boolean use) { - useTimings = use; + co.aikar.timings.Timings.setTimingsEnabled(use); // Paper diff --git a/patches/server/Add-NamespacedKey-biome-methods.patch b/patches/server/Add-NamespacedKey-biome-methods.patch index c76175389c..abefd86fda 100644 --- a/patches/server/Add-NamespacedKey-biome-methods.patch +++ b/patches/server/Add-NamespacedKey-biome-methods.patch @@ -10,10 +10,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { + var supplier = net.minecraft.world.entity.ai.attributes.DefaultAttributes.getSupplier((net.minecraft.world.entity.EntityType) net.minecraft.core.registries.BuiltInRegistries.ENTITY_TYPE.getValue(CraftNamespacedKey.toMinecraft(bukkitEntityKey))); + return new io.papermc.paper.attribute.UnmodifiableAttributeMap(supplier); } - // Paper end - -+ // Paper start - namespaced key biome methods ++ + @Override + public org.bukkit.NamespacedKey getBiomeKey(org.bukkit.RegionAccessor accessor, int x, int y, int z) { + org.bukkit.craftbukkit.CraftRegionAccessor cra = (org.bukkit.craftbukkit.CraftRegionAccessor) accessor; @@ -26,8 +26,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + net.minecraft.core.Holder biomeBase = cra.getHandle().registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.BIOME).getOrThrow(net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.BIOME, org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(biomeKey))); + cra.setBiome(x, y, z, biomeBase); + } -+ // Paper end - namespaced key biome methods -+ - @Override - public String get(Class aClass, String s) { - if (aClass == Enchantment.class) { + // Paper end + + /** diff --git a/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch b/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch index 2dc30c2136..42dd267b50 100644 --- a/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch +++ b/patches/server/Add-Raw-Byte-ItemStack-Serialization.patch @@ -62,4 +62,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } // Paper end - @Override + /** diff --git a/patches/server/Add-api-for-spawn-egg-texture-colors.patch b/patches/server/Add-api-for-spawn-egg-texture-colors.patch index f2e2c9ebcf..529c61964b 100644 --- a/patches/server/Add-api-for-spawn-egg-texture-colors.patch +++ b/patches/server/Add-api-for-spawn-egg-texture-colors.patch @@ -9,8 +9,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT); } + // Paper end + // Paper start - spawn egg color visibility + @Override diff --git a/patches/server/Add-debug-for-sync-chunk-loads.patch b/patches/server/Add-debug-for-sync-chunk-loads.patch index d5da40e03f..70307e6cf9 100644 --- a/patches/server/Add-debug-for-sync-chunk-loads.patch +++ b/patches/server/Add-debug-for-sync-chunk-loads.patch @@ -308,11 +308,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { Objects.requireNonNull(completablefuture); - if (!completablefuture.isDone()) { // Paper -+ com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x, z); // Paper - Add debug for sync chunk loads - this.level.timings.syncChunkLoad.startTiming(); // Paper chunkproviderserver_b.managedBlock(completablefuture::isDone); - this.level.timings.syncChunkLoad.stopTiming(); // Paper ++ // com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x, z); // Paper - Add debug for sync chunk loads + ChunkResult chunkresult = (ChunkResult) completablefuture.join(); + ChunkAccess ichunkaccess1 = (ChunkAccess) chunkresult.orElse(null); // CraftBukkit - decompile error + diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java diff --git a/patches/server/Add-tick-times-API-and-mspt-command.patch b/patches/server/Add-tick-times-API-and-mspt-command.patch index dbe9ac038d..a17b18508b 100644 --- a/patches/server/Add-tick-times-API-and-mspt-command.patch +++ b/patches/server/Add-tick-times-API-and-mspt-command.patch @@ -151,7 +151,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - Add tick times API and /mspt command this.logTickMethodTime(i); gameprofilerfiller.pop(); - co.aikar.timings.TimingsManager.FULL_SERVER_TICK.stopTiming(); // Paper + } @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop getTypeKey(); @@ -1191,7 +1191,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config this.generator = gen; @@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - this.timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings + // CraftBukkit end this.entityLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.entityMaxTickTime); this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime); + this.chunkPacketBlockController = this.paperConfig().anticheat.antiXray.enabled ? new com.destroystokyo.paper.antixray.ChunkPacketBlockControllerAntiXray(this, executor) : com.destroystokyo.paper.antixray.ChunkPacketBlockController.NO_OPERATION_INSTANCE; // Paper - Anti-Xray diff --git a/patches/server/Async-command-map-building.patch b/patches/server/Async-command-map-building.patch index 9062c429c2..d6df455d42 100644 --- a/patches/server/Async-command-map-building.patch +++ b/patches/server/Async-command-map-building.patch @@ -61,6 +61,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 MinecraftServer.LOGGER.info("Stopping server"); + Commands.COMMAND_SENDING_POOL.shutdownNow(); // Paper - Perf: Async command map building; Shutdown and don't bother finishing - MinecraftTimings.stopServer(); // Paper // CraftBukkit start if (this.server != null) { + this.server.disablePlugins(); diff --git a/patches/server/Brigadier-based-command-API.patch b/patches/server/Brigadier-based-command-API.patch index 62564d9dfb..93118ff19c 100644 --- a/patches/server/Brigadier-based-command-API.patch +++ b/patches/server/Brigadier-based-command-API.patch @@ -2345,10 +2345,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } -+ @Deprecated // Paper - public void handleCommand(String s) { // Paper - private -> public +- private void handleCommand(String s) { - org.spigotmc.AsyncCatcher.catchOp("Command Dispatched Async: " + s); // Paper - Add async catcher -- co.aikar.timings.MinecraftTimings.playerCommandTimer.startTiming(); // Paper - if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot - this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s); - @@ -2358,7 +2356,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - this.cserver.getPluginManager().callEvent(event); - - if (event.isCancelled()) { -- co.aikar.timings.MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - return; - } - @@ -2371,7 +2368,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); - return; - } finally { -- co.aikar.timings.MinecraftTimings.playerCommandTimer.stopTiming(); // Paper ++ @Deprecated // Paper ++ public void handleCommand(String s) { // Paper - private -> public + // Paper start - Remove all this old duplicated logic + if (s.startsWith("/")) { + s = s.substring(1); diff --git a/patches/server/Bundle-spark.patch b/patches/server/Bundle-spark.patch index df87061f4f..74f8eb1acd 100644 --- a/patches/server/Bundle-spark.patch +++ b/patches/server/Bundle-spark.patch @@ -282,9 +282,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 io.papermc.paper.command.brigadier.PaperCommands.INSTANCE.setValid(); // Paper - reset invalid state for event fire below io.papermc.paper.plugin.lifecycle.event.LifecycleEventRunner.INSTANCE.callReloadableRegistrarEvent(io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents.COMMANDS, io.papermc.paper.command.brigadier.PaperCommands.INSTANCE, org.bukkit.plugin.Plugin.class, io.papermc.paper.plugin.lifecycle.event.registrar.ReloadableRegistrarEvent.Cause.INITIAL); // Paper - call commands event for regular plugins @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/co/aikar/timings/TimingsExport.java -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -0,0 +0,0 @@ public class TimingsExport extends Thread { - JSONObject object = new JSONObject(); - for (String key : config.getKeys(false)) { - String fullKey = (parentKey != null ? parentKey + "." + key : key); -- if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) { -+ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld") || key.equals("feature-seeds")) { - continue; - } - final Object val = config.get(key); diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java diff --git a/patches/server/Configurable-max-block-fluid-ticks.patch b/patches/server/Configurable-max-block-fluid-ticks.patch index 00638674f8..e86e8982ff 100644 --- a/patches/server/Configurable-max-block-fluid-ticks.patch +++ b/patches/server/Configurable-max-block-fluid-ticks.patch @@ -19,4 +19,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.fluidTicks.tick(j, paperConfig().environment.maxFluidTicks, this::tickFluid); // Paper - configurable max fluid ticks gameprofilerfiller.pop(); } - this.timings.scheduledBlocks.stopTiming(); // Paper + diff --git a/patches/server/Detail-more-information-in-watchdog-dumps.patch b/patches/server/Detail-more-information-in-watchdog-dumps.patch index 393f366d68..9d5a4deee3 100644 --- a/patches/server/Detail-more-information-in-watchdog-dumps.patch +++ b/patches/server/Detail-more-information-in-watchdog-dumps.patch @@ -61,7 +61,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + try { // Paper - detailed watchdog information if (listener instanceof ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // CraftBukkit - Don't handle sync packets for kicked players if (listener.shouldHandleMessage(packet)) { - co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings + try { @@ -0,0 +0,0 @@ public class PacketUtils { } else { PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet); @@ -103,14 +103,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + currentlyTickingEntity.lazySet(entity); + } + // Paper end - log detailed entity tick information - ++TimingHistory.entityTicks; // Paper - timings // Spigot start - co.aikar.timings.Timing timer; // Paper + /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out EAR 2 + entity.tickCount++; @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2 } - // } finally { timer.stopTiming(); } // Paper - timings // EAR 2 -- + + // Paper start - log detailed entity tick information + } finally { + if (currentlyTickingEntity.get() == entity) { diff --git a/patches/server/Disable-ice-and-snow.patch b/patches/server/Disable-ice-and-snow.patch index bd89303434..8a3af1eb62 100644 --- a/patches/server/Disable-ice-and-snow.patch +++ b/patches/server/Disable-ice-and-snow.patch @@ -21,4 +21,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } // Paper - Option to disable ice and snow gameprofilerfiller.popPush("tickBlocks"); - timings.chunkTicksBlocks.startTiming(); // Paper + if (randomTickSpeed > 0) { diff --git a/patches/server/Enforce-Sync-Player-Saves.patch b/patches/server/Enforce-Sync-Player-Saves.patch index 348efbfe81..793cf831d4 100644 --- a/patches/server/Enforce-Sync-Player-Saves.patch +++ b/patches/server/Enforce-Sync-Player-Saves.patch @@ -15,12 +15,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void saveAll() { + io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper for (int i = 0; i < this.players.size(); ++i) { -- this.save((ServerPlayer) this.players.get(i)); -+ this.save(this.players.get(i)); + this.save((ServerPlayer) this.players.get(i)); } - MinecraftTimings.savePlayers.stopTiming(); // Paper + + return null; }); // Paper - ensure main } diff --git a/patches/server/Entity-Activation-Range-2.0.patch b/patches/server/Entity-Activation-Range-2.0.patch index 013902bd7c..347e88421e 100644 --- a/patches/server/Entity-Activation-Range-2.0.patch +++ b/patches/server/Entity-Activation-Range-2.0.patch @@ -20,36 +20,22 @@ diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/mai index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -0,0 +0,0 @@ package net.minecraft.server.level; - - import com.google.common.annotations.VisibleForTesting; - import co.aikar.timings.TimingHistory; // Paper --import co.aikar.timings.Timings; // Paper - import com.google.common.collect.Lists; - import com.mojang.datafixers.DataFixer; - import com.mojang.datafixers.util.Pair; @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - ++TimingHistory.entityTicks; // Paper - timings + + public void tickNonPassenger(Entity entity) { // Spigot start - co.aikar.timings.Timing timer; // Paper - if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { -+ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out - EAR 2, reimplement below ++ /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out EAR 2 entity.tickCount++; - timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings entity.inactiveTick(); - } finally { timer.stopTiming(); } // Paper return; - } + }*/ // Paper - comment out EAR 2 // Spigot end - // Paper start- timings -- TimingHistory.activatedEntityTicks++; -- timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); -+ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); -+ timer = isActive ? entity.getType().tickTimer.startTiming() : entity.getType().inactiveTickTimer.startTiming(); // Paper - try { - // Paper end - timings ++ final boolean isActive = org.spigotmc.ActivationRange.checkIfActive(entity); // Paper - EAR 2 entity.setOldPosAndRot(); + ProfilerFiller gameprofilerfiller = Profiler.get(); + @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe return BuiltInRegistries.ENTITY_TYPE.getKey(entity.getType()).toString(); }); @@ -59,7 +45,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 entity.postTick(); // CraftBukkit + } else { entity.inactiveTick(); } // Paper - EAR 2 gameprofilerfiller.pop(); -+ } finally { timer.stopTiming(); } // Paper - timings // EAR 2 Iterator iterator = entity.getPassengers().iterator(); while (iterator.hasNext()) { @@ -68,8 +53,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - this.tickPassenger(entity, entity1); + this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2 } -- } finally { timer.stopTiming(); } // Paper - timings -+ // } finally { timer.stopTiming(); } // Paper - timings // EAR 2 } @@ -408,26 +391,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 import net.minecraft.world.entity.projectile.FireworkRocketEntity; import net.minecraft.world.entity.projectile.ThrowableProjectile; import net.minecraft.world.entity.projectile.ThrownTrident; - import net.minecraft.world.entity.raid.Raider; -+import co.aikar.timings.MinecraftTimings; -+import net.minecraft.world.entity.schedule.Activity; - import net.minecraft.world.level.Level; - import net.minecraft.world.phys.AABB; --import co.aikar.timings.MinecraftTimings; - - public class ActivationRange - { @@ -0,0 +0,0 @@ public class ActivationRange AABB boundingBox = new AABB( 0, 0, 0, 0, 0, 0 ); } + // Paper start + -+ static Activity[] VILLAGER_PANIC_IMMUNITIES = { -+ Activity.HIDE, -+ Activity.PRE_RAID, -+ Activity.RAID, -+ Activity.PANIC ++ static net.minecraft.world.entity.schedule.Activity[] VILLAGER_PANIC_IMMUNITIES = { ++ net.minecraft.world.entity.schedule.Activity.HIDE, ++ net.minecraft.world.entity.schedule.Activity.PRE_RAID, ++ net.minecraft.world.entity.schedule.Activity.RAID, ++ net.minecraft.world.entity.schedule.Activity.PANIC + }; + + private static int checkInactiveWakeup(Entity entity) { @@ -556,8 +530,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + // Paper end } - MinecraftTimings.entityActivationCheckTimer.stopTiming(); } + @@ -0,0 +0,0 @@ public class ActivationRange * @param entity * @return @@ -620,7 +594,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 { - return true; + return 20; // Paper -+ } + } +- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) + // Paper start + if (entity instanceof Bee) { + Bee bee = (Bee)entity; @@ -631,13 +606,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ) { + return 20; + } - } -- if ( entity instanceof Villager && ( (Villager) entity ).canBreed() ) ++ } + if ( entity instanceof Villager ) { + Brain behaviorController = ((Villager) entity).getBrain(); + + if (config.villagersActiveForPanic) { -+ for (Activity activity : VILLAGER_PANIC_IMMUNITIES) { ++ for (net.minecraft.world.entity.schedule.Activity activity : VILLAGER_PANIC_IMMUNITIES) { + if (behaviorController.isActive(activity)) { + return 20*5; + } @@ -645,7 +619,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + if (config.villagersWorkImmunityAfter > 0 && inactiveFor >= config.villagersWorkImmunityAfter) { -+ if (behaviorController.isActive(Activity.WORK)) { ++ if (behaviorController.isActive(net.minecraft.world.entity.schedule.Activity.WORK)) { + return config.villagersWorkImmunityFor; + } + } @@ -677,11 +651,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper start + if (entity instanceof Mob && ((Mob) entity).targetSelector.hasTasks() ) { + return 0; - } ++ } + if (entity instanceof Pillager) { + Pillager pillager = (Pillager) entity; + // TODO:? -+ } + } + // Paper end } // SPIGOT-6644: Otherwise the target refresh tick will be missed diff --git a/patches/server/Expand-world-key-API.patch b/patches/server/Expand-world-key-API.patch index f8595def4f..f1b177099b 100644 --- a/patches/server/Expand-world-key-API.patch +++ b/patches/server/Expand-world-key-API.patch @@ -81,4 +81,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } // Paper end - @Override + /** diff --git a/patches/server/Expose-protocol-version.patch b/patches/server/Expose-protocol-version.patch index 219a69d9cd..30902c3a65 100644 --- a/patches/server/Expose-protocol-version.patch +++ b/patches/server/Expose-protocol-version.patch @@ -19,4 +19,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } // Paper end - @Override + /** diff --git a/patches/server/Expose-server-build-information.patch b/patches/server/Expose-server-build-information.patch index 3cf70f5fae..478f0836cc 100644 --- a/patches/server/Expose-server-build-information.patch +++ b/patches/server/Expose-server-build-information.patch @@ -696,17 +696,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - public String getTimingsServerName() { - return io.papermc.paper.configuration.GlobalConfiguration.get().timings.serverName; + return CraftRegistry.get(registry, namespacedKey, ApiVersion.CURRENT); } -+ + ++ // Paper start + @Override + public com.destroystokyo.paper.util.VersionFetcher getVersionFetcher() { + return new com.destroystokyo.paper.PaperVersionFetcher(); + } - // Paper end - - @Override ++ // Paper end ++ + /** + * This helper class represents the different NBT Tags. + *

diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java diff --git a/patches/server/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch b/patches/server/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch index ccade23d20..d30b1984a8 100644 --- a/patches/server/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch +++ b/patches/server/Expose-the-Entity-Counter-to-allow-plugins-to-use-va.patch @@ -35,4 +35,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } // Paper end - @Override + /** diff --git a/patches/server/Fix-MC-117075-Block-entity-unload-lag-spike.patch b/patches/server/Fix-MC-117075-Block-entity-unload-lag-spike.patch index 92238a2190..c242f7e854 100644 --- a/patches/server/Fix-MC-117075-Block-entity-unload-lag-spike.patch +++ b/patches/server/Fix-MC-117075-Block-entity-unload-lag-spike.patch @@ -30,5 +30,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } + this.blockEntityTickers.removeAll(toRemove); // Paper - Fix MC-117075 - this.timings.tileEntityTick.stopTiming(); // Spigot this.tickingBlockEntities = false; + gameprofilerfiller.pop(); diff --git a/patches/server/Fix-custom-statistic-criteria-creation.patch b/patches/server/Fix-custom-statistic-criteria-creation.patch index 523bc264e6..840bf593c6 100644 --- a/patches/server/Fix-custom-statistic-criteria-creation.patch +++ b/patches/server/Fix-custom-statistic-criteria-creation.patch @@ -9,17 +9,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { + net.minecraft.core.Holder biomeBase = cra.getHandle().registryAccess().lookupOrThrow(net.minecraft.core.registries.Registries.BIOME).getOrThrow(net.minecraft.resources.ResourceKey.create(net.minecraft.core.registries.Registries.BIOME, org.bukkit.craftbukkit.util.CraftNamespacedKey.toMinecraft(biomeKey))); + cra.setBiome(x, y, z, biomeBase); } - // Paper end - namespaced key biome methods - -+ // Paper start - fix custom stats criteria creation ++ + @Override + public String getStatisticCriteriaKey(org.bukkit.Statistic statistic) { + if (statistic.getType() != org.bukkit.Statistic.Type.UNTYPED) return "minecraft.custom:minecraft." + statistic.getKey().getKey(); + return org.bukkit.craftbukkit.CraftStatistic.getNMSStatistic(statistic).getName(); + } -+ // Paper end - fix custom stats criteria creation -+ - @Override - public String get(Class aClass, String s) { - if (aClass == Enchantment.class) { + // Paper end + + /** diff --git a/patches/server/Folia-scheduler-and-owned-region-API.patch b/patches/server/Folia-scheduler-and-owned-region-API.patch index d818ef5573..863eb9a51c 100644 --- a/patches/server/Folia-scheduler-and-owned-region-API.patch +++ b/patches/server/Folia-scheduler-and-owned-region-API.patch @@ -1152,9 +1152,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { @@ -1171,7 +1171,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - Folia scheduler API io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue(this.tickCount); // Paper gameprofilerfiller.push("commandFunctions"); - MinecraftTimings.commandFunctionsTimer.startTiming(); // Spigot // Paper + this.getFunctions().tick(); diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/players/PlayerList.java diff --git a/patches/server/Get-entity-default-attributes.patch b/patches/server/Get-entity-default-attributes.patch index 41556b0e11..d61a9db855 100644 --- a/patches/server/Get-entity-default-attributes.patch +++ b/patches/server/Get-entity-default-attributes.patch @@ -102,7 +102,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } // Paper end - @Override + /** diff --git a/src/test/java/io/papermc/paper/attribute/EntityTypeAttributesTest.java b/src/test/java/io/papermc/paper/attribute/EntityTypeAttributesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 diff --git a/patches/server/Improve-Player-chat-API-handling.patch b/patches/server/Improve-Player-chat-API-handling.patch index ec17e80cb3..3e06781075 100644 --- a/patches/server/Improve-Player-chat-API-handling.patch +++ b/patches/server/Improve-Player-chat-API-handling.patch @@ -30,15 +30,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } else if (this.player.getChatVisibility() == ChatVisiblity.SYSTEM) { // Do nothing, this is coming from a plugin @@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } } -- private void handleCommand(String s) { -+ public void handleCommand(String s) { // Paper - private -> public + private void handleCommand(String s) { + org.spigotmc.AsyncCatcher.catchOp("Command Dispatched Async: " + s); // Paper - Add async catcher - co.aikar.timings.MinecraftTimings.playerCommandTimer.startTiming(); // Paper if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s); + diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java diff --git a/patches/server/Improved-Async-Task-Scheduler.patch b/patches/server/Improved-Async-Task-Scheduler.patch index 803db65442..7d1a7109ff 100644 --- a/patches/server/Improved-Async-Task-Scheduler.patch +++ b/patches/server/Improved-Async-Task-Scheduler.patch @@ -353,18 +353,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } - private void parsePending() { -- MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); + void parsePending() { // Paper -+ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); // Paper CraftTask head = this.head; CraftTask task = head.getNext(); CraftTask lastTask = head; -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -- MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); -+ if (!this.isAsyncScheduler) MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); // Paper - } - - private boolean isReady(final int currentTick) { diff --git a/patches/server/Incremental-chunk-and-player-saving.patch b/patches/server/Incremental-chunk-and-player-saving.patch index 49a1b487a9..9e117f351b 100644 --- a/patches/server/Incremental-chunk-and-player-saving.patch +++ b/patches/server/Incremental-chunk-and-player-saving.patch @@ -65,24 +65,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(getWorld())); + } + -+ try (co.aikar.timings.Timing ignored = this.timings.worldSave.startTiming()) { -+ if (doFull) { -+ this.saveLevelData(true); -+ } -+ -+ // chunk autosave is already called by the ChunkSystem during unload processing (ChunkMap#processUnloads) -+ -+ // Copied from save() -+ // CraftBukkit start - moved from MinecraftServer.saveChunks -+ if (doFull) { // Paper -+ ServerLevel worldserver1 = this; -+ -+ this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); -+ this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save(this.registryAccess())); -+ this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); -+ } -+ // CraftBukkit end ++ if (doFull) { ++ this.saveLevelData(true); + } ++ // chunk autosave is already called by the ChunkSystem during unload processing (ChunkMap#processUnloads) ++ // Copied from save() ++ // CraftBukkit start - moved from MinecraftServer.saveChunks ++ if (doFull) { // Paper ++ ServerLevel worldserver1 = this; ++ this.serverLevelData.setWorldBorder(worldserver1.getWorldBorder().createSettings()); ++ this.serverLevelData.setCustomBossEvents(this.server.getCustomBossEvents().save(this.registryAccess())); ++ this.convertable.saveDataTag(this.server.registryAccess(), this.serverLevelData, this.server.getPlayerList().getSingleplayerData()); ++ } ++ // CraftBukkit end + } + // Paper end - Incremental chunk and player saving + @@ -123,17 +118,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public void saveAll(int interval) { io.papermc.paper.util.MCUtil.ensureMain("Save Players" , () -> { // Paper - Ensure main - MinecraftTimings.savePlayers.startTiming(); // Paper + int numSaved = 0; + long now = MinecraftServer.currentTick; for (int i = 0; i < this.players.size(); ++i) { -- this.save(this.players.get(i)); -+ ServerPlayer entityplayer = this.players.get(i); -+ if (interval == -1 || now - entityplayer.lastSave >= interval) { -+ this.save(entityplayer); +- this.save((ServerPlayer) this.players.get(i)); ++ final ServerPlayer player = this.players.get(i); ++ if (interval == -1 || now - player.lastSave >= interval) { ++ this.save(player); + if (interval != -1 && ++numSaved >= io.papermc.paper.configuration.GlobalConfiguration.get().playerAutoSave.maxPerTick()) { break; } + } + // Paper end - Incremental chunk and player saving } - MinecraftTimings.savePlayers.stopTiming(); // Paper + return null; }); // Paper - ensure main diff --git a/patches/server/ItemStack-Tooltip-API.patch b/patches/server/ItemStack-Tooltip-API.patch index 59cb40649f..d55c6b64c9 100644 --- a/patches/server/ItemStack-Tooltip-API.patch +++ b/patches/server/ItemStack-Tooltip-API.patch @@ -9,10 +9,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { + if (statistic.getType() != org.bukkit.Statistic.Type.UNTYPED) return "minecraft.custom:minecraft." + statistic.getKey().getKey(); + return org.bukkit.craftbukkit.CraftStatistic.getNMSStatistic(statistic).getName(); } - // Paper end - fix custom stats criteria creation - -+ // Paper start - expose itemstack tooltip lines ++ + @Override + public java.util.List computeTooltipLines(final ItemStack itemStack, final io.papermc.paper.inventory.tooltip.TooltipContext tooltipContext, final org.bukkit.entity.Player player) { + Preconditions.checkArgument(tooltipContext != null, "tooltipContext cannot be null"); @@ -25,8 +25,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + player == null ? null : ((org.bukkit.craftbukkit.entity.CraftPlayer) player).getHandle(), flag); + return lines.stream().map(io.papermc.paper.adventure.PaperAdventure::asAdventure).toList(); + } -+ // Paper end - expose itemstack tooltip lines -+ - @Override - public String get(Class aClass, String s) { - if (aClass == Enchantment.class) { + // Paper end + + // Paper start - spawn egg color visibility diff --git a/patches/server/ItemStack-repair-check-API.patch b/patches/server/ItemStack-repair-check-API.patch index 2c5eca8700..5c6804a0c0 100644 --- a/patches/server/ItemStack-repair-check-API.patch +++ b/patches/server/ItemStack-repair-check-API.patch @@ -22,7 +22,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } // Paper end - @Override + /** diff --git a/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java b/src/test/java/io/papermc/paper/util/ItemStackRepairCheckTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 diff --git a/patches/server/Moonrise-optimisation-patches.patch b/patches/server/Moonrise-optimisation-patches.patch index f437c2333e..ac6ec19f98 100644 --- a/patches/server/Moonrise-optimisation-patches.patch +++ b/patches/server/Moonrise-optimisation-patches.patch @@ -23390,8 +23390,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ import org.bukkit.event.server.ServerLoadEvent; + // CraftBukkit end - import co.aikar.timings.MinecraftTimings; // Paper -public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, ChunkIOErrorReporter, CommandSource { +public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, ChunkIOErrorReporter, CommandSource, ca.spottedleaf.moonrise.patches.chunk_system.server.ChunkSystemMinecraftServer { // Paper - rewrite chunk system @@ -26436,12 +26436,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor; - - Objects.requireNonNull(completablefuture); -- if (!completablefuture.isDone()) { // Paper -- com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x, z); // Paper - Add debug for sync chunk loads -- this.level.timings.syncChunkLoad.startTiming(); // Paper - chunkproviderserver_b.managedBlock(completablefuture::isDone); -- this.level.timings.syncChunkLoad.stopTiming(); // Paper -- } // Paper +- // com.destroystokyo.paper.io.SyncLoadFinder.logSyncLoad(this.level, x, z); // Paper - Add debug for sync chunk loads - ChunkResult chunkresult = (ChunkResult) completablefuture.join(); - ChunkAccess ichunkaccess1 = (ChunkAccess) chunkresult.orElse(null); // CraftBukkit - decompile error - @@ -26622,9 +26618,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 public void save(boolean flush) { - this.runDistanceManagerUpdates(); + // Paper - rewrite chunk system - try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings this.chunkMap.saveAllChunks(flush); - } // Paper - Timings + } + @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { } @@ -26647,13 +26643,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 gameprofilerfiller.push("purge"); @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + this.runDistanceManagerUpdates(); gameprofilerfiller.popPush("chunks"); if (tickChunks) { - this.level.timings.chunks.startTiming(); // Paper - timings + ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getPlayerChunkLoader().tick(); // Paper - rewrite chunk system this.tickChunks(); - this.level.timings.chunks.stopTiming(); // Paper - timings this.chunkMap.tick(); + } @@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { gameprofilerfiller.push("filteringTickingChunks"); this.collectTickingChunks(list); @@ -27290,8 +27286,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } } @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + gameprofilerfiller.popPush("tickBlocks"); - timings.chunkTicksBlocks.startTiming(); // Paper if (randomTickSpeed > 0) { - LevelChunkSection[] achunksection = chunk.getSections(); - @@ -27325,7 +27321,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.optimiseRandomTick(chunk, randomTickSpeed); // Paper - optimise random ticking } - timings.chunkTicksBlocks.stopTiming(); // Paper + gameprofilerfiller.pop(); @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe if (fluid1.is(fluid)) { fluid1.tick(this, pos, iblockdata); @@ -27363,18 +27359,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (!savingDisabled) { @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + progressListener.progressStage(Component.translatable("menu.savingChunks")); } - timings.worldSaveChunks.startTiming(); // Paper - chunkproviderserver.save(flush); -+ if (!close) { chunkproviderserver.save(flush); } // Paper - add close param - timings.worldSaveChunks.stopTiming(); // Paper - }// Paper - if (flush) { - this.entityManager.saveAll(); - } else { - this.entityManager.autoSave(); - } ++ if (!close) { chunkproviderserver.save(flush); } // Paper - add close param + // Paper - rewrite chunk system } @@ -31791,7 +31785,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + org.bukkit.craftbukkit.event.CraftEventFactory.callEntitiesLoadEvent(this.level, this.chunkPos, ((ca.spottedleaf.moonrise.patches.chunk_system.level.ChunkSystemServerLevel)this.level).moonrise$getChunkTaskScheduler().chunkHolderManager.getChunkHolder(this.locX, this.locZ).getEntityChunk().getAllEntities()); // Paper - rewrite chunk system if (this.needsDecoration) { - try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper + this.needsDecoration = false; @@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess { } diff --git a/patches/server/Optimize-Hoppers.patch b/patches/server/Optimize-Hoppers.patch index 2f79c8aa44..3b088a1787 100644 --- a/patches/server/Optimize-Hoppers.patch +++ b/patches/server/Optimize-Hoppers.patch @@ -88,14 +88,14 @@ diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.ja index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -0,0 +0,0 @@ import co.aikar.timings.MinecraftTimings; // Paper - import co.aikar.timings.Timing; // Paper +@@ -0,0 +0,0 @@ import org.bukkit.inventory.InventoryHolder; + // CraftBukkit end public abstract class BlockEntity { + static boolean ignoreTileUpdates; // Paper - Perf: Optimize Hoppers - public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper // CraftBukkit start - data containers + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); @@ -0,0 +0,0 @@ public abstract class BlockEntity { public void setChanged() { diff --git a/patches/server/Optimize-World-Time-Updates.patch b/patches/server/Optimize-World-Time-Updates.patch index 759905849f..4832cc5a15 100644 --- a/patches/server/Optimize-World-Time-Updates.patch +++ b/patches/server/Optimize-World-Time-Updates.patch @@ -12,8 +12,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop chunks) { profiler.popPush("naturalSpawnCount"); - this.level.timings.countNaturalMobs.startTiming(); // Paper - timings int j = this.distanceManager.getNaturalSpawnChunkCount(); - NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(j, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)); + // Paper start - Optional per player mob spawns @@ -67,9 +67,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + spawnercreature_d = NaturalSpawner.createState(naturalSpawnChunkCount, this.level.getAllEntities(), this::getFullChunk, !this.level.paperConfig().entities.spawning.perPlayerMobSpawns ? new LocalMobCapCalculator(this.chunkMap) : null, false); + } + // Paper end - Optional per player mob spawns - this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings this.lastSpawnState = spawnercreature_d; + profiler.popPush("spawnAndTick"); diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java diff --git a/patches/server/Paper-config-files.patch b/patches/server/Paper-config-files.patch index ad972ff6bc..5be23480b5 100644 --- a/patches/server/Paper-config-files.patch +++ b/patches/server/Paper-config-files.patch @@ -493,7 +493,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package io.papermc.paper.configuration; + -+import co.aikar.timings.MinecraftTimings; +import com.mojang.logging.LogUtils; +import io.papermc.paper.configuration.constraint.Constraints; +import io.papermc.paper.configuration.type.number.DoubleOr; @@ -510,7 +509,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import org.spongepowered.configurate.objectmapping.meta.Required; +import org.spongepowered.configurate.objectmapping.meta.Setting; + -+import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.OptionalInt; @@ -592,29 +590,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public boolean enableImmediately = false; + } + -+ @Deprecated(forRemoval = true) -+ public Timings timings; -+ -+ @Deprecated(forRemoval = true) -+ public class Timings extends ConfigurationPart { -+ public boolean enabled = false; -+ public boolean verbose = true; -+ public String url = "https://timings.aikar.co/"; -+ public boolean serverNamePrivacy = false; -+ public List hiddenConfigEntries = List.of( -+ "database", -+ "proxies.velocity.secret" -+ ); -+ public int historyInterval = 300; -+ public int historyLength = 3600; -+ public String serverName = "Unknown Server"; -+ -+ @PostProcess -+ private void postProcess() { -+ MinecraftTimings.processConfig(this); -+ } -+ } -+ + public Proxies proxies; + + public class Proxies extends ConfigurationPart { diff --git a/patches/server/Prevent-block-entity-and-entity-crashes.patch b/patches/server/Prevent-block-entity-and-entity-crashes.patch index c2975880ed..a9b9988f22 100644 --- a/patches/server/Prevent-block-entity-and-entity-crashes.patch +++ b/patches/server/Prevent-block-entity-and-entity-crashes.patch @@ -62,5 +62,5 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + LevelChunk.this.removeBlockEntity(this.getPos()); + // Paper end - Prevent block entity and entity crashes // Spigot start - } finally { - this.blockEntity.tickTimer.stopTiming(); + } + } diff --git a/patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch b/patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch index 385a2dae4f..3fedeca0d6 100644 --- a/patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch +++ b/patches/server/Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch @@ -44,9 +44,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/block/Block.java +++ b/src/main/java/net/minecraft/world/level/block/Block.java @@ -0,0 +0,0 @@ public class Block extends BlockBehaviour implements ItemLike { + public static final int UPDATE_LIMIT = 512; protected final StateDefinition stateDefinition; private BlockState defaultBlockState; - // Paper start ++ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed + public final boolean isDestroyable() { + return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits || + this != Blocks.BARRIER && @@ -60,9 +61,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this != Blocks.STRUCTURE_BLOCK && + this != Blocks.JIGSAW; + } - public co.aikar.timings.Timing timing; - public co.aikar.timings.Timing getTiming() { - if (timing == null) { ++ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed + @Nullable + private Item item; + private static final int CACHE_SIZE = 256; diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java diff --git a/patches/server/Rate-options-and-timings-for-sensors-and-behaviors.patch b/patches/server/Rate-options-and-timings-for-sensors-and-behaviors.patch index 793fdc2240..4606707c88 100644 --- a/patches/server/Rate-options-and-timings-for-sensors-and-behaviors.patch +++ b/patches/server/Rate-options-and-timings-for-sensors-and-behaviors.patch @@ -8,25 +8,6 @@ This adds config options to specify the tick rate for sensors 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/co/aikar/timings/MinecraftTimings.java -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -0,0 +0,0 @@ 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/ai/behavior/Behavior.java @@ -37,7 +18,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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, MemoryStatus> requiredMemoryState) { @@ -53,7 +33,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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 } @@ -71,27 +50,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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; -@@ -0,0 +0,0 @@ public abstract class Behavior 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 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/entity/ai/sensing/Sensor.java @@ -102,7 +60,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 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) { @@ -113,7 +70,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 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); @@ -125,11 +81,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - this.timeToTick = (long)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(); this.updateTargetingConditionRanges(entity); + // Paper end this.doTick(world, entity); -+ this.timing.stopTiming(); // Paper - sensor timings } } - diff --git a/patches/server/Remove-CraftScheduler-Async-Task-Debugger.patch b/patches/server/Remove-CraftScheduler-Async-Task-Debugger.patch index 2f353c5788..bb1c993db1 100644 --- a/patches/server/Remove-CraftScheduler-Async-Task-Debugger.patch +++ b/patches/server/Remove-CraftScheduler-Async-Task-Debugger.patch @@ -22,9 +22,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // We don't need to parse pending // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) @@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { + } this.pending.addAll(temp); temp.clear(); - MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper - this.debugHead = this.debugHead.getNextHead(this.currentTick); + //this.debugHead = this.debugHead.getNextHead(this.currentTick); // Paper } diff --git a/patches/server/Remove-Spigot-timings.patch b/patches/server/Remove-Spigot-timings.patch new file mode 100644 index 0000000000..6b3f649b01 --- /dev/null +++ b/patches/server/Remove-Spigot-timings.patch @@ -0,0 +1,967 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 3 Mar 2016 04:00:11 -0600 +Subject: [PATCH] Remove Spigot timings + + +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.Main; + import org.bukkit.event.server.ServerLoadEvent; + // CraftBukkit end + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + + public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, ChunkIOErrorReporter, CommandSource { + +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { + entityplayer.connection.suspendFlushing(); + }); +- SpigotTimings.schedulerTimer.startTiming(); // Spigot + this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit +- SpigotTimings.schedulerTimer.stopTiming(); // Spigot + io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue(this.tickCount); // Paper + gameprofilerfiller.push("commandFunctions"); +- SpigotTimings.commandFunctionsTimer.startTiming(); // Spigot + this.getFunctions().tick(); +- SpigotTimings.commandFunctionsTimer.stopTiming(); // Spigot + gameprofilerfiller.popPush("levels"); + Iterator iterator = this.getAllLevels().iterator(); + + // CraftBukkit start + // Run tasks that are waiting on processing +- SpigotTimings.processQueueTimer.startTiming(); // Spigot + while (!this.processQueue.isEmpty()) { + this.processQueue.remove().run(); + } +- SpigotTimings.processQueueTimer.stopTiming(); // Spigot + +- SpigotTimings.timeUpdateTimer.startTiming(); // Spigot + // Send time updates to everyone, it will get the right time from the world the player is in. + if (this.tickCount % 20 == 0) { + for (int i = 0; i < this.getPlayerList().players.size(); ++i) { +@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); + ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor; + + Objects.requireNonNull(completablefuture); + chunkproviderserver_b.managedBlock(completablefuture::isDone); +- this.level.timings.syncChunkLoadTimer.stopTiming(); // Spigot + ChunkResult chunkresult = (ChunkResult) completablefuture.join(); + ChunkAccess ichunkaccess1 = (ChunkAccess) chunkresult.orElse(null); // CraftBukkit - decompile error + +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + ProfilerFiller gameprofilerfiller = Profiler.get(); + + gameprofilerfiller.push("purge"); +- this.level.timings.doChunkMap.startTiming(); // Spigot + if (this.level.tickRateManager().runsNormally() || !tickChunks || this.level.spigotConfig.unloadFrozenChunks) { // Spigot + this.distanceManager.purgeStaleTickets(); + } + + this.runDistanceManagerUpdates(); +- this.level.timings.doChunkMap.stopTiming(); // Spigot + gameprofilerfiller.popPush("chunks"); + if (tickChunks) { + this.tickChunks(); +- this.level.timings.tracker.startTiming(); // Spigot + this.chunkMap.tick(); +- this.level.timings.tracker.stopTiming(); // Spigot + } + +- this.level.timings.doChunkUnload.startTiming(); // Spigot + gameprofilerfiller.popPush("unload"); + this.chunkMap.tick(shouldKeepTicking); +- this.level.timings.doChunkUnload.stopTiming(); // Spigot + gameprofilerfiller.pop(); + this.clearCache(); + } +@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { + } + + if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { +- this.level.timings.doTickTiles.startTiming(); // Spigot + this.level.tickChunk(chunk, k); +- this.level.timings.doTickTiles.stopTiming(); // Spigot + } + } + +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ import net.minecraft.world.ticks.LevelTicks; + import org.slf4j.Logger; + import org.bukkit.Bukkit; + import org.bukkit.WeatherType; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.event.CraftEventFactory; + import org.bukkit.craftbukkit.generator.CustomWorldChunkManager; + import org.bukkit.craftbukkit.util.WorldUUID; +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + } + + gameprofilerfiller.push("tickPending"); +- this.timings.doTickPending.startTiming(); // Spigot + if (!this.isDebug() && flag) { + j = this.getGameTime(); + gameprofilerfiller.push("blockTicks"); +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + this.fluidTicks.tick(j, 65536, this::tickFluid); + gameprofilerfiller.pop(); + } +- this.timings.doTickPending.stopTiming(); // Spigot + + gameprofilerfiller.popPush("raid"); + if (flag) { +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + this.getChunkSource().tick(shouldKeepTicking, true); + gameprofilerfiller.popPush("blockEvents"); + if (flag) { +- this.timings.doSounds.startTiming(); // Spigot + this.runBlockEvents(); +- this.timings.doSounds.stopTiming(); // Spigot + } + + this.handlingTick = false; +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + + if (flag1 || this.emptyTime++ < 300) { + gameprofilerfiller.push("entities"); +- this.timings.tickEntities.startTiming(); // Spigot + if (this.dragonFight != null && flag) { + gameprofilerfiller.push("dragonFight"); + this.dragonFight.tick(); +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + } + + org.spigotmc.ActivationRange.activateEntities(this); // Spigot +- this.timings.entityTick.startTiming(); // Spigot + this.entityTickList.forEach((entity) -> { + if (!entity.isRemoved()) { + if (!tickratemanager.isEntityFrozen(entity)) { +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + } + } + }); +- this.timings.entityTick.stopTiming(); // Spigot +- this.timings.tickEntities.stopTiming(); // Spigot + gameprofilerfiller.pop(); + this.tickBlockEntities(); + } +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + return; + } + // Spigot end +- entity.tickTimer.startTiming(); // Spigot + entity.setOldPosAndRot(); + ProfilerFiller gameprofilerfiller = Profiler.get(); + +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + + this.tickPassenger(entity, entity1); + } +- entity.tickTimer.stopTiming(); // Spigot + + } + +diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java ++++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + + @Override + public void tick() { +- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.startTiming(); // Spigot + if (this.ackBlockChangesUpTo > -1) { + this.send(new ClientboundBlockChangedAckPacket(this.ackBlockChangesUpTo)); + this.ackBlockChangesUpTo = -1; +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 + this.disconnect((Component) Component.translatable("multiplayer.disconnect.idling")); + } +- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.stopTiming(); // Spigot + + } + +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + } + + private void handleCommand(String s) { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot + if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot + this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s); + +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + this.cserver.getPluginManager().callEvent(event); + + if (event.isCancelled()) { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot + return; + } + +@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl + java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); + return; + } finally { +- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot + } + } + // CraftBukkit end +diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/Entity.java ++++ b/src/main/java/net/minecraft/world/entity/Entity.java +@@ -0,0 +0,0 @@ import org.bukkit.command.CommandSender; + import org.bukkit.entity.Hanging; + import org.bukkit.entity.LivingEntity; + import org.bukkit.entity.Vehicle; +-import org.spigotmc.CustomTimingsHandler; // Spigot + import org.bukkit.event.entity.EntityCombustByEntityEvent; + import org.bukkit.event.hanging.HangingBreakByEntityEvent; + import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; +@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + // Marks an entity, that it was removed by a plugin via Entity#remove + // Main use case currently is for SPIGOT-7487, preventing dropping of leash when leash is removed + public boolean pluginRemoved = false; +- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot + // Spigot start + public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); + public final boolean defaultActivationState; +@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + } + + public void move(MoverType type, Vec3 movement) { +- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot + if (this.noPhysics) { + this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z); + } else { +@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + gameprofilerfiller.pop(); + } + } +- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot + } + + private void applyMovementEmissionAndPlaySound(Entity.MovementEmission moveEffect, Vec3 movement, BlockPos landingPos, BlockState landingState) { +diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java ++++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java +@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityTeleportEvent; + import org.bukkit.event.player.PlayerItemConsumeEvent; + // CraftBukkit end + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot +- + public abstract class LivingEntity extends Entity implements Attackable { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { + + @Override + public void tick() { +- SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot + super.tick(); + this.updatingUsingItem(); + this.updateSwimAmount(); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { + } + + if (!this.isRemoved()) { +- SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot + this.aiStep(); +- SpigotTimings.timerEntityTickRest.startTiming(); // Spigot + } + + double d0 = this.getX() - this.xo; +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { + } + + this.elytraAnimationState.tick(); +- SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot + } + + public void detectEquipmentUpdatesPublic() { // CraftBukkit +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { + ProfilerFiller gameprofilerfiller = Profiler.get(); + + gameprofilerfiller.push("ai"); +- SpigotTimings.timerEntityAI.startTiming(); // Spigot + if (this.isImmobile()) { + this.jumping = false; + this.xxa = 0.0F; +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { + this.serverAiStep(); + gameprofilerfiller.pop(); + } +- SpigotTimings.timerEntityAI.stopTiming(); // Spigot + + gameprofilerfiller.pop(); + gameprofilerfiller.push("jump"); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { + this.resetFallDistance(); + } + +- SpigotTimings.timerEntityAIMove.startTiming(); // Spigot + label112: + { + LivingEntity entityliving = this.getControllingPassenger(); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { + + this.travel(vec3d1); + } +- SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot + + if (!this.level().isClientSide() || this.isControlledByLocalInstance()) { + this.applyEffectsFromBlocks(); +@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { + this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); + } + +- SpigotTimings.timerEntityAICollision.startTiming(); // Spigot + this.pushEntities(); +- SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot + gameprofilerfiller.pop(); + world = this.level(); + if (world instanceof ServerLevel worldserver) { +diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/Level.java ++++ b/src/main/java/net/minecraft/world/level/Level.java +@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePa + import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.CraftServer; + import org.bukkit.craftbukkit.CraftWorld; +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.block.CapturedBlockState; + import org.bukkit.craftbukkit.block.CraftBlockState; + import org.bukkit.craftbukkit.block.data.CraftBlockData; +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + // Paper end - add paper world config + +- public final SpigotTimings.WorldTimingsHandler timings; // Spigot + public static BlockPos lastPhysicsProblem; // Spigot + private org.spigotmc.TickLimiter entityLimiter; + private org.spigotmc.TickLimiter tileLimiter; +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {} + }); + // CraftBukkit end +- this.timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings + this.entityLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.entityMaxTickTime); + this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime); + } +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + ProfilerFiller gameprofilerfiller = Profiler.get(); + + gameprofilerfiller.push("blockEntities"); +- this.timings.tileEntityPending.startTiming(); // Spigot + this.tickingBlockEntities = true; + if (!this.pendingBlockEntityTickers.isEmpty()) { + this.blockEntityTickers.addAll(this.pendingBlockEntityTickers); + this.pendingBlockEntityTickers.clear(); + } +- this.timings.tileEntityPending.stopTiming(); // Spigot + +- this.timings.tileEntityTick.startTiming(); // Spigot + // Spigot start + // Iterator iterator = this.blockEntityTickers.iterator(); + boolean flag = this.tickRateManager().runsNormally(); +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + } + } + +- this.timings.tileEntityTick.stopTiming(); // Spigot + this.tickingBlockEntities = false; + gameprofilerfiller.pop(); + this.spigotConfig.currentPrimedTnt = 0; // Spigot +@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { + + public void guardEntityTick(Consumer tickConsumer, T entity) { + try { +- SpigotTimings.tickEntityTimer.startTiming(); // Spigot + tickConsumer.accept(entity); +- SpigotTimings.tickEntityTimer.stopTiming(); // Spigot + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); +diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java ++++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + ProfilerFiller gameprofilerfiller = Profiler.get(); + + gameprofilerfiller.push("spawner"); +- world.timings.mobSpawn.startTiming(); // Spigot + Iterator iterator = spawnableGroups.iterator(); + + while (iterator.hasNext()) { +@@ -0,0 +0,0 @@ public final class NaturalSpawner { + } + } + +- world.timings.mobSpawn.stopTiming(); // Spigot + gameprofilerfiller.pop(); + } + +diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java ++++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java +@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; + import org.bukkit.inventory.InventoryHolder; + // CraftBukkit end + +-import org.spigotmc.CustomTimingsHandler; // Spigot +- + public abstract class BlockEntity { + +- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot + // CraftBukkit start - data containers + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); + public CraftPersistentDataContainer persistentDataContainer; +diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java +@@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess { + ProfilerFiller gameprofilerfiller = Profiler.get(); + + gameprofilerfiller.push(this::getType); +- this.blockEntity.tickTimer.startTiming(); // Spigot + BlockState iblockdata = LevelChunk.this.getBlockState(blockposition); + + if (this.blockEntity.getType().isValid(iblockdata)) { +@@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess { + this.blockEntity.fillCrashReportCategory(crashreportsystemdetails); + throw new ReportedException(crashreport); + // Spigot start +- } finally { +- this.blockEntity.tickTimer.stopTiming(); +- // Spigot end + } + } + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/src/main/java/net/minecraft/world/level/chunk/storage/SerializableChunkData.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/storage/SerializableChunkData.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/SerializableChunkData.java +@@ -0,0 +0,0 @@ public record SerializableChunkData(Registry biomeRegistry, ChunkPos chun + @Nullable + private static LevelChunk.PostLoadProcessor postLoadChunk(ServerLevel world, List entities, List blockEntities) { + return entities.isEmpty() && blockEntities.isEmpty() ? null : (chunk) -> { +- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot + if (!entities.isEmpty()) { + world.addLegacyChunkEntities(EntityType.loadEntitiesRecursive(entities, world, EntitySpawnReason.LOAD)); + } +- world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot + + Iterator iterator = blockEntities.iterator(); + +- world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot + while (iterator.hasNext()) { + CompoundTag nbttagcompound = (CompoundTag) iterator.next(); + boolean flag = nbttagcompound.getBoolean("keepPacked"); +@@ -0,0 +0,0 @@ public record SerializableChunkData(Registry biomeRegistry, ChunkPos chun + } + } + } +- world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot + + }; + } +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + this.saveCommandsConfig(); + this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); + this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); +- this.pluginManager.useTimings(this.configuration.getBoolean("settings.plugin-profiling")); + this.overrideSpawnLimits(); + console.autosavePeriod = this.configuration.getInt("ticks-per.autosave"); + this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose")); +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() + { + ++ @Deprecated + @Override + public YamlConfiguration getConfig() + { + return org.spigotmc.SpigotConfig.config; + } + ++ @Override ++ public YamlConfiguration getBukkitConfig() ++ { ++ return configuration; ++ } ++ ++ @Override ++ public YamlConfiguration getSpigotConfig() ++ { ++ return org.spigotmc.SpigotConfig.config; ++ } ++ ++ @Override ++ public YamlConfiguration getPaperConfig() ++ { ++ return CraftServer.this.console.paperConfigurations.createLegacyObject(CraftServer.this.console); ++ } ++ + @Override + public void restart() { + org.spigotmc.RestartCommand.restart(); +diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +deleted file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java ++++ /dev/null +@@ -0,0 +0,0 @@ +-package org.bukkit.craftbukkit; +- +-import java.util.HashMap; +-import net.minecraft.world.entity.Entity; +-import net.minecraft.world.level.Level; +-import net.minecraft.world.level.block.entity.BlockEntity; +-import net.minecraft.world.level.storage.PrimaryLevelData; +-import org.bukkit.craftbukkit.scheduler.CraftTask; +-import org.bukkit.plugin.java.JavaPluginLoader; +-import org.bukkit.scheduler.BukkitTask; +-import org.spigotmc.CustomTimingsHandler; +- +-public class SpigotTimings { +- +- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); +- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); +- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); +- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); +- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); +- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); +- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); +- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); +- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); +- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); +- +- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); +- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); +- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); +- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); +- +- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); +- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); +- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); +- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); +- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); +- +- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); +- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); +- +- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); +- +- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); +- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); +- +- public static final HashMap entityTypeTimingMap = new HashMap(); +- public static final HashMap tileEntityTypeTimingMap = new HashMap(); +- public static final HashMap pluginTaskTimingMap = new HashMap(); +- +- /** +- * Gets a timer associated with a plugins tasks. +- * @param task +- * @param period +- * @return +- */ +- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { +- if (!task.isSync()) { +- return null; +- } +- String plugin; +- final CraftTask ctask = (CraftTask) task; +- +- if (task.getOwner() != null) { +- plugin = task.getOwner().getDescription().getFullName(); +- } else { +- plugin = "Unknown"; +- } +- String taskname = ctask.getTaskName(); +- +- String name = "Task: " + plugin + " Runnable: " + taskname; +- if (period > 0) { +- name += "(interval:" + period + ")"; +- } else { +- name += "(Single)"; +- } +- CustomTimingsHandler result = SpigotTimings.pluginTaskTimingMap.get(name); +- if (result == null) { +- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); +- SpigotTimings.pluginTaskTimingMap.put(name, result); +- } +- return result; +- } +- +- /** +- * Get a named timer for the specified entity type to track type specific timings. +- * @param entity +- * @return +- */ +- public static CustomTimingsHandler getEntityTimings(Entity entity) { +- String entityType = entity.getClass().getName(); +- CustomTimingsHandler result = SpigotTimings.entityTypeTimingMap.get(entityType); +- if (result == null) { +- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), SpigotTimings.activatedEntityTimer); +- SpigotTimings.entityTypeTimingMap.put(entityType, result); +- } +- return result; +- } +- +- /** +- * Get a named timer for the specified tile entity type to track type specific timings. +- * @param entity +- * @return +- */ +- public static CustomTimingsHandler getTileEntityTimings(BlockEntity entity) { +- String entityType = entity.getClass().getName(); +- CustomTimingsHandler result = SpigotTimings.tileEntityTypeTimingMap.get(entityType); +- if (result == null) { +- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), SpigotTimings.tickTileEntityTimer); +- SpigotTimings.tileEntityTypeTimingMap.put(entityType, result); +- } +- return result; +- } +- +- /** +- * Set of timers per world, to track world specific timings. +- */ +- public static class WorldTimingsHandler { +- public final CustomTimingsHandler mobSpawn; +- public final CustomTimingsHandler doChunkUnload; +- public final CustomTimingsHandler doTickPending; +- public final CustomTimingsHandler doTickTiles; +- public final CustomTimingsHandler doChunkMap; +- public final CustomTimingsHandler doSounds; +- public final CustomTimingsHandler entityTick; +- public final CustomTimingsHandler tileEntityTick; +- public final CustomTimingsHandler tileEntityPending; +- public final CustomTimingsHandler tracker; +- public final CustomTimingsHandler doTick; +- public final CustomTimingsHandler tickEntities; +- +- public final CustomTimingsHandler syncChunkLoadTimer; +- public final CustomTimingsHandler syncChunkLoadStructuresTimer; +- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; +- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; +- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; +- public final CustomTimingsHandler syncChunkLoadPostTimer; +- +- public WorldTimingsHandler(Level server) { +- String name = ((PrimaryLevelData) server.levelData).getLevelName() + " - "; +- +- this.mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); +- this.doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); +- this.doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); +- this.doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); +- this.doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); +- this.doSounds = new CustomTimingsHandler("** " + name + "doSounds"); +- this.entityTick = new CustomTimingsHandler("** " + name + "entityTick"); +- this.tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); +- this.tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); +- +- this.syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); +- this.syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); +- this.syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); +- this.syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); +- this.syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); +- this.syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); +- +- +- this.tracker = new CustomTimingsHandler(name + "tracker"); +- this.doTick = new CustomTimingsHandler(name + "doTick"); +- this.tickEntities = new CustomTimingsHandler(name + "tickEntities"); +- } +- } +-} +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { + + CraftPlayer.this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSystemChatPacket(components, position == net.md_5.bungee.api.ChatMessageType.ACTION_BAR)); + } ++ ++ // Paper start ++ @Override ++ public int getPing() ++ { ++ return CraftPlayer.this.getPing(); ++ } ++ // Paper end + }; + + public Player.Spigot spigot() +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java +@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { + if (task.isSync()) { + this.currentTask = task; + try { +- task.timings.startTiming(); // Spigot + task.run(); +- task.timings.stopTiming(); // Spigot + } catch (final Throwable throwable) { + task.getOwner().getLogger().log( + Level.WARNING, +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +@@ -0,0 +0,0 @@ + package org.bukkit.craftbukkit.scheduler; + + import java.util.function.Consumer; ++ + import org.bukkit.Bukkit; + import org.bukkit.plugin.Plugin; + import org.bukkit.scheduler.BukkitTask; + +-import org.bukkit.craftbukkit.SpigotTimings; // Spigot +-import org.spigotmc.CustomTimingsHandler; // Spigot +- + public class CraftTask implements BukkitTask, Runnable { // Spigot + + private volatile CraftTask next = null; +@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + */ + private volatile long period; + private long nextRun; +- private final Runnable rTask; +- private final Consumer cTask; ++ public final Runnable rTask; ++ public final Consumer cTask; + private final Plugin plugin; + private final int id; + private final long createdAt = System.nanoTime(); + +- final CustomTimingsHandler timings; // Spigot + CraftTask() { + this(null, null, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); + } +@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + } + this.id = id; + this.period = period; +- this.timings = this.isSync() ? SpigotTimings.getPluginTaskTimings(this, period) : null; // Spigot + } + + @Override +@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot + return true; + } + +- // Spigot start +- public String getTaskName() { +- return (this.getTaskClass() == null) ? "Unknown" : this.getTaskClass().getName(); +- } +- // Spigot end + } +diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java ++++ b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java +@@ -0,0 +0,0 @@ + package org.bukkit.craftbukkit.util; + + import org.bukkit.util.CachedServerIcon; ++import org.jetbrains.annotations.Nullable; + + public class CraftIconCache implements CachedServerIcon { + public final byte[] value; +@@ -0,0 +0,0 @@ public class CraftIconCache implements CachedServerIcon { + public CraftIconCache(final byte[] value) { + this.value = value; + } ++ ++ @Override ++ public @Nullable String getData() { ++ if (this.value == null) { ++ return null; ++ } ++ return "data:image/png;base64," + new String(java.util.Base64.getEncoder().encode(this.value), java.nio.charset.StandardCharsets.UTF_8); ++ } + } +diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/spigotmc/ActivationRange.java ++++ b/src/main/java/org/spigotmc/ActivationRange.java +@@ -0,0 +0,0 @@ import net.minecraft.world.entity.projectile.ThrownTrident; + import net.minecraft.world.entity.raid.Raider; + import net.minecraft.world.level.Level; + import net.minecraft.world.phys.AABB; +-import org.bukkit.craftbukkit.SpigotTimings; + + public class ActivationRange + { +@@ -0,0 +0,0 @@ public class ActivationRange + */ + public static void activateEntities(Level world) + { +- SpigotTimings.entityActivationCheckTimer.startTiming(); + final int miscActivationRange = world.spigotConfig.miscActivationRange; + final int raiderActivationRange = world.spigotConfig.raiderActivationRange; + final int animalActivationRange = world.spigotConfig.animalActivationRange; +@@ -0,0 +0,0 @@ public class ActivationRange + + world.getEntities().get(ActivationRange.maxBB, ActivationRange::activateEntity); + } +- SpigotTimings.entityActivationCheckTimer.stopTiming(); + } + + /** +@@ -0,0 +0,0 @@ public class ActivationRange + */ + public static boolean checkIfActive(Entity entity) + { +- SpigotTimings.checkIfActiveTimer.startTiming(); + // Never safe to skip fireworks or entities not yet added to chunk + if ( entity instanceof FireworkRocketEntity ) { +- SpigotTimings.checkIfActiveTimer.stopTiming(); + return true; + } + +@@ -0,0 +0,0 @@ public class ActivationRange + { + isActive = false; + } +- SpigotTimings.checkIfActiveTimer.stopTiming(); + return isActive; + } + } diff --git a/patches/server/Server-Tick-Events.patch b/patches/server/Server-Tick-Events.patch index 81750c9434..5cd827d63d 100644 --- a/patches/server/Server-Tick-Events.patch +++ b/patches/server/Server-Tick-Events.patch @@ -10,17 +10,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function serverFactory) { AtomicReference atomicreference = new AtomicReference(); @@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop -Date: Tue, 21 Apr 2020 01:53:22 -0700 -Subject: [PATCH] Time scoreboard search - -Plugins leaking scoreboards will make this very expensive, -let server owners debug it easily - -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/co/aikar/timings/MinecraftTimings.java -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -0,0 +0,0 @@ public final class MinecraftTimings { - - public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); - public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); -+ public static final Timing scoreboardScoreSearch = Timings.ofSafe("Scoreboard score search"); // Paper - add timings for scoreboard search - - private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); - -diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java -@@ -0,0 +0,0 @@ public final class CraftScoreboardManager implements ScoreboardManager { - - // CraftBukkit method - public void forAllObjectives(ObjectiveCriteria criteria, ScoreHolder holder, Consumer consumer) { -+ // Paper start - add timings for scoreboard search -+ // plugins leaking scoreboards will make this very expensive, let server owners debug it easily -+ co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.startTimingIfSync(); -+ try { -+ // Paper end - add timings for scoreboard search - for (CraftScoreboard scoreboard : this.scoreboards) { - Scoreboard board = scoreboard.board; - board.forAllObjectives(criteria, holder, (score) -> consumer.accept(score)); - } -+ } finally { // Paper start - add timings for scoreboard search -+ co.aikar.timings.MinecraftTimings.scoreboardScoreSearch.stopTimingIfSync(); -+ } -+ // Paper end - add timings for scoreboard search - } - } diff --git a/patches/server/Timings-v2.patch b/patches/server/Timings-v2.patch deleted file mode 100644 index f09278a978..0000000000 --- a/patches/server/Timings-v2.patch +++ /dev/null @@ -1,2077 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 3 Mar 2016 04:00:11 -0600 -Subject: [PATCH] Timings v2 - - -diff --git a/src/main/java/co/aikar/timings/MinecraftTimings.java b/src/main/java/co/aikar/timings/MinecraftTimings.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/MinecraftTimings.java -@@ -0,0 +0,0 @@ -+package co.aikar.timings; -+ -+import com.google.common.collect.MapMaker; -+import io.papermc.paper.configuration.GlobalConfiguration; -+import net.minecraft.commands.functions.CommandFunction; -+import net.minecraft.network.protocol.Packet; -+import net.minecraft.world.level.block.Block; -+import net.minecraft.world.level.block.entity.BlockEntity; -+import org.bukkit.plugin.Plugin; -+import org.bukkit.scheduler.BukkitTask; -+ -+import org.bukkit.craftbukkit.scheduler.CraftTask; -+ -+import java.util.Map; -+ -+// TODO: Re-implement missing timers -+@Deprecated(forRemoval = true) -+public final class MinecraftTimings { -+ -+ public static final Timing serverOversleep = Timings.ofSafe("Server Oversleep"); -+ public static final Timing playerListTimer = Timings.ofSafe("Player List"); -+ public static final Timing commandFunctionsTimer = Timings.ofSafe("Command Functions"); -+ public static final Timing connectionTimer = Timings.ofSafe("Connection Handler"); -+ public static final Timing tickablesTimer = Timings.ofSafe("Tickables"); -+ public static final Timing minecraftSchedulerTimer = Timings.ofSafe("Minecraft Scheduler"); -+ public static final Timing bukkitSchedulerTimer = Timings.ofSafe("Bukkit Scheduler"); -+ public static final Timing bukkitSchedulerPendingTimer = Timings.ofSafe("Bukkit Scheduler - Pending"); -+ public static final Timing bukkitSchedulerFinishTimer = Timings.ofSafe("Bukkit Scheduler - Finishing"); -+ public static final Timing chunkIOTickTimer = Timings.ofSafe("ChunkIOTick"); -+ public static final Timing timeUpdateTimer = Timings.ofSafe("Time Update"); -+ public static final Timing serverCommandTimer = Timings.ofSafe("Server Command"); -+ public static final Timing savePlayers = Timings.ofSafe("Save Players"); -+ -+ public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity"); -+ public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity"); -+ public static final Timing packetProcessTimer = Timings.ofSafe("## Packet Processing"); -+ public static final Timing scheduledBlocksTimer = Timings.ofSafe("## Scheduled Blocks"); -+ public static final Timing structureGenerationTimer = Timings.ofSafe("Structure Generation"); -+ -+ public static final Timing processQueueTimer = Timings.ofSafe("processQueue"); -+ public static final Timing processTasksTimer = Timings.ofSafe("processTasks"); -+ -+ public static final Timing playerCommandTimer = Timings.ofSafe("playerCommand"); -+ -+ public static final Timing entityActivationCheckTimer = Timings.ofSafe("entityActivationCheck"); -+ -+ public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update"); -+ public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate"); -+ -+ private static final Map, String> taskNameCache = new MapMaker().weakKeys().makeMap(); -+ -+ private MinecraftTimings() {} -+ -+ public static Timing getInternalTaskName(String taskName) { -+ return Timings.ofSafe(taskName); -+ } -+ -+ /** -+ * Gets a timer associated with a plugins tasks. -+ * @param bukkitTask -+ * @param period -+ * @return -+ */ -+ public static Timing getPluginTaskTimings(BukkitTask bukkitTask, long period) { -+ if (!bukkitTask.isSync()) { -+ return NullTimingHandler.NULL; -+ } -+ Plugin plugin; -+ -+ CraftTask craftTask = (CraftTask) bukkitTask; -+ -+ final Class taskClass = craftTask.getTaskClass(); -+ if (bukkitTask.getOwner() != null) { -+ plugin = bukkitTask.getOwner(); -+ } else { -+ plugin = TimingsManager.getPluginByClassloader(taskClass); -+ } -+ -+ final String taskname = taskNameCache.computeIfAbsent(taskClass, clazz -> { -+ try { -+ String clsName = !clazz.isMemberClass() -+ ? clazz.getName() -+ : clazz.getCanonicalName(); -+ if (clsName != null && clsName.contains("$Lambda$")) { -+ clsName = clsName.replaceAll("(Lambda\\$.*?)/.*", "$1"); -+ } -+ return clsName != null ? clsName : "UnknownTask"; -+ } catch (Throwable ex) { -+ new Exception("Error occurred detecting class name", ex).printStackTrace(); -+ return "MangledClassFile"; -+ } -+ }); -+ -+ StringBuilder name = new StringBuilder(64); -+ name.append("Task: ").append(taskname); -+ if (period > 0) { -+ name.append(" (interval:").append(period).append(")"); -+ } else { -+ name.append(" (Single)"); -+ } -+ -+ if (plugin == null) { -+ return Timings.ofSafe(null, name.toString()); -+ } -+ -+ return Timings.ofSafe(plugin, name.toString()); -+ } -+ -+ /** -+ * Get a named timer for the specified entity type to track type specific timings. -+ * @param entityType -+ * @return -+ */ -+ public static Timing getEntityTimings(String entityType, String type) { -+ return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType + " - " + type, tickEntityTimer); -+ } -+ -+ /** -+ * Get a named timer for the specified tile entity type to track type specific timings. -+ * @param entity -+ * @return -+ */ -+ public static Timing getTileEntityTimings(BlockEntity entity) { -+ String entityType = entity.getClass().getName(); -+ return Timings.ofSafe("Minecraft", "## tickTileEntity - " + entityType, tickTileEntityTimer); -+ } -+ public static Timing getCancelTasksTimer() { -+ return Timings.ofSafe("Cancel Tasks"); -+ } -+ public static Timing getCancelTasksTimer(Plugin plugin) { -+ return Timings.ofSafe(plugin, "Cancel Tasks"); -+ } -+ -+ public static void stopServer() { -+ TimingsManager.stopServer(); -+ } -+ -+ public static Timing getBlockTiming(Block block) { -+ return Timings.ofSafe("## Scheduled Block: " + block.toString(), scheduledBlocksTimer); -+ } -+/* -+ public static Timing getStructureTiming(StructureGenerator structureGenerator) { -+ return Timings.ofSafe("Structure Generator - " + structureGenerator.getName(), structureGenerationTimer); -+ }*/ -+ -+ public static Timing getPacketTiming(Packet packet) { -+ return Timings.ofSafe("## Packet - " + packet.getClass().getName(), packetProcessTimer); -+ } -+ -+ public static Timing getCommandFunctionTiming(CommandFunction function) { -+ return Timings.ofSafe("Command Function - " + function.id()); -+ } -+ -+ public static void processConfig(GlobalConfiguration.Timings config) { -+ TimingsManager.url = config.url; -+ if (!TimingsManager.url.endsWith("/")) { -+ TimingsManager.url += "/"; -+ } -+ TimingsManager.privacy = config.serverNamePrivacy; -+ if (!config.hiddenConfigEntries.contains("proxies.velocity.secret")) { -+ config.hiddenConfigEntries.add("proxies.velocity.secret"); -+ } -+ TimingsManager.hiddenConfigs.addAll(config.hiddenConfigEntries); -+ co.aikar.timings.Timings.setVerboseTimingsEnabled(config.verbose); -+ co.aikar.timings.Timings.setTimingsEnabled(config.enabled); -+ co.aikar.timings.Timings.setHistoryInterval(config.historyInterval * 20); -+ co.aikar.timings.Timings.setHistoryLength(config.historyLength * 20); -+ } -+} -diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/TimingsExport.java -@@ -0,0 +0,0 @@ -+/* -+ * This file is licensed under the MIT License (MIT). -+ * -+ * Copyright (c) 2014 Daniel Ennis -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a copy -+ * of this software and associated documentation files (the "Software"), to deal -+ * in the Software without restriction, including without limitation the rights -+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -+ * copies of the Software, and to permit persons to whom the Software is -+ * furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice shall be included in -+ * all copies or substantial portions of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -+ * THE SOFTWARE. -+ */ -+package co.aikar.timings; -+ -+import com.google.common.collect.Sets; -+import io.papermc.paper.adventure.PaperAdventure; -+import net.kyori.adventure.text.event.ClickEvent; -+import net.kyori.adventure.text.format.NamedTextColor; -+import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer; -+import net.minecraft.server.MinecraftServer; -+import org.apache.commons.lang.StringUtils; -+import org.bukkit.Bukkit; -+import org.bukkit.Material; -+import org.bukkit.configuration.ConfigurationSection; -+import org.bukkit.configuration.MemorySection; -+import org.bukkit.entity.EntityType; -+import org.json.simple.JSONObject; -+import org.json.simple.JSONValue; -+import oshi.SystemInfo; -+import oshi.hardware.HardwareAbstractionLayer; -+ -+import java.io.ByteArrayOutputStream; -+import java.io.IOException; -+import java.io.InputStream; -+import java.io.OutputStream; -+import java.lang.management.ManagementFactory; -+import java.lang.management.OperatingSystemMXBean; -+import java.lang.management.RuntimeMXBean; -+import java.net.HttpURLConnection; -+import java.net.InetAddress; -+import java.net.URL; -+import java.util.List; -+import java.util.Map; -+import java.util.Set; -+import java.util.logging.Level; -+import java.util.zip.GZIPOutputStream; -+ -+import static co.aikar.timings.TimingsManager.HISTORY; -+import static co.aikar.util.JSONUtil.appendObjectData; -+import static co.aikar.util.JSONUtil.createObject; -+import static co.aikar.util.JSONUtil.pair; -+import static co.aikar.util.JSONUtil.toArray; -+import static co.aikar.util.JSONUtil.toArrayMapper; -+import static co.aikar.util.JSONUtil.toObjectMapper; -+import static net.kyori.adventure.text.Component.text; -+ -+@SuppressWarnings({"rawtypes", "SuppressionAnnotation"}) -+@Deprecated(forRemoval = true) -+public class TimingsExport extends Thread { -+ -+ private final TimingsReportListener listeners; -+ private final Map out; -+ private final TimingHistory[] history; -+ private static long lastReport = 0; -+ -+ private TimingsExport(TimingsReportListener listeners, Map out, TimingHistory[] history) { -+ super("Timings paste thread"); -+ this.listeners = listeners; -+ this.out = out; -+ this.history = history; -+ } -+ -+ /** -+ * Checks if any pending reports are being requested, and builds one if needed. -+ */ -+ public static void reportTimings() { -+ if (Timings.requestingReport.isEmpty()) { -+ return; -+ } -+ TimingsReportListener listeners = new TimingsReportListener(Timings.requestingReport); -+ listeners.addConsoleIfNeeded(); -+ -+ Timings.requestingReport.clear(); -+ long now = System.currentTimeMillis(); -+ final long lastReportDiff = now - lastReport; -+ if (lastReportDiff < 60000) { -+ listeners.sendMessage(text("Please wait at least 1 minute in between Timings reports. (" + (int)((60000 - lastReportDiff) / 1000) + " seconds)", NamedTextColor.RED)); -+ listeners.done(); -+ return; -+ } -+ final long lastStartDiff = now - TimingsManager.timingStart; -+ if (lastStartDiff < 180000) { -+ listeners.sendMessage(text("Please wait at least 3 minutes before generating a Timings report. Unlike Timings v1, v2 benefits from longer timings and is not as useful with short timings. (" + (int)((180000 - lastStartDiff) / 1000) + " seconds)", NamedTextColor.RED)); -+ listeners.done(); -+ return; -+ } -+ listeners.sendMessage(text("Preparing Timings Report...", NamedTextColor.GREEN)); -+ lastReport = now; -+ Map parent = createObject( -+ // Get some basic system details about the server -+ pair("version", Bukkit.getVersion()), -+ pair("maxplayers", Bukkit.getMaxPlayers()), -+ pair("start", TimingsManager.timingStart / 1000), -+ pair("end", System.currentTimeMillis() / 1000), -+ pair("online-mode", Bukkit.getServer().getOnlineMode()), -+ pair("sampletime", (System.currentTimeMillis() - TimingsManager.timingStart) / 1000), -+ pair("datapacks", toArrayMapper(MinecraftServer.getServer().getPackRepository().getSelectedPacks(), pack -> { -+ return PlainTextComponentSerializer.plainText().serialize(PaperAdventure.asAdventure(pack.getChatLink(true))); -+ })) -+ ); -+ if (!TimingsManager.privacy) { -+ appendObjectData(parent, -+ pair("server", Bukkit.getUnsafe().getTimingsServerName()), -+ pair("motd", Bukkit.getServer().getMotd()), -+ pair("icon", Bukkit.getServer().getServerIcon().getData()) -+ ); -+ } -+ -+ final Runtime runtime = Runtime.getRuntime(); -+ RuntimeMXBean runtimeBean = ManagementFactory.getRuntimeMXBean(); -+ -+ OperatingSystemMXBean osInfo = ManagementFactory.getOperatingSystemMXBean(); -+ -+ HardwareAbstractionLayer hardwareInfo = new SystemInfo().getHardware(); -+ -+ parent.put("system", createObject( -+ pair("timingcost", getCost()), -+ pair("loadavg", osInfo.getSystemLoadAverage()), -+ pair("name", System.getProperty("os.name")), -+ pair("version", System.getProperty("os.version")), -+ pair("jvmversion", System.getProperty("java.version")), -+ pair("jvmvendor", System.getProperty("java.vendor")), -+ pair("jvmvendorversion", System.getProperty("java.vendor.version")), -+ pair("arch", System.getProperty("os.arch")), -+ pair("maxmem", runtime.maxMemory()), -+ pair("memory", createObject( -+ pair("heap", ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().toString()), -+ pair("nonheap", ManagementFactory.getMemoryMXBean().getNonHeapMemoryUsage().toString()), -+ pair("finalizing", ManagementFactory.getMemoryMXBean().getObjectPendingFinalizationCount()) -+ )), -+ pair("cpu", runtime.availableProcessors()), -+ pair("cpuname", hardwareInfo.getProcessor().getProcessorIdentifier().getName().trim()), -+ pair("runtime", runtimeBean.getUptime()), -+ pair("flags", StringUtils.join(runtimeBean.getInputArguments(), " ")), -+ pair("gc", toObjectMapper(ManagementFactory.getGarbageCollectorMXBeans(), input -> pair(input.getName(), toArray(input.getCollectionCount(), input.getCollectionTime())))) -+ ) -+ ); -+ -+ parent.put("worlds", toObjectMapper(MinecraftServer.getServer().getAllLevels(), world -> { -+ if (world.getWorld().getName().equals("worldeditregentempworld")) return null; -+ return pair(world.getWorld().getName(), createObject( -+ pair("gamerules", toObjectMapper(world.getWorld().getGameRules(), rule -> { -+ return pair(rule, world.getWorld().getGameRuleValue(rule)); -+ })), -+ pair("ticking-distance", world.getWorld().getSimulationDistance()), -+ pair("no-ticking-distance", world.getWorld().getViewDistance()), -+ pair("sending-distance", world.getWorld().getSendViewDistance()) -+ )); -+ })); -+ -+ Set tileEntityTypeSet = Sets.newHashSet(); -+ Set entityTypeSet = Sets.newHashSet(); -+ -+ int size = HISTORY.size(); -+ TimingHistory[] history = new TimingHistory[size + 1]; -+ int i = 0; -+ for (TimingHistory timingHistory : HISTORY) { -+ tileEntityTypeSet.addAll(timingHistory.tileEntityTypeSet); -+ entityTypeSet.addAll(timingHistory.entityTypeSet); -+ history[i++] = timingHistory; -+ } -+ -+ history[i] = new TimingHistory(); // Current snapshot -+ tileEntityTypeSet.addAll(history[i].tileEntityTypeSet); -+ entityTypeSet.addAll(history[i].entityTypeSet); -+ -+ -+ Map handlers = createObject(); -+ Map groupData; -+ synchronized (TimingIdentifier.GROUP_MAP) { -+ for (TimingIdentifier.TimingGroup group : TimingIdentifier.GROUP_MAP.values()) { -+ synchronized (group.handlers) { -+ for (TimingHandler id : group.handlers) { -+ -+ if (!id.isTimed() && !id.isSpecial()) { -+ continue; -+ } -+ -+ String name = id.identifier.name; -+ if (name.startsWith("##")) { -+ name = name.substring(3); -+ } -+ handlers.put(id.id, toArray( -+ group.id, -+ name -+ )); -+ } -+ } -+ } -+ -+ groupData = toObjectMapper( -+ TimingIdentifier.GROUP_MAP.values(), group -> pair(group.id, group.name)); -+ } -+ -+ parent.put("idmap", createObject( -+ pair("groups", groupData), -+ pair("handlers", handlers), -+ pair("worlds", toObjectMapper(TimingHistory.worldMap.entrySet(), input -> pair(input.getValue(), input.getKey()))), -+ pair("tileentity", -+ toObjectMapper(tileEntityTypeSet, input -> pair(input.ordinal(), input.name()))), -+ pair("entity", -+ toObjectMapper(entityTypeSet, input -> pair(input.ordinal(), input.name()))) -+ )); -+ -+ // Information about loaded plugins -+ -+ parent.put("plugins", toObjectMapper(Bukkit.getPluginManager().getPlugins(), -+ plugin -> pair(plugin.getName(), createObject( -+ pair("version", plugin.getDescription().getVersion()), -+ pair("description", String.valueOf(plugin.getDescription().getDescription()).trim()), -+ pair("website", plugin.getDescription().getWebsite()), -+ pair("authors", StringUtils.join(plugin.getDescription().getAuthors(), ", ")) -+ )))); -+ -+ -+ -+ // Information on the users Config -+ -+ parent.put("config", createObject( -+ pair("spigot", mapAsJSON(Bukkit.spigot().getSpigotConfig(), null)), -+ pair("bukkit", mapAsJSON(Bukkit.spigot().getBukkitConfig(), null)), -+ pair("paper", mapAsJSON(Bukkit.spigot().getPaperConfig(), null)) -+ )); -+ -+ new TimingsExport(listeners, parent, history).start(); -+ } -+ -+ static long getCost() { -+ // Benchmark the users System.nanotime() for cost basis -+ int passes = 100; -+ TimingHandler SAMPLER1 = Timings.ofSafe("Timings Sampler 1"); -+ TimingHandler SAMPLER2 = Timings.ofSafe("Timings Sampler 2"); -+ TimingHandler SAMPLER3 = Timings.ofSafe("Timings Sampler 3"); -+ TimingHandler SAMPLER4 = Timings.ofSafe("Timings Sampler 4"); -+ TimingHandler SAMPLER5 = Timings.ofSafe("Timings Sampler 5"); -+ TimingHandler SAMPLER6 = Timings.ofSafe("Timings Sampler 6"); -+ -+ long start = System.nanoTime(); -+ for (int i = 0; i < passes; i++) { -+ SAMPLER1.startTiming(); -+ SAMPLER2.startTiming(); -+ SAMPLER3.startTiming(); -+ SAMPLER3.stopTiming(); -+ SAMPLER4.startTiming(); -+ SAMPLER5.startTiming(); -+ SAMPLER6.startTiming(); -+ SAMPLER6.stopTiming(); -+ SAMPLER5.stopTiming(); -+ SAMPLER4.stopTiming(); -+ SAMPLER2.stopTiming(); -+ SAMPLER1.stopTiming(); -+ } -+ long timingsCost = (System.nanoTime() - start) / passes / 6; -+ SAMPLER1.reset(true); -+ SAMPLER2.reset(true); -+ SAMPLER3.reset(true); -+ SAMPLER4.reset(true); -+ SAMPLER5.reset(true); -+ SAMPLER6.reset(true); -+ return timingsCost; -+ } -+ -+ private static JSONObject mapAsJSON(ConfigurationSection config, String parentKey) { -+ -+ JSONObject object = new JSONObject(); -+ for (String key : config.getKeys(false)) { -+ String fullKey = (parentKey != null ? parentKey + "." + key : key); -+ if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) { -+ continue; -+ } -+ final Object val = config.get(key); -+ -+ object.put(key, valAsJSON(val, fullKey)); -+ } -+ return object; -+ } -+ -+ private static Object valAsJSON(Object val, final String parentKey) { -+ if (!(val instanceof MemorySection)) { -+ if (val instanceof List) { -+ Iterable v = (Iterable) val; -+ return toArrayMapper(v, input -> valAsJSON(input, parentKey)); -+ } else { -+ return String.valueOf(val); -+ } -+ } else { -+ return mapAsJSON((ConfigurationSection) val, parentKey); -+ } -+ } -+ -+ @Override -+ public void run() { -+ out.put("data", toArrayMapper(history, TimingHistory::export)); -+ -+ -+ String response = null; -+ String timingsURL = null; -+ try { -+ HttpURLConnection con = (HttpURLConnection) new URL(TimingsManager.url + "post").openConnection(); -+ con.setDoOutput(true); -+ String hostName = "BrokenHost"; -+ try { -+ hostName = InetAddress.getLocalHost().getHostName(); -+ } catch (Exception ignored) {} -+ con.setRequestProperty("User-Agent", "Paper/" + Bukkit.getUnsafe().getTimingsServerName() + "/" + hostName); -+ con.setRequestMethod("POST"); -+ con.setInstanceFollowRedirects(false); -+ -+ OutputStream request = new GZIPOutputStream(con.getOutputStream()) {{ -+ this.def.setLevel(7); -+ }}; -+ -+ request.write(JSONValue.toJSONString(out).getBytes("UTF-8")); -+ request.close(); -+ -+ response = getResponse(con); -+ -+ if (con.getResponseCode() != 302) { -+ listeners.sendMessage(text( "Upload Error: " + con.getResponseCode() + ": " + con.getResponseMessage(), NamedTextColor.RED)); -+ listeners.sendMessage(text("Check your logs for more information", NamedTextColor.RED)); -+ if (response != null) { -+ Bukkit.getLogger().log(Level.SEVERE, response); -+ } -+ return; -+ } -+ -+ timingsURL = con.getHeaderField("Location"); -+ listeners.sendMessage(text("View Timings Report: ", NamedTextColor.GREEN).append(text(timingsURL).clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, timingsURL)))); -+ -+ if (response != null && !response.isEmpty()) { -+ Bukkit.getLogger().log(Level.INFO, "Timing Response: " + response); -+ } -+ } catch (IOException ex) { -+ listeners.sendMessage(text("Error uploading timings, check your logs for more information", NamedTextColor.RED)); -+ if (response != null) { -+ Bukkit.getLogger().log(Level.SEVERE, response); -+ } -+ Bukkit.getLogger().log(Level.SEVERE, "Could not paste timings", ex); -+ } finally { -+ this.listeners.done(timingsURL); -+ } -+ } -+ -+ private String getResponse(HttpURLConnection con) throws IOException { -+ InputStream is = null; -+ try { -+ is = con.getInputStream(); -+ ByteArrayOutputStream bos = new ByteArrayOutputStream(); -+ -+ byte[] b = new byte[1024]; -+ int bytesRead; -+ while ((bytesRead = is.read(b)) != -1) { -+ bos.write(b, 0, bytesRead); -+ } -+ return bos.toString(); -+ -+ } catch (IOException ex) { -+ listeners.sendMessage(text("Error uploading timings, check your logs for more information", NamedTextColor.RED)); -+ Bukkit.getLogger().log(Level.WARNING, con.getResponseMessage(), ex); -+ return null; -+ } finally { -+ if (is != null) { -+ is.close(); -+ } -+ } -+ } -+} -diff --git a/src/main/java/co/aikar/timings/WorldTimingsHandler.java b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- /dev/null -+++ b/src/main/java/co/aikar/timings/WorldTimingsHandler.java -@@ -0,0 +0,0 @@ -+package co.aikar.timings; -+ -+import net.minecraft.server.level.ServerLevel; -+import net.minecraft.world.level.Level; -+import net.minecraft.world.level.storage.PrimaryLevelData; -+ -+/** -+ * Set of timers per world, to track world specific timings. -+ */ -+// TODO: Re-implement missing timers -+@Deprecated(forRemoval = true) -+public class WorldTimingsHandler { -+ public final Timing mobSpawn; -+ public final Timing doChunkUnload; -+ public final Timing doPortalForcer; -+ public final Timing scheduledBlocks; -+ public final Timing scheduledBlocksCleanup; -+ public final Timing scheduledBlocksTicking; -+ public final Timing chunkTicks; -+ public final Timing lightChunk; -+ public final Timing chunkTicksBlocks; -+ public final Timing doVillages; -+ public final Timing doChunkMap; -+ public final Timing doChunkMapUpdate; -+ public final Timing doChunkMapToUpdate; -+ public final Timing doChunkMapSortMissing; -+ public final Timing doChunkMapSortSendToPlayers; -+ public final Timing doChunkMapPlayersNeedingChunks; -+ public final Timing doChunkMapPendingSendToPlayers; -+ public final Timing doChunkMapUnloadChunks; -+ public final Timing doChunkGC; -+ public final Timing doSounds; -+ public final Timing entityRemoval; -+ public final Timing entityTick; -+ public final Timing tileEntityTick; -+ public final Timing tileEntityPending; -+ public final Timing tracker1; -+ public final Timing tracker2; -+ public final Timing doTick; -+ public final Timing tickEntities; -+ public final Timing chunks; -+ public final Timing newEntities; -+ public final Timing raids; -+ public final Timing chunkProviderTick; -+ public final Timing broadcastChunkUpdates; -+ public final Timing countNaturalMobs; -+ -+ public final Timing chunkLoad; -+ public final Timing chunkLoadPopulate; -+ public final Timing syncChunkLoad; -+ public final Timing chunkLoadLevelTimer; -+ public final Timing chunkIO; -+ public final Timing chunkPostLoad; -+ public final Timing worldSave; -+ public final Timing worldSaveChunks; -+ public final Timing worldSaveLevel; -+ public final Timing chunkSaveData; -+ -+ -+ public final Timing miscMobSpawning; -+ -+ public WorldTimingsHandler(Level server) { -+ String name = ((PrimaryLevelData) server.getLevelData()).getLevelName() + " - "; -+ -+ mobSpawn = Timings.ofSafe(name + "mobSpawn"); -+ doChunkUnload = Timings.ofSafe(name + "doChunkUnload"); -+ scheduledBlocks = Timings.ofSafe(name + "Scheduled Blocks"); -+ scheduledBlocksCleanup = Timings.ofSafe(name + "Scheduled Blocks - Cleanup"); -+ scheduledBlocksTicking = Timings.ofSafe(name + "Scheduled Blocks - Ticking"); -+ chunkTicks = Timings.ofSafe(name + "Chunk Ticks"); -+ lightChunk = Timings.ofSafe(name + "Light Chunk"); -+ chunkTicksBlocks = Timings.ofSafe(name + "Chunk Ticks - Blocks"); -+ doVillages = Timings.ofSafe(name + "doVillages"); -+ doChunkMap = Timings.ofSafe(name + "doChunkMap"); -+ doChunkMapUpdate = Timings.ofSafe(name + "doChunkMap - Update"); -+ doChunkMapToUpdate = Timings.ofSafe(name + "doChunkMap - To Update"); -+ doChunkMapSortMissing = Timings.ofSafe(name + "doChunkMap - Sort Missing"); -+ doChunkMapSortSendToPlayers = Timings.ofSafe(name + "doChunkMap - Sort Send To Players"); -+ doChunkMapPlayersNeedingChunks = Timings.ofSafe(name + "doChunkMap - Players Needing Chunks"); -+ doChunkMapPendingSendToPlayers = Timings.ofSafe(name + "doChunkMap - Pending Send To Players"); -+ doChunkMapUnloadChunks = Timings.ofSafe(name + "doChunkMap - Unload Chunks"); -+ doSounds = Timings.ofSafe(name + "doSounds"); -+ doChunkGC = Timings.ofSafe(name + "doChunkGC"); -+ doPortalForcer = Timings.ofSafe(name + "doPortalForcer"); -+ entityTick = Timings.ofSafe(name + "entityTick"); -+ entityRemoval = Timings.ofSafe(name + "entityRemoval"); -+ tileEntityTick = Timings.ofSafe(name + "tileEntityTick"); -+ tileEntityPending = Timings.ofSafe(name + "tileEntityPending"); -+ -+ chunkLoad = Timings.ofSafe(name + "Chunk Load"); -+ chunkLoadPopulate = Timings.ofSafe(name + "Chunk Load - Populate"); -+ syncChunkLoad = Timings.ofSafe(name + "Sync Chunk Load"); -+ chunkLoadLevelTimer = Timings.ofSafe(name + "Chunk Load - Load Level"); -+ chunkIO = Timings.ofSafe(name + "Chunk Load - DiskIO"); -+ chunkPostLoad = Timings.ofSafe(name + "Chunk Load - Post Load"); -+ worldSave = Timings.ofSafe(name + "World Save"); -+ worldSaveLevel = Timings.ofSafe(name + "World Save - Level"); -+ worldSaveChunks = Timings.ofSafe(name + "World Save - Chunks"); -+ chunkSaveData = Timings.ofSafe(name + "Chunk Save - Data"); -+ -+ tracker1 = Timings.ofSafe(name + "tracker stage 1"); -+ tracker2 = Timings.ofSafe(name + "tracker stage 2"); -+ doTick = Timings.ofSafe(name + "doTick"); -+ tickEntities = Timings.ofSafe(name + "tickEntities"); -+ -+ chunks = Timings.ofSafe(name + "Chunks"); -+ newEntities = Timings.ofSafe(name + "New entity registration"); -+ raids = Timings.ofSafe(name + "Raids"); -+ chunkProviderTick = Timings.ofSafe(name + "Chunk provider tick"); -+ broadcastChunkUpdates = Timings.ofSafe(name + "Broadcast chunk updates"); -+ countNaturalMobs = Timings.ofSafe(name + "Count natural mobs"); -+ -+ -+ miscMobSpawning = Timings.ofSafe(name + "Mob spawning - Misc"); -+ } -+ -+ public static Timing getTickList(ServerLevel worldserver, String timingsType) { -+ return Timings.ofSafe(((PrimaryLevelData) worldserver.getLevelData()).getLevelName() + " - Scheduled " + timingsType); -+ } -+} -diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -@@ -0,0 +0,0 @@ public class PacketUtils { - engine.executeIfPossible(() -> { - if (listener instanceof ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // CraftBukkit - Don't handle sync packets for kicked players - if (listener.shouldHandleMessage(packet)) { -- try { -+ co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings -+ try (co.aikar.timings.Timing ignored = timing.startTiming()) { // Paper - timings - packet.handle(listener); - } catch (Exception exception) { - if (exception instanceof ReportedException) { -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ import org.bukkit.craftbukkit.Main; - import org.bukkit.event.server.ServerLoadEvent; - // CraftBukkit end - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, ChunkIOErrorReporter, CommandSource { - -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -- return !this.haveTime(); -+ return !this.canSleepForTickNoOversleep(); // Paper - move oversleep into full server tick - }); - } finally { - this.waitingForNextTick = false; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { -+ return !this.canOversleep(); -+ }); -+ isOversleep = false;MinecraftTimings.serverOversleep.stopTiming(); -+ // Paper end -+ - ++this.tickCount; - this.tickRateManager.tick(); - this.tickChildren(shouldKeepTicking); -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop { - entityplayer.connection.suspendFlushing(); - }); -- SpigotTimings.schedulerTimer.startTiming(); // Spigot -+ MinecraftTimings.bukkitSchedulerTimer.startTiming(); // Spigot // Paper - this.server.getScheduler().mainThreadHeartbeat(); // CraftBukkit -- SpigotTimings.schedulerTimer.stopTiming(); // Spigot -+ MinecraftTimings.bukkitSchedulerTimer.stopTiming(); // Spigot // Paper - io.papermc.paper.adventure.providers.ClickCallbackProviderImpl.CALLBACK_MANAGER.handleQueue(this.tickCount); // Paper - gameprofilerfiller.push("commandFunctions"); -- SpigotTimings.commandFunctionsTimer.startTiming(); // Spigot -+ MinecraftTimings.commandFunctionsTimer.startTiming(); // Spigot // Paper - this.getFunctions().tick(); -- SpigotTimings.commandFunctionsTimer.stopTiming(); // Spigot -+ MinecraftTimings.commandFunctionsTimer.stopTiming(); // Spigot // Paper - gameprofilerfiller.popPush("levels"); - Iterator iterator = this.getAllLevels().iterator(); - - // CraftBukkit start - // Run tasks that are waiting on processing -- SpigotTimings.processQueueTimer.startTiming(); // Spigot -+ MinecraftTimings.processQueueTimer.startTiming(); // Spigot - while (!this.processQueue.isEmpty()) { - this.processQueue.remove().run(); - } -- SpigotTimings.processQueueTimer.stopTiming(); // Spigot -+ MinecraftTimings.processQueueTimer.stopTiming(); // Spigot - -- SpigotTimings.timeUpdateTimer.startTiming(); // Spigot -+ MinecraftTimings.timeUpdateTimer.startTiming(); // Spigot // Paper - // Send time updates to everyone, it will get the right time from the world the player is in. - if (this.tickCount % 20 == 0) { - for (int i = 0; i < this.getPlayerList().players.size(); ++i) { -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop command = new java.util.concurrent.atomic.AtomicReference<>(s); // Paper - this.executeBlocking(() -> { - CommandSourceStack wrapper = rconConsoleSource.createCommandSourceStack(); - RemoteServerCommandEvent event = new RemoteServerCommandEvent(rconConsoleSource.getBukkitSender(wrapper), s); -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - if (event.isCancelled()) { - return; - } -+ // Paper start -+ command.set(event.getCommand()); -+ if (event.getCommand().toLowerCase(java.util.Locale.ROOT).startsWith("timings") && event.getCommand().toLowerCase(java.util.Locale.ROOT).matches("timings (report|paste|get|merged|seperate)")) { -+ org.bukkit.command.BufferedCommandSender sender = new org.bukkit.command.BufferedCommandSender(); -+ Waitable waitable = new Waitable<>() { -+ @Override -+ protected String evaluate() { -+ return sender.getBuffer(); -+ } -+ }; -+ waitableArray[0] = waitable; -+ co.aikar.timings.Timings.generateReport(new co.aikar.timings.TimingsReportListener(sender, waitable)); -+ } else { -+ // Paper end - ConsoleInput serverCommand = new ConsoleInput(event.getCommand(), wrapper); - this.server.dispatchServerCommand(event.getSender(), serverCommand); -+ } // Paper - }); -+ // Paper start -+ if (waitableArray[0] != null) { -+ //noinspection unchecked -+ Waitable waitable = waitableArray[0]; -+ try { -+ return waitable.get(); -+ } catch (java.util.concurrent.ExecutionException e) { -+ throw new RuntimeException("Exception processing rcon command " + command.get(), e.getCause()); -+ } catch (InterruptedException e) { -+ Thread.currentThread().interrupt(); // Maintain interrupted state -+ throw new RuntimeException("Interrupted processing rcon command " + command.get(), e); -+ } -+ -+ } -+ // Paper end - return rconConsoleSource.getCommandResponse(); - // CraftBukkit end - } -diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ChunkMap.java -+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.level; - -+import co.aikar.timings.Timing; // Paper - import com.google.common.collect.ImmutableList; - import com.google.common.collect.ImmutableList.Builder; - import com.google.common.collect.Iterables; -+import com.google.common.collect.ComparisonChain; // Paper - import com.google.common.collect.Lists; - import com.google.common.collect.Queues; - import com.google.common.collect.Sets; -@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - List list = Lists.newArrayList(); - List list1 = this.level.players(); - ObjectIterator objectiterator = this.entityMap.values().iterator(); -+ level.timings.tracker1.startTiming(); // Paper - - ChunkMap.TrackedEntity playerchunkmap_entitytracker; - -@@ -0,0 +0,0 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider - playerchunkmap_entitytracker.serverEntity.sendChanges(); - } - } -+ level.timings.tracker1.stopTiming(); // Paper - - if (!list.isEmpty()) { - objectiterator = this.entityMap.values().iterator(); - -+ level.timings.tracker2.startTiming(); // Paper - while (objectiterator.hasNext()) { - playerchunkmap_entitytracker = (ChunkMap.TrackedEntity) objectiterator.next(); - playerchunkmap_entitytracker.updatePlayers(list); - } -+ level.timings.tracker2.stopTiming(); // Paper - } - - } -diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java -+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java -@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { - } - - gameprofilerfiller.incrementCounter("getChunkCacheMiss"); -- this.level.timings.syncChunkLoadTimer.startTiming(); // Spigot - CompletableFuture> completablefuture = this.getChunkFutureMainThread(x, z, leastStatus, create); - ServerChunkCache.MainThreadExecutor chunkproviderserver_b = this.mainThreadProcessor; - - Objects.requireNonNull(completablefuture); -+ if (!completablefuture.isDone()) { // Paper -+ this.level.timings.syncChunkLoad.startTiming(); // Paper - chunkproviderserver_b.managedBlock(completablefuture::isDone); -- this.level.timings.syncChunkLoadTimer.stopTiming(); // Spigot -+ this.level.timings.syncChunkLoad.stopTiming(); // Paper -+ } // Paper - ChunkResult chunkresult = (ChunkResult) completablefuture.join(); - ChunkAccess ichunkaccess1 = (ChunkAccess) chunkresult.orElse(null); // CraftBukkit - decompile error - -@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { - - public void save(boolean flush) { - this.runDistanceManagerUpdates(); -+ try (co.aikar.timings.Timing timed = level.timings.chunkSaveData.startTiming()) { // Paper - Timings - this.chunkMap.saveAllChunks(flush); -+ } // Paper - Timings - } - - @Override -@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { - this.level.timings.doChunkMap.stopTiming(); // Spigot - gameprofilerfiller.popPush("chunks"); - if (tickChunks) { -+ this.level.timings.chunks.startTiming(); // Paper - timings - this.tickChunks(); -- this.level.timings.tracker.startTiming(); // Spigot -+ this.level.timings.chunks.stopTiming(); // Paper - timings - this.chunkMap.tick(); -- this.level.timings.tracker.stopTiming(); // Spigot - } - - this.level.timings.doChunkUnload.startTiming(); // Spigot -@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { - LevelChunk chunk = playerchunk.getTickingChunk(); - - if (chunk != null) { -+ this.level.timings.broadcastChunkUpdates.startTiming(); // Paper - timing - playerchunk.broadcastChanges(chunk); -+ this.level.timings.broadcastChunkUpdates.stopTiming(); // Paper - timing - } - } - -@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { - - private void tickChunks(ProfilerFiller profiler, long timeDelta, List chunks) { - profiler.popPush("naturalSpawnCount"); -+ this.level.timings.countNaturalMobs.startTiming(); // Paper - timings - int j = this.distanceManager.getNaturalSpawnChunkCount(); - NaturalSpawner.SpawnState spawnercreature_d = NaturalSpawner.createState(j, this.level.getAllEntities(), this::getFullChunk, new LocalMobCapCalculator(this.chunkMap)); -+ this.level.timings.countNaturalMobs.stopTiming(); // Paper - timings - - this.lastSpawnState = spawnercreature_d; - profiler.popPush("spawnAndTick"); -@@ -0,0 +0,0 @@ public class ServerChunkCache extends ChunkSource { - } - - if (this.level.shouldTickBlocksAt(chunkcoordintpair.toLong())) { -- this.level.timings.doTickTiles.startTiming(); // Spigot - this.level.tickChunk(chunk, k); -- this.level.timings.doTickTiles.stopTiming(); // Spigot - } - } - -+ this.level.timings.chunkTicks.stopTiming(); // Paper -+ - profiler.popPush("customSpawners"); - if (flag) { -+ try (co.aikar.timings.Timing ignored = this.level.timings.miscMobSpawning.startTiming()) { // Paper - timings - this.level.tickCustomSpawners(this.spawnEnemies, this.spawnFriendlies); -+ } - } - - } -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.level; - - import com.google.common.annotations.VisibleForTesting; -+import co.aikar.timings.TimingHistory; // Paper -+import co.aikar.timings.Timings; // Paper - import com.google.common.collect.Lists; - import com.mojang.datafixers.DataFixer; - import com.mojang.datafixers.util.Pair; -@@ -0,0 +0,0 @@ import net.minecraft.world.ticks.LevelTicks; - import org.slf4j.Logger; - import org.bukkit.Bukkit; - import org.bukkit.WeatherType; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.event.CraftEventFactory; - import org.bukkit.craftbukkit.generator.CustomWorldChunkManager; - import org.bukkit.craftbukkit.util.WorldUUID; -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - } - - gameprofilerfiller.push("tickPending"); -- this.timings.doTickPending.startTiming(); // Spigot -+ this.timings.scheduledBlocks.startTiming(); // Paper - if (!this.isDebug() && flag) { - j = this.getGameTime(); - gameprofilerfiller.push("blockTicks"); -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - this.fluidTicks.tick(j, 65536, this::tickFluid); - gameprofilerfiller.pop(); - } -- this.timings.doTickPending.stopTiming(); // Spigot -+ this.timings.scheduledBlocks.stopTiming(); // Paper - - gameprofilerfiller.popPush("raid"); - if (flag) { -+ this.timings.raids.startTiming(); // Paper - timings - this.raids.tick(); -+ this.timings.raids.stopTiming(); // Paper - timings - } - - gameprofilerfiller.popPush("chunkSource"); -+ this.timings.chunkProviderTick.startTiming(); // Paper - timings - this.getChunkSource().tick(shouldKeepTicking, true); -+ this.timings.chunkProviderTick.stopTiming(); // Paper - timings - gameprofilerfiller.popPush("blockEvents"); - if (flag) { - this.timings.doSounds.startTiming(); // Spigot -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - } - - gameprofilerfiller.popPush("tickBlocks"); -+ timings.chunkTicksBlocks.startTiming(); // Paper - if (randomTickSpeed > 0) { - LevelChunkSection[] achunksection = chunk.getSections(); - -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - } - } - -+ timings.chunkTicksBlocks.stopTiming(); // Paper - gameprofilerfiller.pop(); - } - -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - } - - public void tickNonPassenger(Entity entity) { -+ ++TimingHistory.entityTicks; // Paper - timings - // Spigot start -+ co.aikar.timings.Timing timer; // Paper - if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { - entity.tickCount++; -+ timer = entity.getType().inactiveTickTimer.startTiming(); try { // Paper - timings - entity.inactiveTick(); -+ } finally { timer.stopTiming(); } // Paper - return; - } - // Spigot end -- entity.tickTimer.startTiming(); // Spigot -+ // Paper start- timings -+ TimingHistory.activatedEntityTicks++; -+ timer = entity.getVehicle() != null ? entity.getType().passengerTickTimer.startTiming() : entity.getType().tickTimer.startTiming(); -+ try { -+ // Paper end - timings - entity.setOldPosAndRot(); - ProfilerFiller gameprofilerfiller = Profiler.get(); - -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - - this.tickPassenger(entity, entity1); - } -- entity.tickTimer.stopTiming(); // Spigot -+ } finally { timer.stopTiming(); } // Paper - timings - - } - -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - - if (!savingDisabled) { - org.bukkit.Bukkit.getPluginManager().callEvent(new org.bukkit.event.world.WorldSaveEvent(this.getWorld())); // CraftBukkit -+ try (co.aikar.timings.Timing ignored = timings.worldSave.startTiming()) { // Paper - if (progressListener != null) { - progressListener.progressStartNoAbort(Component.translatable("menu.savingLevel")); - } -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - progressListener.progressStage(Component.translatable("menu.savingChunks")); - } - -+ timings.worldSaveChunks.startTiming(); // Paper - chunkproviderserver.save(flush); -+ timings.worldSaveChunks.stopTiming(); // Paper -+ }// Paper - if (flush) { - this.entityManager.saveAll(); - } else { -diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - - @Override - public void tick() { -- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.startTiming(); // Spigot - if (this.ackBlockChangesUpTo > -1) { - this.send(new ClientboundBlockChangedAckPacket(this.ackBlockChangesUpTo)); - this.ackBlockChangesUpTo = -1; -@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - this.player.resetLastActionTime(); // CraftBukkit - SPIGOT-854 - this.disconnect((Component) Component.translatable("multiplayer.disconnect.idling")); - } -- org.bukkit.craftbukkit.SpigotTimings.playerConnectionTimer.stopTiming(); // Spigot - - } - -@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - } - - private void handleCommand(String s) { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot -+ co.aikar.timings.MinecraftTimings.playerCommandTimer.startTiming(); // Paper - if ( org.spigotmc.SpigotConfig.logCommands ) // Spigot - this.LOGGER.info(this.player.getScoreboardName() + " issued server command: " + s); - -@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - this.cserver.getPluginManager().callEvent(event); - - if (event.isCancelled()) { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot -+ co.aikar.timings.MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - return; - } - -@@ -0,0 +0,0 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl - java.util.logging.Logger.getLogger(ServerGamePacketListenerImpl.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); - return; - } finally { -- org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot -+ co.aikar.timings.MinecraftTimings.playerCommandTimer.stopTiming(); // Paper - } - } - // CraftBukkit end -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ - package net.minecraft.server.players; - -+import co.aikar.timings.MinecraftTimings; - import com.google.common.collect.Lists; - import com.google.common.collect.Maps; - import com.google.common.collect.Sets; -@@ -0,0 +0,0 @@ public abstract class PlayerList { - } - - public void saveAll() { -+ MinecraftTimings.savePlayers.startTiming(); // Paper - for (int i = 0; i < this.players.size(); ++i) { - this.save((ServerPlayer) this.players.get(i)); - } -- -+ MinecraftTimings.savePlayers.stopTiming(); // Paper - } - - public UserWhiteList getWhiteList() { -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ import org.bukkit.command.CommandSender; - import org.bukkit.entity.Hanging; - import org.bukkit.entity.LivingEntity; - import org.bukkit.entity.Vehicle; --import org.spigotmc.CustomTimingsHandler; // Spigot - import org.bukkit.event.entity.EntityCombustByEntityEvent; - import org.bukkit.event.hanging.HangingBreakByEntityEvent; - import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; -@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - // Marks an entity, that it was removed by a plugin via Entity#remove - // Main use case currently is for SPIGOT-7487, preventing dropping of leash when leash is removed - public boolean pluginRemoved = false; -- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot - // Spigot start - public final org.spigotmc.ActivationRange.ActivationType activationType = org.spigotmc.ActivationRange.initializeEntityActivationType(this); - public final boolean defaultActivationState; -@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - } - - public void move(MoverType type, Vec3 movement) { -- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot - if (this.noPhysics) { - this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z); - } else { -@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - gameprofilerfiller.pop(); - } - } -- org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot - } - - private void applyMovementEmissionAndPlaySound(Entity.MovementEmission moveEffect, Vec3 movement, BlockPos landingPos, BlockState landingState) { -diff --git a/src/main/java/net/minecraft/world/entity/EntityType.java b/src/main/java/net/minecraft/world/entity/EntityType.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/EntityType.java -+++ b/src/main/java/net/minecraft/world/entity/EntityType.java -@@ -0,0 +0,0 @@ public class EntityType implements FeatureElement, EntityTypeT - } - - public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet canSpawnInside, EntityDimensions dimensions, float spawnBoxScale, int maxTrackDistance, int trackTickInterval, String translationKey, Optional> lootTable, FeatureFlagSet requiredFeatures) { -+ // Paper start -+ this(factory, spawnGroup, saveable, summonable, fireImmune, spawnableFarFromPlayer, canSpawnInside, dimensions, spawnBoxScale, maxTrackDistance, trackTickInterval, translationKey, lootTable, requiredFeatures, "custom"); -+ } -+ public EntityType(EntityType.EntityFactory factory, MobCategory spawnGroup, boolean saveable, boolean summonable, boolean fireImmune, boolean spawnableFarFromPlayer, ImmutableSet canSpawnInside, EntityDimensions dimensions, float spawnBoxScale, int maxTrackDistance, int trackTickInterval, String translationKey, Optional> lootTable, FeatureFlagSet requiredFeatures, String id) { -+ this.tickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "tick"); -+ this.inactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "inactiveTick"); -+ this.passengerTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerTick"); -+ this.passengerInactiveTickTimer = co.aikar.timings.MinecraftTimings.getEntityTimings(id, "passengerInactiveTick"); -+ // Paper end - this.builtInRegistryHolder = BuiltInRegistries.ENTITY_TYPE.createIntrusiveHolder(this); - this.factory = factory; - this.category = spawnGroup; -@@ -0,0 +0,0 @@ public class EntityType implements FeatureElement, EntityTypeT - return this.updateInterval; - } - -+ // Paper start - timings -+ public final co.aikar.timings.Timing tickTimer; -+ public final co.aikar.timings.Timing inactiveTickTimer; -+ public final co.aikar.timings.Timing passengerTickTimer; -+ public final co.aikar.timings.Timing passengerInactiveTickTimer; -+ // Paper end - public boolean trackDeltas() { - return this != EntityType.PLAYER && this != EntityType.LLAMA_SPIT && this != EntityType.WITHER && this != EntityType.BAT && this != EntityType.ITEM_FRAME && this != EntityType.GLOW_ITEM_FRAME && this != EntityType.LEASH_KNOT && this != EntityType.PAINTING && this != EntityType.END_CRYSTAL && this != EntityType.EVOKER_FANGS; - } -diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/LivingEntity.java -+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java -@@ -0,0 +0,0 @@ import org.bukkit.event.entity.EntityTeleportEvent; - import org.bukkit.event.player.PlayerItemConsumeEvent; - // CraftBukkit end - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper - - public abstract class LivingEntity extends Entity implements Attackable { - -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - - @Override - public void tick() { -- SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot - super.tick(); - this.updatingUsingItem(); - this.updateSwimAmount(); -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - } - - if (!this.isRemoved()) { -- SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot - this.aiStep(); -- SpigotTimings.timerEntityTickRest.startTiming(); // Spigot - } - - double d0 = this.getX() - this.xo; -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - } - - this.elytraAnimationState.tick(); -- SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot - } - - public void detectEquipmentUpdatesPublic() { // CraftBukkit -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - ProfilerFiller gameprofilerfiller = Profiler.get(); - - gameprofilerfiller.push("ai"); -- SpigotTimings.timerEntityAI.startTiming(); // Spigot - if (this.isImmobile()) { - this.jumping = false; - this.xxa = 0.0F; -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.serverAiStep(); - gameprofilerfiller.pop(); - } -- SpigotTimings.timerEntityAI.stopTiming(); // Spigot - - gameprofilerfiller.pop(); - gameprofilerfiller.push("jump"); -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.resetFallDistance(); - } - -- SpigotTimings.timerEntityAIMove.startTiming(); // Spigot - label112: - { - LivingEntity entityliving = this.getControllingPassenger(); -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - - this.travel(vec3d1); - } -- SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot - - if (!this.level().isClientSide() || this.isControlledByLocalInstance()) { - this.applyEffectsFromBlocks(); -@@ -0,0 +0,0 @@ public abstract class LivingEntity extends Entity implements Attackable { - this.checkAutoSpinAttack(axisalignedbb, this.getBoundingBox()); - } - -- SpigotTimings.timerEntityAICollision.startTiming(); // Spigot - this.pushEntities(); -- SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot - gameprofilerfiller.pop(); - world = this.level(); - if (world instanceof ServerLevel worldserver) { -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -0,0 +0,0 @@ import net.minecraft.network.protocol.game.ClientboundSetBorderWarningDistancePa - import org.bukkit.Bukkit; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.bukkit.craftbukkit.block.CapturedBlockState; - import org.bukkit.craftbukkit.block.CraftBlockState; - import org.bukkit.craftbukkit.block.data.CraftBlockData; -@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - } - // Paper end - add paper world config - -- public final SpigotTimings.WorldTimingsHandler timings; // Spigot -+ public final co.aikar.timings.WorldTimingsHandler timings; // Paper - public static BlockPos lastPhysicsProblem; // Spigot - private org.spigotmc.TickLimiter entityLimiter; - private org.spigotmc.TickLimiter tileLimiter; -@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - public void onBorderSetDamageSafeZOne(WorldBorder border, double safeZoneRadius) {} - }); - // CraftBukkit end -- this.timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings -+ this.timings = new co.aikar.timings.WorldTimingsHandler(this); // Paper - code below can generate new world and access timings - this.entityLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.entityMaxTickTime); - this.tileLimiter = new org.spigotmc.TickLimiter(this.spigotConfig.tileMaxTickTime); - } -@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable { - - this.timings.tileEntityTick.stopTiming(); // Spigot - this.tickingBlockEntities = false; -+ co.aikar.timings.TimingHistory.tileEntityTicks += this.blockEntityTickers.size(); // Paper - gameprofilerfiller.pop(); - this.spigotConfig.currentPrimedTnt = 0; // Spigot - } - - public void guardEntityTick(Consumer tickConsumer, T entity) { - try { -- SpigotTimings.tickEntityTimer.startTiming(); // Spigot - tickConsumer.accept(entity); -- SpigotTimings.tickEntityTimer.stopTiming(); // Spigot - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); - CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); -diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/Block.java -+++ b/src/main/java/net/minecraft/world/level/block/Block.java -@@ -0,0 +0,0 @@ public class Block extends BlockBehaviour implements ItemLike { - public static final int UPDATE_LIMIT = 512; - protected final StateDefinition stateDefinition; - private BlockState defaultBlockState; -+ // Paper start -+ public co.aikar.timings.Timing timing; -+ public co.aikar.timings.Timing getTiming() { -+ if (timing == null) { -+ timing = co.aikar.timings.MinecraftTimings.getBlockTiming(this); -+ } -+ return timing; -+ } -+ // Paper end - @Nullable - private Item item; - private static final int CACHE_SIZE = 256; -diff --git a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -+++ b/src/main/java/net/minecraft/world/level/block/entity/BlockEntity.java -@@ -0,0 +0,0 @@ import org.bukkit.inventory.InventoryHolder; - // CraftBukkit end - - import org.spigotmc.CustomTimingsHandler; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - public abstract class BlockEntity { - -- public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot -+ public Timing tickTimer = MinecraftTimings.getTileEntityTimings(this); // Paper - // CraftBukkit start - data containers - private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); - public CraftPersistentDataContainer persistentDataContainer; -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess { - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(bukkitChunk, this.needsDecoration)); - - if (this.needsDecoration) { -+ try (co.aikar.timings.Timing ignored = this.level.timings.chunkLoadPopulate.startTiming()) { // Paper - this.needsDecoration = false; - java.util.Random random = new java.util.Random(); - random.setSeed(this.level.getSeed()); -@@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess { - } - } - server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(bukkitChunk)); -+ } // Paper - } - } - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SerializableChunkData.java b/src/main/java/net/minecraft/world/level/chunk/storage/SerializableChunkData.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/SerializableChunkData.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/SerializableChunkData.java -@@ -0,0 +0,0 @@ public record SerializableChunkData(Registry biomeRegistry, ChunkPos chun - @Nullable - private static LevelChunk.PostLoadProcessor postLoadChunk(ServerLevel world, List entities, List blockEntities) { - return entities.isEmpty() && blockEntities.isEmpty() ? null : (chunk) -> { -- world.timings.syncChunkLoadEntitiesTimer.startTiming(); // Spigot - if (!entities.isEmpty()) { - world.addLegacyChunkEntities(EntityType.loadEntitiesRecursive(entities, world, EntitySpawnReason.LOAD)); - } -- world.timings.syncChunkLoadEntitiesTimer.stopTiming(); // Spigot - - Iterator iterator = blockEntities.iterator(); - -- world.timings.syncChunkLoadTileEntitiesTimer.startTiming(); // Spigot - while (iterator.hasNext()) { - CompoundTag nbttagcompound = (CompoundTag) iterator.next(); - boolean flag = nbttagcompound.getBoolean("keepPacked"); -@@ -0,0 +0,0 @@ public record SerializableChunkData(Registry biomeRegistry, ChunkPos chun - } - } - } -- world.timings.syncChunkLoadTileEntitiesTimer.stopTiming(); // Spigot - - }; - } -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - this.saveCommandsConfig(); - this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); - this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); -- this.pluginManager.useTimings(this.configuration.getBoolean("settings.plugin-profiling")); -+ //this.pluginManager.useTimings(this.configuration.getBoolean("settings.plugin-profiling")); // Paper - we already moved this - this.overrideSpawnLimits(); - console.autosavePeriod = this.configuration.getInt("ticks-per.autosave"); - this.warningState = WarningState.value(this.configuration.getString("settings.deprecated-verbose")); -@@ -0,0 +0,0 @@ public final class CraftServer implements Server { - private final org.bukkit.Server.Spigot spigot = new org.bukkit.Server.Spigot() - { - -+ @Deprecated - @Override - public YamlConfiguration getConfig() - { - return org.spigotmc.SpigotConfig.config; - } - -+ @Override -+ public YamlConfiguration getBukkitConfig() -+ { -+ return configuration; -+ } -+ -+ @Override -+ public YamlConfiguration getSpigotConfig() -+ { -+ return org.spigotmc.SpigotConfig.config; -+ } -+ -+ @Override -+ public YamlConfiguration getPaperConfig() -+ { -+ return CraftServer.this.console.paperConfigurations.createLegacyObject(CraftServer.this.console); -+ } -+ - @Override - public void restart() { - org.spigotmc.RestartCommand.restart(); -diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -deleted file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 ---- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java -+++ /dev/null -@@ -0,0 +0,0 @@ --package org.bukkit.craftbukkit; -- --import java.util.HashMap; --import net.minecraft.world.entity.Entity; --import net.minecraft.world.level.Level; --import net.minecraft.world.level.block.entity.BlockEntity; --import net.minecraft.world.level.storage.PrimaryLevelData; --import org.bukkit.craftbukkit.scheduler.CraftTask; --import org.bukkit.plugin.java.JavaPluginLoader; --import org.bukkit.scheduler.BukkitTask; --import org.spigotmc.CustomTimingsHandler; -- --public class SpigotTimings { -- -- public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); -- public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); -- public static final CustomTimingsHandler commandFunctionsTimer = new CustomTimingsHandler("Command Functions"); -- public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection Handler"); -- public static final CustomTimingsHandler playerConnectionTimer = new CustomTimingsHandler("** PlayerConnection"); -- public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); -- public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); -- public static final CustomTimingsHandler timeUpdateTimer = new CustomTimingsHandler("Time Update"); -- public static final CustomTimingsHandler serverCommandTimer = new CustomTimingsHandler("Server Command"); -- public static final CustomTimingsHandler worldSaveTimer = new CustomTimingsHandler("World Save"); -- -- public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); -- public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); -- public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); -- public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); -- -- public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); -- public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); -- public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); -- public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); -- public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); -- -- public static final CustomTimingsHandler processQueueTimer = new CustomTimingsHandler("processQueue"); -- public static final CustomTimingsHandler schedulerSyncTimer = new CustomTimingsHandler("** Scheduler - Sync Tasks", JavaPluginLoader.pluginParentTimer); -- -- public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); -- -- public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); -- public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); -- -- public static final HashMap entityTypeTimingMap = new HashMap(); -- public static final HashMap tileEntityTypeTimingMap = new HashMap(); -- public static final HashMap pluginTaskTimingMap = new HashMap(); -- -- /** -- * Gets a timer associated with a plugins tasks. -- * @param task -- * @param period -- * @return -- */ -- public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { -- if (!task.isSync()) { -- return null; -- } -- String plugin; -- final CraftTask ctask = (CraftTask) task; -- -- if (task.getOwner() != null) { -- plugin = task.getOwner().getDescription().getFullName(); -- } else { -- plugin = "Unknown"; -- } -- String taskname = ctask.getTaskName(); -- -- String name = "Task: " + plugin + " Runnable: " + taskname; -- if (period > 0) { -- name += "(interval:" + period + ")"; -- } else { -- name += "(Single)"; -- } -- CustomTimingsHandler result = SpigotTimings.pluginTaskTimingMap.get(name); -- if (result == null) { -- result = new CustomTimingsHandler(name, SpigotTimings.schedulerSyncTimer); -- SpigotTimings.pluginTaskTimingMap.put(name, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getEntityTimings(Entity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = SpigotTimings.entityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickEntity - " + entity.getClass().getSimpleName(), SpigotTimings.activatedEntityTimer); -- SpigotTimings.entityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Get a named timer for the specified tile entity type to track type specific timings. -- * @param entity -- * @return -- */ -- public static CustomTimingsHandler getTileEntityTimings(BlockEntity entity) { -- String entityType = entity.getClass().getName(); -- CustomTimingsHandler result = SpigotTimings.tileEntityTypeTimingMap.get(entityType); -- if (result == null) { -- result = new CustomTimingsHandler("** tickTileEntity - " + entity.getClass().getSimpleName(), SpigotTimings.tickTileEntityTimer); -- SpigotTimings.tileEntityTypeTimingMap.put(entityType, result); -- } -- return result; -- } -- -- /** -- * Set of timers per world, to track world specific timings. -- */ -- public static class WorldTimingsHandler { -- public final CustomTimingsHandler mobSpawn; -- public final CustomTimingsHandler doChunkUnload; -- public final CustomTimingsHandler doTickPending; -- public final CustomTimingsHandler doTickTiles; -- public final CustomTimingsHandler doChunkMap; -- public final CustomTimingsHandler doSounds; -- public final CustomTimingsHandler entityTick; -- public final CustomTimingsHandler tileEntityTick; -- public final CustomTimingsHandler tileEntityPending; -- public final CustomTimingsHandler tracker; -- public final CustomTimingsHandler doTick; -- public final CustomTimingsHandler tickEntities; -- -- public final CustomTimingsHandler syncChunkLoadTimer; -- public final CustomTimingsHandler syncChunkLoadStructuresTimer; -- public final CustomTimingsHandler syncChunkLoadEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileEntitiesTimer; -- public final CustomTimingsHandler syncChunkLoadTileTicksTimer; -- public final CustomTimingsHandler syncChunkLoadPostTimer; -- -- public WorldTimingsHandler(Level server) { -- String name = ((PrimaryLevelData) server.levelData).getLevelName() + " - "; -- -- this.mobSpawn = new CustomTimingsHandler("** " + name + "mobSpawn"); -- this.doChunkUnload = new CustomTimingsHandler("** " + name + "doChunkUnload"); -- this.doTickPending = new CustomTimingsHandler("** " + name + "doTickPending"); -- this.doTickTiles = new CustomTimingsHandler("** " + name + "doTickTiles"); -- this.doChunkMap = new CustomTimingsHandler("** " + name + "doChunkMap"); -- this.doSounds = new CustomTimingsHandler("** " + name + "doSounds"); -- this.entityTick = new CustomTimingsHandler("** " + name + "entityTick"); -- this.tileEntityTick = new CustomTimingsHandler("** " + name + "tileEntityTick"); -- this.tileEntityPending = new CustomTimingsHandler("** " + name + "tileEntityPending"); -- -- this.syncChunkLoadTimer = new CustomTimingsHandler("** " + name + "syncChunkLoad"); -- this.syncChunkLoadStructuresTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Structures"); -- this.syncChunkLoadEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Entities"); -- this.syncChunkLoadTileEntitiesTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileEntities"); -- this.syncChunkLoadTileTicksTimer = new CustomTimingsHandler("** " + name + "chunkLoad - TileTicks"); -- this.syncChunkLoadPostTimer = new CustomTimingsHandler("** " + name + "chunkLoad - Post"); -- -- -- this.tracker = new CustomTimingsHandler(name + "tracker"); -- this.doTick = new CustomTimingsHandler(name + "doTick"); -- this.tickEntities = new CustomTimingsHandler(name + "tickEntities"); -- } -- } --} -diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java -@@ -0,0 +0,0 @@ public class CraftPlayer extends CraftHumanEntity implements Player { - - CraftPlayer.this.getHandle().connection.send(new net.minecraft.network.protocol.game.ClientboundSystemChatPacket(components, position == net.md_5.bungee.api.ChatMessageType.ACTION_BAR)); - } -+ -+ // Paper start -+ @Override -+ public int getPing() -+ { -+ return CraftPlayer.this.getPing(); -+ } -+ // Paper end - }; - - public Player.Spigot spigot() -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.scheduler; - -+import co.aikar.timings.MinecraftTimings; // Paper - import com.google.common.base.Preconditions; - import com.google.common.util.concurrent.ThreadFactoryBuilder; - import java.util.ArrayList; -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - } - return false; - } -- }); -+ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer();}}; // Paper - this.handle(task, 0L); - for (CraftTask taskPending = this.head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { - if (taskPending == task) { -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - } - } - } -- }); -+ }){{this.timings=co.aikar.timings.MinecraftTimings.getCancelTasksTimer(plugin);}}; // Paper - this.handle(task, 0L); - for (CraftTask taskPending = this.head.getNext(); taskPending != null; taskPending = taskPending.getNext()) { - if (taskPending == task) { -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - if (task.isSync()) { - this.currentTask = task; - try { -- task.timings.startTiming(); // Spigot - task.run(); -- task.timings.stopTiming(); // Spigot - } catch (final Throwable throwable) { - task.getOwner().getLogger().log( - Level.WARNING, -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - this.runners.remove(task.getTaskId()); - } - } -+ MinecraftTimings.bukkitSchedulerFinishTimer.startTiming(); // Paper - this.pending.addAll(temp); - temp.clear(); -+ MinecraftTimings.bukkitSchedulerFinishTimer.stopTiming(); // Paper - this.debugHead = this.debugHead.getNextHead(this.currentTick); - } - -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - } - - private void parsePending() { -+ MinecraftTimings.bukkitSchedulerPendingTimer.startTiming(); - CraftTask head = this.head; - CraftTask task = head.getNext(); - CraftTask lastTask = head; -@@ -0,0 +0,0 @@ public class CraftScheduler implements BukkitScheduler { - task.setNext(null); - } - this.head = lastTask; -+ MinecraftTimings.bukkitSchedulerPendingTimer.stopTiming(); - } - - private boolean isReady(final int currentTick) { -diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java -@@ -0,0 +0,0 @@ - package org.bukkit.craftbukkit.scheduler; - - import java.util.function.Consumer; -+ -+import co.aikar.timings.NullTimingHandler; - import org.bukkit.Bukkit; - import org.bukkit.plugin.Plugin; - import org.bukkit.scheduler.BukkitTask; - --import org.bukkit.craftbukkit.SpigotTimings; // Spigot - import org.spigotmc.CustomTimingsHandler; // Spigot -+import co.aikar.timings.MinecraftTimings; // Paper -+import co.aikar.timings.Timing; // Paper - - public class CraftTask implements BukkitTask, Runnable { // Spigot - -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - */ - private volatile long period; - private long nextRun; -- private final Runnable rTask; -- private final Consumer cTask; -+ public final Runnable rTask; // Paper -+ public final Consumer cTask; // Paper -+ public Timing timings; // Paper - private final Plugin plugin; - private final int id; - private final long createdAt = System.nanoTime(); - -- final CustomTimingsHandler timings; // Spigot - CraftTask() { - this(null, null, CraftTask.NO_REPEATING, CraftTask.NO_REPEATING); - } -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - } - this.id = id; - this.period = period; -- this.timings = this.isSync() ? SpigotTimings.getPluginTaskTimings(this, period) : null; // Spigot -+ timings = task != null ? MinecraftTimings.getPluginTaskTimings(this, period) : NullTimingHandler.NULL; // Paper - } - - @Override -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - - @Override - public void run() { -+ try (Timing ignored = timings.startTiming()) { // Paper - if (this.rTask != null) { - this.rTask.run(); - } else { - this.cTask.accept(this); - } -+ } // Paper - } - - long getCreatedAt() { -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - this.next = next; - } - -- Class getTaskClass() { -+ public Class getTaskClass() { // Paper - return (this.rTask != null) ? this.rTask.getClass() : ((this.cTask != null) ? this.cTask.getClass() : null); - } - -@@ -0,0 +0,0 @@ public class CraftTask implements BukkitTask, Runnable { // Spigot - return true; - } - -- // Spigot start -- public String getTaskName() { -- return (this.getTaskClass() == null) ? "Unknown" : this.getTaskClass().getName(); -- } -- // Spigot end - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftIconCache.java -@@ -0,0 +0,0 @@ public class CraftIconCache implements CachedServerIcon { - public CraftIconCache(final byte[] value) { - this.value = value; - } -+ -+ public String getData() { -+ if (value == null) { -+ return null; -+ } -+ return "data:image/png;base64," + new String(java.util.Base64.getEncoder().encode(value), java.nio.charset.StandardCharsets.UTF_8); -+ } // Paper - } -diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - return CraftNamespacedKey.toMinecraft(mat.getKey()); - } - // ======================================================================== -+ // Paper start -+ @Override -+ public void reportTimings() { -+ co.aikar.timings.TimingsExport.reportTimings(); -+ } -+ // Paper end - - public static byte toLegacyData(BlockState data) { - return CraftLegacy.toLegacyData(data); -@@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - public DamageSource.Builder createDamageSourceBuilder(DamageType damageType) { - return new CraftDamageSourceBuilder(damageType); - } -+ // Paper start -+ @Override -+ public String getTimingsServerName() { -+ return io.papermc.paper.configuration.GlobalConfiguration.get().timings.serverName; -+ } -+ // Paper end - - @Override - public String get(Class aClass, String s) { -diff --git a/src/main/java/org/spigotmc/ActivationRange.java b/src/main/java/org/spigotmc/ActivationRange.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/ActivationRange.java -+++ b/src/main/java/org/spigotmc/ActivationRange.java -@@ -0,0 +0,0 @@ import net.minecraft.world.entity.projectile.ThrownTrident; - import net.minecraft.world.entity.raid.Raider; - import net.minecraft.world.level.Level; - import net.minecraft.world.phys.AABB; --import org.bukkit.craftbukkit.SpigotTimings; -+import co.aikar.timings.MinecraftTimings; - - public class ActivationRange - { -@@ -0,0 +0,0 @@ public class ActivationRange - /** - * These entities are excluded from Activation range checks. - * -- * @param entity -- * @param config -+ * @param entity Entity to initialize -+ * @param config Spigot config to determine ranges - * @return boolean If it should always tick. - */ - public static boolean initializeEntityActivationState(Entity entity, SpigotWorldConfig config) -@@ -0,0 +0,0 @@ public class ActivationRange - */ - public static void activateEntities(Level world) - { -- SpigotTimings.entityActivationCheckTimer.startTiming(); -+ MinecraftTimings.entityActivationCheckTimer.startTiming(); - final int miscActivationRange = world.spigotConfig.miscActivationRange; - final int raiderActivationRange = world.spigotConfig.raiderActivationRange; - final int animalActivationRange = world.spigotConfig.animalActivationRange; -@@ -0,0 +0,0 @@ public class ActivationRange - - world.getEntities().get(ActivationRange.maxBB, ActivationRange::activateEntity); - } -- SpigotTimings.entityActivationCheckTimer.stopTiming(); -+ MinecraftTimings.entityActivationCheckTimer.stopTiming(); - } - - /** -@@ -0,0 +0,0 @@ public class ActivationRange - */ - public static boolean checkIfActive(Entity entity) - { -- SpigotTimings.checkIfActiveTimer.startTiming(); - // Never safe to skip fireworks or entities not yet added to chunk - if ( entity instanceof FireworkRocketEntity ) { -- SpigotTimings.checkIfActiveTimer.stopTiming(); - return true; - } - -@@ -0,0 +0,0 @@ public class ActivationRange - { - isActive = false; - } -- SpigotTimings.checkIfActiveTimer.stopTiming(); - return isActive; - } - } diff --git a/patches/server/Use-a-Queue-for-Queueing-Commands.patch b/patches/server/Use-a-Queue-for-Queueing-Commands.patch index 637c1a6922..480719b172 100644 --- a/patches/server/Use-a-Queue-for-Queueing-Commands.patch +++ b/patches/server/Use-a-Queue-for-Queueing-Commands.patch @@ -27,7 +27,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public void handleConsoleInputs() { - MinecraftTimings.serverCommandTimer.startTiming(); // Spigot - while (!this.consoleInput.isEmpty()) { - ConsoleInput servercommand = (ConsoleInput) this.consoleInput.remove(0); + // Paper start - Perf: use proper queue diff --git a/patches/server/remove-null-possibility-for-getServer-singleton.patch b/patches/server/remove-null-possibility-for-getServer-singleton.patch index a743fbc2bd..aa397c3ef4 100644 --- a/patches/server/remove-null-possibility-for-getServer-singleton.patch +++ b/patches/server/remove-null-possibility-for-getServer-singleton.patch @@ -9,7 +9,7 @@ diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/ index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ import co.aikar.timings.MinecraftTimings; // Paper +@@ -0,0 +0,0 @@ import org.bukkit.event.server.ServerLoadEvent; public abstract class MinecraftServer extends ReentrantBlockableEventLoop implements ServerInfo, ChunkIOErrorReporter, CommandSource {