diff --git a/Spigot-API-Patches/Timings-v2.patch b/Spigot-API-Patches/Timings-v2.patch
index 8dc3241d37..390f746f93 100644
--- a/Spigot-API-Patches/Timings-v2.patch
+++ b/Spigot-API-Patches/Timings-v2.patch
@@ -22,663 +22,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
commons-lang
commons-lang
2.6
-diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/Bukkit.java
-+++ b/src/main/java/org/bukkit/Bukkit.java
-@@ -0,0 +0,0 @@ public final class Bukkit {
- */
- public static void reload() {
- server.reload();
-- org.spigotmc.CustomTimingsHandler.reload(); // Spigot
- }
-
- /**
-diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/Server.java
-+++ b/src/main/java/org/bukkit/Server.java
-@@ -0,0 +0,0 @@ public interface Server extends PluginMessageRecipient {
-
- public class Spigot
- {
--
-+ @Deprecated
- public org.bukkit.configuration.file.YamlConfiguration getConfig()
- {
- throw new UnsupportedOperationException( "Not supported yet." );
- }
-
-+ public org.bukkit.configuration.file.YamlConfiguration getBukkitConfig()
-+ {
-+ throw new UnsupportedOperationException( "Not supported yet." );
-+ }
-+
-+ public org.bukkit.configuration.file.YamlConfiguration getSpigotConfig()
-+ {
-+ throw new UnsupportedOperationException("Not supported yet.");
-+ }
-+
-+ public org.bukkit.configuration.file.YamlConfiguration getPaperSpigotConfig()
-+ {
-+ throw new UnsupportedOperationException("Not supported yet.");
-+ }
-+
- /**
- * Sends the component to the player
- *
-diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/command/Command.java
-+++ b/src/main/java/org/bukkit/command/Command.java
-@@ -0,0 +0,0 @@ public abstract class Command {
- protected String usageMessage;
- private String permission;
- private String permissionMessage;
-- public org.spigotmc.CustomTimingsHandler timings; // Spigot
-+ public org.spigotmc.timings.Timing timings; // Spigot
-+ public String getTimingName() {return getName();} // Spigot
-
- protected Command(String name) {
- this(name, "", "/" + name, new ArrayList());
-@@ -0,0 +0,0 @@ public abstract class Command {
- this.usageMessage = usageMessage;
- this.aliases = aliases;
- this.activeAliases = new ArrayList(aliases);
-- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot
- }
-
- /**
-@@ -0,0 +0,0 @@ public abstract class Command {
- public boolean setLabel(String name) {
- this.nextLabel = name;
- if (!isRegistered()) {
-- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot
- this.label = name;
- return true;
- }
-diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java
-+++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java
-@@ -0,0 +0,0 @@ public class FormattedCommandAlias extends Command {
-
- public FormattedCommandAlias(String alias, String[] formatStrings) {
- super(alias);
-+ timings = org.spigotmc.timings.TimingsManager.getCommandTiming("minecraft", this); // Spigot
- this.formatStrings = formatStrings;
- }
-
-@@ -0,0 +0,0 @@ public class FormattedCommandAlias extends Command {
- return formatString;
- }
-
-+ @Override // Spigot
-+ public String getTimingName() {return "Command Forwarder - " + super.getTimingName();} // Spigot
-+
- private static boolean inRange(int i, int j, int k) {
- return i >= j && i <= k;
- }
-diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/command/SimpleCommandMap.java
-+++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java
-@@ -0,0 +0,0 @@ public class SimpleCommandMap implements CommandMap {
- register("bukkit", new VersionCommand("version"));
- register("bukkit", new ReloadCommand("reload"));
- register("bukkit", new PluginsCommand("plugins"));
-- register("bukkit", new TimingsCommand("timings"));
-+ register("bukkit", new org.spigotmc.timings.TimingsCommand("timings")); // Spigot
- }
-
- public void setFallbackCommands() {
-@@ -0,0 +0,0 @@ public class SimpleCommandMap implements CommandMap {
- * {@inheritDoc}
- */
- public boolean register(String label, String fallbackPrefix, Command command) {
-+ command.timings = org.spigotmc.timings.TimingsManager.getCommandTiming(fallbackPrefix, command); // Spigot
- label = label.toLowerCase().trim();
- fallbackPrefix = fallbackPrefix.toLowerCase().trim();
- boolean registered = register(label, command, false, fallbackPrefix);
-diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java
-+++ b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java
-@@ -0,0 +0,0 @@ import org.spigotmc.CustomTimingsHandler;
- // Spigot end
-
- public class TimingsCommand extends BukkitCommand {
-- private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste"); // Spigot
-- public static long timingStart = 0; // Spigot
-+ public static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("merged", "reset", "separate");
-
- public TimingsCommand(String name) {
- super(name);
-- this.description = "Manages Spigot Timings data to see performance of the server."; // Spigot
-- this.usageMessage = "/timings "; // Spigot
-+ this.description = "Records timings for all plugin events";
-+ this.usageMessage = "/timings ";
- this.setPermission("bukkit.command.timings");
- }
-
-- // Spigot start - redesigned Timings Command
-- public void executeSpigotTimings(CommandSender sender, String[] args) {
-- if ( "on".equals( args[0] ) )
-- {
-- ( (SimplePluginManager) Bukkit.getPluginManager() ).useTimings( true );
-- CustomTimingsHandler.reload();
-- sender.sendMessage( "Enabled Timings & Reset" );
-- return;
-- } else if ( "off".equals( args[0] ) )
-- {
-- ( (SimplePluginManager) Bukkit.getPluginManager() ).useTimings( false );
-- sender.sendMessage( "Disabled Timings" );
-- return;
-- }
--
-- if ( !Bukkit.getPluginManager().useTimings() )
-- {
-- sender.sendMessage( "Please enable timings by typing /timings on" );
-- return;
-- }
--
-- boolean paste = "paste".equals( args[0] );
-- if ("reset".equals(args[0])) {
-- CustomTimingsHandler.reload();
-- sender.sendMessage("Timings reset");
-- } else if ("merged".equals(args[0]) || "report".equals(args[0]) || paste) {
-- long sampleTime = System.nanoTime() - timingStart;
-- int index = 0;
-- File timingFolder = new File("timings");
-- timingFolder.mkdirs();
-- File timings = new File(timingFolder, "timings.txt");
-- ByteArrayOutputStream bout = ( paste ) ? new ByteArrayOutputStream() : null;
-- while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt");
-- PrintStream fileTimings = null;
-- try {
-- fileTimings = ( paste ) ? new PrintStream( bout ) : new PrintStream( timings );
--
-- CustomTimingsHandler.printTimings(fileTimings);
-- fileTimings.println( "Sample time " + sampleTime + " (" + sampleTime / 1E9 + "s)" );
--
-- fileTimings.println( "" );
-- fileTimings.println( Bukkit.spigot().getConfig().saveToString() );
-- fileTimings.println( "" );
--
-- if ( paste )
-- {
-- new PasteThread( sender, bout ).start();
-- return;
-- }
--
-- sender.sendMessage("Timings written to " + timings.getPath());
-- sender.sendMessage( "Paste contents of file into form at http://aikar.co/timings.php to read results." );
--
-- } catch (IOException e) {
-- } finally {
-- if (fileTimings != null) {
-- fileTimings.close();
-- }
-- }
-- }
-- }
-- // Spigot end
--
- @Override
- public boolean execute(CommandSender sender, String currentAlias, String[] args) {
- if (!testPermission(sender)) return true;
-- if (args.length < 1) { // Spigot
-+ if (args.length != 1) {
- sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
- return false;
- }
-- if (true) { executeSpigotTimings(sender, args); return true; } // Spigot
- if (!sender.getServer().getPluginManager().useTimings()) {
- sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml");
- return true;
-@@ -0,0 +0,0 @@ public class TimingsCommand extends BukkitCommand {
- }
- return ImmutableList.of();
- }
--
-- // Spigot start
-- private static class PasteThread extends Thread
-- {
--
-- private final CommandSender sender;
-- private final ByteArrayOutputStream bout;
--
-- public PasteThread(CommandSender sender, ByteArrayOutputStream bout)
-- {
-- super( "Timings paste thread" );
-- this.sender = sender;
-- this.bout = bout;
-- }
--
-- @Override
-- public synchronized void start() {
-- if (sender instanceof RemoteConsoleCommandSender) {
-- run();
-- } else {
-- super.start();
-- }
-- }
--
-- @Override
-- public void run()
-- {
-- try
-- {
-- HttpURLConnection con = (HttpURLConnection) new URL( "http://paste.ubuntu.com/" ).openConnection();
-- con.setDoOutput( true );
-- con.setRequestMethod( "POST" );
-- con.setInstanceFollowRedirects( false );
--
-- OutputStream out = con.getOutputStream();
-- out.write( "poster=Spigot&syntax=text&content=".getBytes( "UTF-8" ) );
-- out.write( URLEncoder.encode( bout.toString( "UTF-8" ), "UTF-8" ).getBytes( "UTF-8" ) );
-- out.close();
-- con.getInputStream().close();
--
-- String location = con.getHeaderField( "Location" );
-- String pasteID = location.substring( "http://paste.ubuntu.com/".length(), location.length() - 1 );
-- sender.sendMessage( ChatColor.GREEN + "Timings results can be viewed at http://aikar.co/timings.php?url=" + pasteID );
-- } catch ( IOException ex )
-- {
-- sender.sendMessage( ChatColor.RED + "Error pasting timings, check your console for more information" );
-- Bukkit.getServer().getLogger().log( Level.WARNING, "Could not paste timings", ex );
-- }
-- }
-- }
-- // Spigot end
- }
-diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/entity/Player.java
-+++ b/src/main/java/org/bukkit/entity/Player.java
-@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
- {
- throw new UnsupportedOperationException( "Not supported yet" );
- }
-+
-+ public int getPing()
-+ {
-+ throw new UnsupportedOperationException( "Not supported yet." );
-+ }
- }
-
- Spigot spigot();
-diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-+++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
-@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
- }
- }
-
-- org.bukkit.command.defaults.TimingsCommand.timingStart = System.nanoTime(); // Spigot
- return result.toArray(new Plugin[result.size()]);
- }
-
-@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
-
- if (result != null) {
- plugins.add(result);
-- lookupNames.put(result.getDescription().getName(), result);
-+ lookupNames.put(result.getDescription().getName().toLowerCase(), result); // Spigot
- }
-
- return result;
-@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
- * @return Plugin if it exists, otherwise null
- */
- public synchronized Plugin getPlugin(String name) {
-- return lookupNames.get(name.replace(' ', '_'));
-+ return lookupNames.get(name.replace(' ', '_').toLowerCase()); // Spigot
- }
-
- public synchronized Plugin[] getPlugins() {
-@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
- throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled");
- }
-
-- if (useTimings) {
-+ executor = new org.spigotmc.timings.TimedEventExecutor(executor, plugin, null, event); // Spigot
-+ if (false) { // Spigot - RL handles useTimings check now
- getEventListeners(event).register(new TimedRegisteredListener(listener, executor, priority, plugin, ignoreCancelled));
- } else {
- getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled));
-@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
- }
-
- public boolean useTimings() {
-- return useTimings;
-+ return org.spigotmc.timings.Timings.isTimingsEnabled(); // Spigot
- }
-
- /**
-@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
- * @param use True if per event timing code should be used
- */
- public void useTimings(boolean use) {
-- useTimings = use;
-+ org.spigotmc.timings.Timings.setTimingsEnabled(use); // Spigot
- }
- }
-diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
-+++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
-@@ -0,0 +0,0 @@ import org.bukkit.plugin.PluginLoader;
- import org.bukkit.plugin.RegisteredListener;
- import org.bukkit.plugin.TimedRegisteredListener;
- import org.bukkit.plugin.UnknownDependencyException;
--import org.spigotmc.CustomTimingsHandler; // Spigot
- import org.yaml.snakeyaml.error.YAMLException;
-
- /**
-@@ -0,0 +0,0 @@ public final class JavaPluginLoader implements PluginLoader {
- private final Pattern[] fileFilters = new Pattern[] { Pattern.compile("\\.jar$"), };
- private final Map> classes = new java.util.concurrent.ConcurrentHashMap>(); // Spigot
- private final Map loaders = new LinkedHashMap();
-- public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot
-
- /**
- * This class was not meant to be constructed explicitly
-@@ -0,0 +0,0 @@ public final class JavaPluginLoader implements PluginLoader {
- }
- }
-
-- final CustomTimingsHandler timings = new CustomTimingsHandler("Plugin: " + plugin.getDescription().getFullName() + " Event: " + listener.getClass().getName() + "::" + method.getName()+"("+eventClass.getSimpleName()+")", pluginParentTimer); // Spigot
-- EventExecutor executor = new EventExecutor() {
-+ EventExecutor executor = new org.spigotmc.timings.TimedEventExecutor(new EventExecutor() { // Spigot
- public void execute(Listener listener, Event event) throws EventException {
- try {
- if (!eventClass.isAssignableFrom(event.getClass())) {
- return;
- }
-- // Spigot start
-- boolean isAsync = event.isAsynchronous();
-- if (!isAsync) timings.startTiming();
- method.invoke(listener, event);
-- if (!isAsync) timings.stopTiming();
-- // Spigot end
- } catch (InvocationTargetException ex) {
- throw new EventException(ex.getCause());
- } catch (Throwable t) {
- throw new EventException(t);
- }
- }
-- };
-+ }, plugin, method, eventClass); // Spigot
- if (false) { // Spigot - RL handles useTimings check now
- eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
- } else {
-diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
-+++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
-@@ -0,0 +0,0 @@ import org.bukkit.plugin.PluginDescriptionFile;
- /**
- * A ClassLoader for plugins, to allow shared classes across multiple plugins
- */
--final class PluginClassLoader extends URLClassLoader {
-+public final class PluginClassLoader extends URLClassLoader { // Spigot
-+ public JavaPlugin getPlugin() { return plugin; } // Spigot
- private final JavaPluginLoader loader;
- private final Map> classes = new java.util.concurrent.ConcurrentHashMap>(); // Spigot
- private final PluginDescriptionFile description;
-diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/bukkit/util/CachedServerIcon.java
-+++ b/src/main/java/org/bukkit/util/CachedServerIcon.java
-@@ -0,0 +0,0 @@ import org.bukkit.event.server.ServerListPingEvent;
- * @see Server#loadServerIcon(java.io.File)
- * @see ServerListPingEvent#setServerIcon(CachedServerIcon)
- */
--public interface CachedServerIcon {}
-+public interface CachedServerIcon {
-+ public String getData(); // Spigot
-+}
-diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
---- a/src/main/java/org/spigotmc/CustomTimingsHandler.java
-+++ b/src/main/java/org/spigotmc/CustomTimingsHandler.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 org.spigotmc;
-
--import org.bukkit.command.defaults.TimingsCommand;
--import org.bukkit.event.HandlerList;
-+import org.bukkit.Bukkit;
-+import org.bukkit.plugin.AuthorNagException;
- import org.bukkit.plugin.Plugin;
--import org.bukkit.plugin.RegisteredListener;
--import org.bukkit.plugin.TimedRegisteredListener;
--import java.io.PrintStream;
--import java.util.Collection;
--import java.util.HashSet;
--import java.util.List;
--import java.util.Queue;
--import java.util.concurrent.ConcurrentLinkedQueue;
-+import org.spigotmc.timings.NullTimingHandler;
-+import org.spigotmc.timings.Timing;
-+import org.spigotmc.timings.Timings;
-+import org.spigotmc.timings.TimingsManager;
-+import sun.reflect.Reflection;
-
--import org.bukkit.Bukkit;
--import org.bukkit.World;
-+import java.lang.reflect.Method;
-+import java.util.logging.Level;
-
- /**
-- * Provides custom timing sections for /timings merged.
-+ * This is here for legacy purposes incase any plugin used it.
-+ *
-+ * If you use this, migrate ASAP as this will be removed in the future!
-+ *
-+ * @deprecated
-+ * @see org.spigotmc.timings.Timings#of
- */
--public class CustomTimingsHandler
--{
-+@Deprecated
-+public final class CustomTimingsHandler {
-+ private final Timing handler;
-
-- private static Queue HANDLERS = new ConcurrentLinkedQueue();
-- /*========================================================================*/
-- private final String name;
-- private final CustomTimingsHandler parent;
-- private long count = 0;
-- private long start = 0;
-- private long timingDepth = 0;
-- private long totalTime = 0;
-- private long curTickTotal = 0;
-- private long violations = 0;
-+ public CustomTimingsHandler(String name) {
-+ Timing timing;
-
-- public CustomTimingsHandler(String name)
-- {
-- this( name, null );
-- }
-+ Plugin plugin = null;
-+ try {
-+ plugin = TimingsManager.getPluginByClassloader(Reflection.getCallerClass(2));
-+ } catch (Exception ignored) {}
-
-- public CustomTimingsHandler(String name, CustomTimingsHandler parent)
-- {
-- this.name = name;
-- this.parent = parent;
-- HANDLERS.add( this );
-- }
--
-- /**
-- * Prints the timings and extra data to the given stream.
-- *
-- * @param printStream
-- */
-- public static void printTimings(PrintStream printStream)
-- {
-- printStream.println( "Minecraft" );
-- for ( CustomTimingsHandler timings : HANDLERS )
-- {
-- long time = timings.totalTime;
-- long count = timings.count;
-- if ( count == 0 )
-- {
-- continue;
-+ new AuthorNagException("Deprecated use of CustomTimingsHandler. Please Switch to Timings.of ASAP").printStackTrace();
-+ if (plugin != null) {
-+ timing = Timings.of(plugin, "(Deprecated API) " + name);
-+ } else {
-+ try {
-+ final Method ofSafe = TimingsManager.class.getMethod("getHandler", String.class, String.class, Timing.class, boolean.class);
-+ timing = (Timing) ofSafe.invoke("Minecraft", "(Deprecated API) " + name, null, true);
-+ } catch (Exception e) {
-+ Bukkit.getLogger().log(Level.SEVERE, "This handler could not be registered");
-+ timing = Timings.NULL_HANDLER;
- }
-- long avg = time / count;
--
-- printStream.println( " " + timings.name + " Time: " + time + " Count: " + count + " Avg: " + avg + " Violations: " + timings.violations );
- }
-- printStream.println( "# Version " + Bukkit.getVersion() );
-- int entities = 0;
-- int livingEntities = 0;
-- for ( World world : Bukkit.getWorlds() )
-- {
-- entities += world.getEntities().size();
-- livingEntities += world.getLivingEntities().size();
-- }
-- printStream.println( "# Entities " + entities );
-- printStream.println( "# LivingEntities " + livingEntities );
-+ handler = timing;
- }
-
-- /**
-- * Resets all timings.
-- */
-- public static void reload()
-- {
-- if ( Bukkit.getPluginManager().useTimings() )
-- {
-- for ( CustomTimingsHandler timings : HANDLERS )
-- {
-- timings.reset();
-- }
-- }
-- TimingsCommand.timingStart = System.nanoTime();
-- }
-+ public void startTiming() { handler.startTiming(); }
-+ public void stopTiming() { handler.stopTiming(); }
-
-- /**
-- * Ticked every tick by CraftBukkit to count the number of times a timer
-- * caused TPS loss.
-- */
-- public static void tick()
-- {
-- if ( Bukkit.getPluginManager().useTimings() )
-- {
-- for ( CustomTimingsHandler timings : HANDLERS )
-- {
-- if ( timings.curTickTotal > 50000000 )
-- {
-- timings.violations += Math.ceil( timings.curTickTotal / 50000000 );
-- }
-- timings.curTickTotal = 0;
-- timings.timingDepth = 0; // incase reset messes this up
-- }
-- }
-- }
--
-- /**
-- * Starts timing to track a section of code.
-- */
-- public void startTiming()
-- {
-- // If second condtion fails we are already timing
-- if ( Bukkit.getPluginManager().useTimings() && ++timingDepth == 1 )
-- {
-- start = System.nanoTime();
-- if ( parent != null && ++parent.timingDepth == 1 )
-- {
-- parent.start = start;
-- }
-- }
-- }
--
-- /**
-- * Stops timing a section of code.
-- */
-- public void stopTiming()
-- {
-- if ( Bukkit.getPluginManager().useTimings() )
-- {
-- if ( --timingDepth != 0 || start == 0 )
-- {
-- return;
-- }
-- long diff = System.nanoTime() - start;
-- totalTime += diff;
-- curTickTotal += diff;
-- count++;
-- start = 0;
-- if ( parent != null )
-- {
-- parent.stopTiming();
-- }
-- }
-- }
--
-- /**
-- * Reset this timer, setting all values to zero.
-- */
-- public void reset()
-- {
-- count = 0;
-- violations = 0;
-- curTickTotal = 0;
-- totalTime = 0;
-- start = 0;
-- timingDepth = 0;
-- }
- }
-diff --git a/src/main/java/org/spigotmc/timings/FullServerTickHandler.java b/src/main/java/org/spigotmc/timings/FullServerTickHandler.java
+diff --git a/src/main/java/co/aikar/timings/FullServerTickHandler.java b/src/main/java/co/aikar/timings/FullServerTickHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/FullServerTickHandler.java
++++ b/src/main/java/co/aikar/timings/FullServerTickHandler.java
@@ -0,0 +0,0 @@
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
-+import static org.spigotmc.timings.TimingsManager.*;
++import static co.aikar.timings.TimingsManager.*;
+
+public class FullServerTickHandler extends TimingHandler {
+ static final TimingIdentifier IDENTITY = new TimingIdentifier("Minecraft", "Full Server Tick", null, false);
@@ -755,11 +107,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return record.curTickTotal > 50000000;
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/NullTimingHandler.java b/src/main/java/org/spigotmc/timings/NullTimingHandler.java
+diff --git a/src/main/java/co/aikar/timings/NullTimingHandler.java b/src/main/java/co/aikar/timings/NullTimingHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/NullTimingHandler.java
++++ b/src/main/java/co/aikar/timings/NullTimingHandler.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -784,7 +136,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+public final class NullTimingHandler implements Timing {
+ @Override
@@ -822,11 +174,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/TimedEventExecutor.java b/src/main/java/org/spigotmc/timings/TimedEventExecutor.java
+diff --git a/src/main/java/co/aikar/timings/TimedEventExecutor.java b/src/main/java/co/aikar/timings/TimedEventExecutor.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/TimedEventExecutor.java
++++ b/src/main/java/co/aikar/timings/TimedEventExecutor.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -851,7 +203,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import org.bukkit.Bukkit;
+import org.bukkit.event.Event;
@@ -909,11 +261,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ timings.stopTiming();
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/Timing.java b/src/main/java/org/spigotmc/timings/Timing.java
+diff --git a/src/main/java/co/aikar/timings/Timing.java b/src/main/java/co/aikar/timings/Timing.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/Timing.java
++++ b/src/main/java/co/aikar/timings/Timing.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -938,7 +290,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+/**
+ * Provides an ability to time sections of code within the Minecraft Server
@@ -987,11 +339,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ @Override
+ void close();
+}
-diff --git a/src/main/java/org/spigotmc/timings/TimingData.java b/src/main/java/org/spigotmc/timings/TimingData.java
+diff --git a/src/main/java/co/aikar/timings/TimingData.java b/src/main/java/co/aikar/timings/TimingData.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/TimingData.java
++++ b/src/main/java/co/aikar/timings/TimingData.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -1016,13 +368,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import com.google.common.base.Function;
+
+import java.util.List;
+
-+import static org.spigotmc.util.JSONUtil.toArray;
++import static co.aikar.util.JSONUtil.toArray;
+
+/**
+ * Lightweight object for tracking timing data
@@ -1098,11 +450,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return list;
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/TimingHandler.java b/src/main/java/org/spigotmc/timings/TimingHandler.java
+diff --git a/src/main/java/co/aikar/timings/TimingHandler.java b/src/main/java/co/aikar/timings/TimingHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/TimingHandler.java
++++ b/src/main/java/co/aikar/timings/TimingHandler.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -1127,13 +479,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import gnu.trove.map.hash.TIntObjectHashMap;
+import org.bukkit.Bukkit;
-+import org.spigotmc.util.LoadingIntMap;
-+import org.spigotmc.util.LoadingMap;
-+import org.spigotmc.util.MRUMapCache;
++import co.aikar.util.LoadingIntMap;
++import co.aikar.util.LoadingMap;
++import co.aikar.util.MRUMapCache;
+
+import java.util.Map;
+import java.util.logging.Level;
@@ -1297,11 +649,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return this == TimingsManager.FULL_SERVER_TICK || this == TimingsManager.TIMINGS_TICK;
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/TimingHistory.java b/src/main/java/org/spigotmc/timings/TimingHistory.java
+diff --git a/src/main/java/co/aikar/timings/TimingHistory.java b/src/main/java/co/aikar/timings/TimingHistory.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/TimingHistory.java
++++ b/src/main/java/co/aikar/timings/TimingHistory.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -1326,7 +678,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Sets;
@@ -1338,8 +690,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.Player;
-+import org.spigotmc.util.LoadingMap;
-+import org.spigotmc.util.MRUMapCache;
++import co.aikar.util.LoadingMap;
++import co.aikar.util.MRUMapCache;
+
+import java.lang.management.ManagementFactory;
+import java.util.Collection;
@@ -1348,9 +700,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import java.util.Map;
+import java.util.Set;
+
-+import static org.spigotmc.timings.TimingsManager.FULL_SERVER_TICK;
-+import static org.spigotmc.timings.TimingsManager.MINUTE_REPORTS;
-+import static org.spigotmc.util.JSONUtil.*;
++import static co.aikar.timings.TimingsManager.FULL_SERVER_TICK;
++import static co.aikar.timings.TimingsManager.MINUTE_REPORTS;
++import static co.aikar.util.JSONUtil.*;
+
+@SuppressWarnings({"deprecation", "SuppressionAnnotation"})
+public class TimingHistory {
@@ -1579,11 +931,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/TimingHistoryEntry.java b/src/main/java/org/spigotmc/timings/TimingHistoryEntry.java
+diff --git a/src/main/java/co/aikar/timings/TimingHistoryEntry.java b/src/main/java/co/aikar/timings/TimingHistoryEntry.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/TimingHistoryEntry.java
++++ b/src/main/java/co/aikar/timings/TimingHistoryEntry.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -1608,13 +960,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import com.google.common.base.Function;
+
+import java.util.List;
+
-+import static org.spigotmc.util.JSONUtil.toArrayMapper;
++import static co.aikar.util.JSONUtil.toArrayMapper;
+
+class TimingHistoryEntry {
+ final TimingData data;
@@ -1644,11 +996,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return result;
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/TimingIdentifier.java b/src/main/java/org/spigotmc/timings/TimingIdentifier.java
+diff --git a/src/main/java/co/aikar/timings/TimingIdentifier.java b/src/main/java/co/aikar/timings/TimingIdentifier.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/TimingIdentifier.java
++++ b/src/main/java/co/aikar/timings/TimingIdentifier.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -1673,11 +1025,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import com.google.common.base.Function;
-+import org.spigotmc.util.LoadingMap;
-+import org.spigotmc.util.MRUMapCache;
++import co.aikar.util.LoadingMap;
++import co.aikar.util.MRUMapCache;
+
+import java.util.ArrayDeque;
+import java.util.Map;
@@ -1752,11 +1104,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/Timings.java b/src/main/java/org/spigotmc/timings/Timings.java
+diff --git a/src/main/java/co/aikar/timings/Timings.java b/src/main/java/co/aikar/timings/Timings.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/Timings.java
++++ b/src/main/java/co/aikar/timings/Timings.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -1781,7 +1133,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.EvictingQueue;
@@ -2031,11 +1383,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return TimingsManager.getHandler(groupName, name, groupHandler, false);
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/TimingsCommand.java b/src/main/java/org/spigotmc/timings/TimingsCommand.java
+diff --git a/src/main/java/co/aikar/timings/TimingsCommand.java b/src/main/java/co/aikar/timings/TimingsCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/TimingsCommand.java
++++ b/src/main/java/co/aikar/timings/TimingsCommand.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -2060,7 +1412,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.commons.lang.Validate;
@@ -2147,11 +1499,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return ImmutableList.of();
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/TimingsExport.java b/src/main/java/org/spigotmc/timings/TimingsExport.java
+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/org/spigotmc/timings/TimingsExport.java
++++ b/src/main/java/co/aikar/timings/TimingsExport.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -2176,7 +1528,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Sets;
@@ -2211,8 +1563,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import java.util.logging.Level;
+import java.util.zip.GZIPOutputStream;
+
-+import static org.spigotmc.timings.TimingsManager.HISTORY;
-+import static org.spigotmc.util.JSONUtil.*;
++import static co.aikar.timings.TimingsManager.HISTORY;
++import static co.aikar.util.JSONUtil.*;
+
+@SuppressWarnings({"rawtypes", "SuppressionAnnotation"})
+class TimingsExport extends Thread {
@@ -2526,11 +1878,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/TimingsManager.java b/src/main/java/org/spigotmc/timings/TimingsManager.java
+diff --git a/src/main/java/co/aikar/timings/TimingsManager.java b/src/main/java/co/aikar/timings/TimingsManager.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/TimingsManager.java
++++ b/src/main/java/co/aikar/timings/TimingsManager.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -2555,7 +1907,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import com.google.common.base.Function;
+import com.google.common.collect.EvictingQueue;
@@ -2564,7 +1916,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+import org.bukkit.command.Command;
+import org.bukkit.plugin.Plugin;
+import org.bukkit.plugin.java.PluginClassLoader;
-+import org.spigotmc.util.LoadingMap;
++import co.aikar.util.LoadingMap;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
@@ -2726,11 +2078,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return null;
+ }
+}
-diff --git a/src/main/java/org/spigotmc/timings/UnsafeTimingHandler.java b/src/main/java/org/spigotmc/timings/UnsafeTimingHandler.java
+diff --git a/src/main/java/co/aikar/timings/UnsafeTimingHandler.java b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/UnsafeTimingHandler.java
++++ b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -2755,7 +2107,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.timings;
++package co.aikar.timings;
+
+import org.bukkit.Bukkit;
+
@@ -2783,13 +2135,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ super.stopTiming();
+ }
+}
-diff --git a/src/main/java/org/spigotmc/util/JSONUtil.java b/src/main/java/org/spigotmc/util/JSONUtil.java
+diff --git a/src/main/java/co/aikar/util/JSONUtil.java b/src/main/java/co/aikar/util/JSONUtil.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/util/JSONUtil.java
++++ b/src/main/java/co/aikar/util/JSONUtil.java
@@ -0,0 +0,0 @@
-+package org.spigotmc.util;
++package co.aikar.util;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
@@ -2912,11 +2264,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ }
+ }
+}
-diff --git a/src/main/java/org/spigotmc/util/LoadingIntMap.java b/src/main/java/org/spigotmc/util/LoadingIntMap.java
+diff --git a/src/main/java/co/aikar/util/LoadingIntMap.java b/src/main/java/co/aikar/util/LoadingIntMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/util/LoadingIntMap.java
++++ b/src/main/java/co/aikar/util/LoadingIntMap.java
@@ -0,0 +0,0 @@
+/*
+ * Copyright (c) 2015. Starlis LLC / dba Empire Minecraft
@@ -2924,7 +2276,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * This source code is proprietary software and must not be redistributed without Starlis LLC's approval
+ *
+ */
-+package org.spigotmc.util;
++package co.aikar.util;
+
+
+import com.google.common.base.Function;
@@ -2986,11 +2338,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public abstract T apply();
+ }
+}
-diff --git a/src/main/java/org/spigotmc/util/LoadingMap.java b/src/main/java/org/spigotmc/util/LoadingMap.java
+diff --git a/src/main/java/co/aikar/util/LoadingMap.java b/src/main/java/co/aikar/util/LoadingMap.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/util/LoadingMap.java
++++ b/src/main/java/co/aikar/util/LoadingMap.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -3015,12 +2367,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.util;
++package co.aikar.util;
+
+
+import com.google.common.base.Function;
+import org.bukkit.Material;
-+import org.spigotmc.timings.TimingHistory;
++import co.aikar.timings.TimingHistory;
+import org.w3c.dom.css.Counter;
+
+import java.lang.reflect.Constructor;
@@ -3324,11 +2676,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ public abstract T apply();
+ }
+}
-diff --git a/src/main/java/org/spigotmc/util/MRUMapCache.java b/src/main/java/org/spigotmc/util/MRUMapCache.java
+diff --git a/src/main/java/co/aikar/util/MRUMapCache.java b/src/main/java/co/aikar/util/MRUMapCache.java
new file mode 100644
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
--- /dev/null
-+++ b/src/main/java/org/spigotmc/util/MRUMapCache.java
++++ b/src/main/java/co/aikar/util/MRUMapCache.java
@@ -0,0 +0,0 @@
+/*
+ * This file is licensed under the MIT License (MIT).
@@ -3353,7 +2705,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
-+package org.spigotmc.util;
++package co.aikar.util;
+
+import java.util.AbstractMap;
+import java.util.Collection;
@@ -3430,4 +2782,652 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
+ return new MRUMapCache(map);
+ }
+}
+diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/Bukkit.java
++++ b/src/main/java/org/bukkit/Bukkit.java
+@@ -0,0 +0,0 @@ public final class Bukkit {
+ */
+ public static void reload() {
+ server.reload();
+- org.spigotmc.CustomTimingsHandler.reload(); // Spigot
+ }
+
+ /**
+diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/Server.java
++++ b/src/main/java/org/bukkit/Server.java
+@@ -0,0 +0,0 @@ public interface Server extends PluginMessageRecipient {
+
+ public class Spigot
+ {
+-
++ @Deprecated
+ public org.bukkit.configuration.file.YamlConfiguration getConfig()
+ {
+ throw new UnsupportedOperationException( "Not supported yet." );
+ }
+
++ public org.bukkit.configuration.file.YamlConfiguration getBukkitConfig()
++ {
++ throw new UnsupportedOperationException( "Not supported yet." );
++ }
++
++ public org.bukkit.configuration.file.YamlConfiguration getSpigotConfig()
++ {
++ throw new UnsupportedOperationException("Not supported yet.");
++ }
++
++ public org.bukkit.configuration.file.YamlConfiguration getPaperSpigotConfig()
++ {
++ throw new UnsupportedOperationException("Not supported yet.");
++ }
++
+ /**
+ * Sends the component to the player
+ *
+diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/command/Command.java
++++ b/src/main/java/org/bukkit/command/Command.java
+@@ -0,0 +0,0 @@ public abstract class Command {
+ protected String usageMessage;
+ private String permission;
+ private String permissionMessage;
+- public org.spigotmc.CustomTimingsHandler timings; // Spigot
++ public co.aikar.timings.Timing timings; // Spigot
++ public String getTimingName() {return getName();} // Spigot
+
+ protected Command(String name) {
+ this(name, "", "/" + name, new ArrayList());
+@@ -0,0 +0,0 @@ public abstract class Command {
+ this.usageMessage = usageMessage;
+ this.aliases = aliases;
+ this.activeAliases = new ArrayList(aliases);
+- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot
+ }
+
+ /**
+@@ -0,0 +0,0 @@ public abstract class Command {
+ public boolean setLabel(String name) {
+ this.nextLabel = name;
+ if (!isRegistered()) {
+- this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot
+ this.label = name;
+ return true;
+ }
+diff --git a/src/main/java/org/bukkit/command/FormattedCommandAlias.java b/src/main/java/org/bukkit/command/FormattedCommandAlias.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/command/FormattedCommandAlias.java
++++ b/src/main/java/org/bukkit/command/FormattedCommandAlias.java
+@@ -0,0 +0,0 @@ public class FormattedCommandAlias extends Command {
+
+ public FormattedCommandAlias(String alias, String[] formatStrings) {
+ super(alias);
++ timings = co.aikar.timings.TimingsManager.getCommandTiming("minecraft", this); // Spigot
+ this.formatStrings = formatStrings;
+ }
+
+@@ -0,0 +0,0 @@ public class FormattedCommandAlias extends Command {
+ return formatString;
+ }
+
++ @Override // Spigot
++ public String getTimingName() {return "Command Forwarder - " + super.getTimingName();} // Spigot
++
+ private static boolean inRange(int i, int j, int k) {
+ return i >= j && i <= k;
+ }
+diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/command/SimpleCommandMap.java
++++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java
+@@ -0,0 +0,0 @@ public class SimpleCommandMap implements CommandMap {
+ register("bukkit", new VersionCommand("version"));
+ register("bukkit", new ReloadCommand("reload"));
+ register("bukkit", new PluginsCommand("plugins"));
+- register("bukkit", new TimingsCommand("timings"));
++ register("bukkit", new co.aikar.timings.TimingsCommand("timings")); // Spigot
+ }
+
+ public void setFallbackCommands() {
+@@ -0,0 +0,0 @@ public class SimpleCommandMap implements CommandMap {
+ * {@inheritDoc}
+ */
+ public boolean register(String label, String fallbackPrefix, Command command) {
++ command.timings = co.aikar.timings.TimingsManager.getCommandTiming(fallbackPrefix, command); // Spigot
+ label = label.toLowerCase().trim();
+ fallbackPrefix = fallbackPrefix.toLowerCase().trim();
+ boolean registered = register(label, command, false, fallbackPrefix);
+diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java
++++ b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java
+@@ -0,0 +0,0 @@ import org.spigotmc.CustomTimingsHandler;
+ // Spigot end
+
+ public class TimingsCommand extends BukkitCommand {
+- private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "paste"); // Spigot
+- public static long timingStart = 0; // Spigot
++ public static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("merged", "reset", "separate");
+
+ public TimingsCommand(String name) {
+ super(name);
+- this.description = "Manages Spigot Timings data to see performance of the server."; // Spigot
+- this.usageMessage = "/timings "; // Spigot
++ this.description = "Records timings for all plugin events";
++ this.usageMessage = "/timings ";
+ this.setPermission("bukkit.command.timings");
+ }
+
+- // Spigot start - redesigned Timings Command
+- public void executeSpigotTimings(CommandSender sender, String[] args) {
+- if ( "on".equals( args[0] ) )
+- {
+- ( (SimplePluginManager) Bukkit.getPluginManager() ).useTimings( true );
+- CustomTimingsHandler.reload();
+- sender.sendMessage( "Enabled Timings & Reset" );
+- return;
+- } else if ( "off".equals( args[0] ) )
+- {
+- ( (SimplePluginManager) Bukkit.getPluginManager() ).useTimings( false );
+- sender.sendMessage( "Disabled Timings" );
+- return;
+- }
+-
+- if ( !Bukkit.getPluginManager().useTimings() )
+- {
+- sender.sendMessage( "Please enable timings by typing /timings on" );
+- return;
+- }
+-
+- boolean paste = "paste".equals( args[0] );
+- if ("reset".equals(args[0])) {
+- CustomTimingsHandler.reload();
+- sender.sendMessage("Timings reset");
+- } else if ("merged".equals(args[0]) || "report".equals(args[0]) || paste) {
+- long sampleTime = System.nanoTime() - timingStart;
+- int index = 0;
+- File timingFolder = new File("timings");
+- timingFolder.mkdirs();
+- File timings = new File(timingFolder, "timings.txt");
+- ByteArrayOutputStream bout = ( paste ) ? new ByteArrayOutputStream() : null;
+- while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt");
+- PrintStream fileTimings = null;
+- try {
+- fileTimings = ( paste ) ? new PrintStream( bout ) : new PrintStream( timings );
+-
+- CustomTimingsHandler.printTimings(fileTimings);
+- fileTimings.println( "Sample time " + sampleTime + " (" + sampleTime / 1E9 + "s)" );
+-
+- fileTimings.println( "" );
+- fileTimings.println( Bukkit.spigot().getConfig().saveToString() );
+- fileTimings.println( "" );
+-
+- if ( paste )
+- {
+- new PasteThread( sender, bout ).start();
+- return;
+- }
+-
+- sender.sendMessage("Timings written to " + timings.getPath());
+- sender.sendMessage( "Paste contents of file into form at http://aikar.co/timings.php to read results." );
+-
+- } catch (IOException e) {
+- } finally {
+- if (fileTimings != null) {
+- fileTimings.close();
+- }
+- }
+- }
+- }
+- // Spigot end
+-
+ @Override
+ public boolean execute(CommandSender sender, String currentAlias, String[] args) {
+ if (!testPermission(sender)) return true;
+- if (args.length < 1) { // Spigot
++ if (args.length != 1) {
+ sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
+ return false;
+ }
+- if (true) { executeSpigotTimings(sender, args); return true; } // Spigot
+ if (!sender.getServer().getPluginManager().useTimings()) {
+ sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml");
+ return true;
+@@ -0,0 +0,0 @@ public class TimingsCommand extends BukkitCommand {
+ }
+ return ImmutableList.of();
+ }
+-
+- // Spigot start
+- private static class PasteThread extends Thread
+- {
+-
+- private final CommandSender sender;
+- private final ByteArrayOutputStream bout;
+-
+- public PasteThread(CommandSender sender, ByteArrayOutputStream bout)
+- {
+- super( "Timings paste thread" );
+- this.sender = sender;
+- this.bout = bout;
+- }
+-
+- @Override
+- public synchronized void start() {
+- if (sender instanceof RemoteConsoleCommandSender) {
+- run();
+- } else {
+- super.start();
+- }
+- }
+-
+- @Override
+- public void run()
+- {
+- try
+- {
+- HttpURLConnection con = (HttpURLConnection) new URL( "http://paste.ubuntu.com/" ).openConnection();
+- con.setDoOutput( true );
+- con.setRequestMethod( "POST" );
+- con.setInstanceFollowRedirects( false );
+-
+- OutputStream out = con.getOutputStream();
+- out.write( "poster=Spigot&syntax=text&content=".getBytes( "UTF-8" ) );
+- out.write( URLEncoder.encode( bout.toString( "UTF-8" ), "UTF-8" ).getBytes( "UTF-8" ) );
+- out.close();
+- con.getInputStream().close();
+-
+- String location = con.getHeaderField( "Location" );
+- String pasteID = location.substring( "http://paste.ubuntu.com/".length(), location.length() - 1 );
+- sender.sendMessage( ChatColor.GREEN + "Timings results can be viewed at http://aikar.co/timings.php?url=" + pasteID );
+- } catch ( IOException ex )
+- {
+- sender.sendMessage( ChatColor.RED + "Error pasting timings, check your console for more information" );
+- Bukkit.getServer().getLogger().log( Level.WARNING, "Could not paste timings", ex );
+- }
+- }
+- }
+- // Spigot end
+ }
+diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/entity/Player.java
++++ b/src/main/java/org/bukkit/entity/Player.java
+@@ -0,0 +0,0 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline
+ {
+ throw new UnsupportedOperationException( "Not supported yet" );
+ }
++
++ public int getPing()
++ {
++ throw new UnsupportedOperationException( "Not supported yet." );
++ }
+ }
+
+ Spigot spigot();
+diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java
++++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java
+@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
+ }
+ }
+
+- org.bukkit.command.defaults.TimingsCommand.timingStart = System.nanoTime(); // Spigot
+ return result.toArray(new Plugin[result.size()]);
+ }
+
+@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
+
+ if (result != null) {
+ plugins.add(result);
+- lookupNames.put(result.getDescription().getName(), result);
++ lookupNames.put(result.getDescription().getName().toLowerCase(), result); // Spigot
+ }
+
+ return result;
+@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
+ * @return Plugin if it exists, otherwise null
+ */
+ public synchronized Plugin getPlugin(String name) {
+- return lookupNames.get(name.replace(' ', '_'));
++ return lookupNames.get(name.replace(' ', '_').toLowerCase()); // Spigot
+ }
+
+ public synchronized Plugin[] getPlugins() {
+@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
+ throw new IllegalPluginAccessException("Plugin attempted to register " + event + " while not enabled");
+ }
+
+- if (useTimings) {
++ executor = new co.aikar.timings.TimedEventExecutor(executor, plugin, null, event); // Spigot
++ if (false) { // Spigot - RL handles useTimings check now
+ getEventListeners(event).register(new TimedRegisteredListener(listener, executor, priority, plugin, ignoreCancelled));
+ } else {
+ getEventListeners(event).register(new RegisteredListener(listener, executor, priority, plugin, ignoreCancelled));
+@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
+ }
+
+ public boolean useTimings() {
+- return useTimings;
++ return co.aikar.timings.Timings.isTimingsEnabled(); // Spigot
+ }
+
+ /**
+@@ -0,0 +0,0 @@ public final class SimplePluginManager implements PluginManager {
+ * @param use True if per event timing code should be used
+ */
+ public void useTimings(boolean use) {
+- useTimings = use;
++ co.aikar.timings.Timings.setTimingsEnabled(use); // Spigot
+ }
+ }
+diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java
+@@ -0,0 +0,0 @@ import org.bukkit.plugin.PluginLoader;
+ import org.bukkit.plugin.RegisteredListener;
+ import org.bukkit.plugin.TimedRegisteredListener;
+ import org.bukkit.plugin.UnknownDependencyException;
+-import org.spigotmc.CustomTimingsHandler; // Spigot
+ import org.yaml.snakeyaml.error.YAMLException;
+
+ /**
+@@ -0,0 +0,0 @@ public final class JavaPluginLoader implements PluginLoader {
+ private final Pattern[] fileFilters = new Pattern[] { Pattern.compile("\\.jar$"), };
+ private final Map> classes = new java.util.concurrent.ConcurrentHashMap>(); // Spigot
+ private final Map loaders = new LinkedHashMap();
+- public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot
+
+ /**
+ * This class was not meant to be constructed explicitly
+@@ -0,0 +0,0 @@ public final class JavaPluginLoader implements PluginLoader {
+ }
+ }
+
+- final CustomTimingsHandler timings = new CustomTimingsHandler("Plugin: " + plugin.getDescription().getFullName() + " Event: " + listener.getClass().getName() + "::" + method.getName()+"("+eventClass.getSimpleName()+")", pluginParentTimer); // Spigot
+- EventExecutor executor = new EventExecutor() {
++ EventExecutor executor = new co.aikar.timings.TimedEventExecutor(new EventExecutor() { // Spigot
+ public void execute(Listener listener, Event event) throws EventException {
+ try {
+ if (!eventClass.isAssignableFrom(event.getClass())) {
+ return;
+ }
+- // Spigot start
+- boolean isAsync = event.isAsynchronous();
+- if (!isAsync) timings.startTiming();
+ method.invoke(listener, event);
+- if (!isAsync) timings.stopTiming();
+- // Spigot end
+ } catch (InvocationTargetException ex) {
+ throw new EventException(ex.getCause());
+ } catch (Throwable t) {
+ throw new EventException(t);
+ }
+ }
+- };
++ }, plugin, method, eventClass); // Spigot
+ if (false) { // Spigot - RL handles useTimings check now
+ eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled()));
+ } else {
+diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
++++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java
+@@ -0,0 +0,0 @@ import org.bukkit.plugin.PluginDescriptionFile;
+ /**
+ * A ClassLoader for plugins, to allow shared classes across multiple plugins
+ */
+-final class PluginClassLoader extends URLClassLoader {
++public final class PluginClassLoader extends URLClassLoader { // Spigot
++ public JavaPlugin getPlugin() { return plugin; } // Spigot
+ private final JavaPluginLoader loader;
+ private final Map> classes = new java.util.concurrent.ConcurrentHashMap>(); // Spigot
+ private final PluginDescriptionFile description;
+diff --git a/src/main/java/org/bukkit/util/CachedServerIcon.java b/src/main/java/org/bukkit/util/CachedServerIcon.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/bukkit/util/CachedServerIcon.java
++++ b/src/main/java/org/bukkit/util/CachedServerIcon.java
+@@ -0,0 +0,0 @@ import org.bukkit.event.server.ServerListPingEvent;
+ * @see Server#loadServerIcon(java.io.File)
+ * @see ServerListPingEvent#setServerIcon(CachedServerIcon)
+ */
+-public interface CachedServerIcon {}
++public interface CachedServerIcon {
++ public String getData(); // Spigot
++}
+diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+--- a/src/main/java/org/spigotmc/CustomTimingsHandler.java
++++ b/src/main/java/org/spigotmc/CustomTimingsHandler.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 org.spigotmc;
+
+-import org.bukkit.command.defaults.TimingsCommand;
+-import org.bukkit.event.HandlerList;
++import org.bukkit.Bukkit;
++import org.bukkit.plugin.AuthorNagException;
+ import org.bukkit.plugin.Plugin;
+-import org.bukkit.plugin.RegisteredListener;
+-import org.bukkit.plugin.TimedRegisteredListener;
+-import java.io.PrintStream;
+-import java.util.Collection;
+-import java.util.HashSet;
+-import java.util.List;
+-import java.util.Queue;
+-import java.util.concurrent.ConcurrentLinkedQueue;
++import co.aikar.timings.NullTimingHandler;
++import co.aikar.timings.Timing;
++import co.aikar.timings.Timings;
++import co.aikar.timings.TimingsManager;
++import sun.reflect.Reflection;
+
+-import org.bukkit.Bukkit;
+-import org.bukkit.World;
++import java.lang.reflect.Method;
++import java.util.logging.Level;
+
+ /**
+- * Provides custom timing sections for /timings merged.
++ * This is here for legacy purposes incase any plugin used it.
++ *
++ * If you use this, migrate ASAP as this will be removed in the future!
++ *
++ * @deprecated
++ * @see co.aikar.timings.Timings#of
+ */
+-public class CustomTimingsHandler
+-{
++@Deprecated
++public final class CustomTimingsHandler {
++ private final Timing handler;
+
+- private static Queue HANDLERS = new ConcurrentLinkedQueue();
+- /*========================================================================*/
+- private final String name;
+- private final CustomTimingsHandler parent;
+- private long count = 0;
+- private long start = 0;
+- private long timingDepth = 0;
+- private long totalTime = 0;
+- private long curTickTotal = 0;
+- private long violations = 0;
++ public CustomTimingsHandler(String name) {
++ Timing timing;
+
+- public CustomTimingsHandler(String name)
+- {
+- this( name, null );
+- }
++ Plugin plugin = null;
++ try {
++ plugin = TimingsManager.getPluginByClassloader(Reflection.getCallerClass(2));
++ } catch (Exception ignored) {}
+
+- public CustomTimingsHandler(String name, CustomTimingsHandler parent)
+- {
+- this.name = name;
+- this.parent = parent;
+- HANDLERS.add( this );
+- }
+-
+- /**
+- * Prints the timings and extra data to the given stream.
+- *
+- * @param printStream
+- */
+- public static void printTimings(PrintStream printStream)
+- {
+- printStream.println( "Minecraft" );
+- for ( CustomTimingsHandler timings : HANDLERS )
+- {
+- long time = timings.totalTime;
+- long count = timings.count;
+- if ( count == 0 )
+- {
+- continue;
++ new AuthorNagException("Deprecated use of CustomTimingsHandler. Please Switch to Timings.of ASAP").printStackTrace();
++ if (plugin != null) {
++ timing = Timings.of(plugin, "(Deprecated API) " + name);
++ } else {
++ try {
++ final Method ofSafe = TimingsManager.class.getMethod("getHandler", String.class, String.class, Timing.class, boolean.class);
++ timing = (Timing) ofSafe.invoke("Minecraft", "(Deprecated API) " + name, null, true);
++ } catch (Exception e) {
++ Bukkit.getLogger().log(Level.SEVERE, "This handler could not be registered");
++ timing = Timings.NULL_HANDLER;
+ }
+- long avg = time / count;
+-
+- printStream.println( " " + timings.name + " Time: " + time + " Count: " + count + " Avg: " + avg + " Violations: " + timings.violations );
+ }
+- printStream.println( "# Version " + Bukkit.getVersion() );
+- int entities = 0;
+- int livingEntities = 0;
+- for ( World world : Bukkit.getWorlds() )
+- {
+- entities += world.getEntities().size();
+- livingEntities += world.getLivingEntities().size();
+- }
+- printStream.println( "# Entities " + entities );
+- printStream.println( "# LivingEntities " + livingEntities );
++ handler = timing;
+ }
+
+- /**
+- * Resets all timings.
+- */
+- public static void reload()
+- {
+- if ( Bukkit.getPluginManager().useTimings() )
+- {
+- for ( CustomTimingsHandler timings : HANDLERS )
+- {
+- timings.reset();
+- }
+- }
+- TimingsCommand.timingStart = System.nanoTime();
+- }
++ public void startTiming() { handler.startTiming(); }
++ public void stopTiming() { handler.stopTiming(); }
+
+- /**
+- * Ticked every tick by CraftBukkit to count the number of times a timer
+- * caused TPS loss.
+- */
+- public static void tick()
+- {
+- if ( Bukkit.getPluginManager().useTimings() )
+- {
+- for ( CustomTimingsHandler timings : HANDLERS )
+- {
+- if ( timings.curTickTotal > 50000000 )
+- {
+- timings.violations += Math.ceil( timings.curTickTotal / 50000000 );
+- }
+- timings.curTickTotal = 0;
+- timings.timingDepth = 0; // incase reset messes this up
+- }
+- }
+- }
+-
+- /**
+- * Starts timing to track a section of code.
+- */
+- public void startTiming()
+- {
+- // If second condtion fails we are already timing
+- if ( Bukkit.getPluginManager().useTimings() && ++timingDepth == 1 )
+- {
+- start = System.nanoTime();
+- if ( parent != null && ++parent.timingDepth == 1 )
+- {
+- parent.start = start;
+- }
+- }
+- }
+-
+- /**
+- * Stops timing a section of code.
+- */
+- public void stopTiming()
+- {
+- if ( Bukkit.getPluginManager().useTimings() )
+- {
+- if ( --timingDepth != 0 || start == 0 )
+- {
+- return;
+- }
+- long diff = System.nanoTime() - start;
+- totalTime += diff;
+- curTickTotal += diff;
+- count++;
+- start = 0;
+- if ( parent != null )
+- {
+- parent.stopTiming();
+- }
+- }
+- }
+-
+- /**
+- * Reset this timer, setting all values to zero.
+- */
+- public void reset()
+- {
+- count = 0;
+- violations = 0;
+- curTickTotal = 0;
+- totalTime = 0;
+- start = 0;
+- timingDepth = 0;
+- }
+ }
--
\ No newline at end of file
diff --git a/Spigot-Server-Patches/Timings-v2.patch b/Spigot-Server-Patches/Timings-v2.patch
index cd60ea947b..4487fe407b 100644
--- a/Spigot-Server-Patches/Timings-v2.patch
+++ b/Spigot-Server-Patches/Timings-v2.patch
@@ -4,6 +4,197 @@ Date: Fri, 8 Jan 2016 23:36:39 -0600
Subject: [PATCH] Timings v2
+diff --git a/src/main/java/co/aikar/timings/SpigotTimings.java b/src/main/java/co/aikar/timings/SpigotTimings.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
+--- /dev/null
++++ b/src/main/java/co/aikar/timings/SpigotTimings.java
+@@ -0,0 +0,0 @@
++package co.aikar.timings;
++
++import net.minecraft.server.*;
++import org.bukkit.plugin.Plugin;
++import org.bukkit.scheduler.BukkitTask;
++
++import org.bukkit.craftbukkit.scheduler.CraftTask;
++
++public final class SpigotTimings {
++
++ public static final Timing playerListTimer = Timings.ofSafe("Player List");
++ public static final Timing connectionTimer = Timings.ofSafe("Connection Handler");
++ public static final Timing tickablesTimer = Timings.ofSafe("Tickables");
++ public static final Timing schedulerTimer = Timings.ofSafe("Scheduler");
++ 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 worldSaveTimer = Timings.ofSafe("World Save");
++
++ public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity");
++ public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity");
++
++ public static final Timing processQueueTimer = Timings.ofSafe("processQueue");
++
++ public static final Timing playerCommandTimer = Timings.ofSafe("playerCommand");
++
++ public static final Timing entityActivationCheckTimer = Timings.ofSafe("entityActivationCheck");
++ public static final Timing checkIfActiveTimer = Timings.ofSafe("checkIfActive");
++
++ public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update");
++ public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate");
++
++ private SpigotTimings() {}
++
++ /**
++ * 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 null;
++ }
++ Plugin plugin;
++
++ Runnable task = ((CraftTask) bukkitTask).task;
++
++ final Class extends Runnable> taskClass = task.getClass();
++ if (bukkitTask.getOwner() != null) {
++ plugin = bukkitTask.getOwner();
++ } else {
++ plugin = TimingsManager.getPluginByClassloader(taskClass);
++ }
++
++ final String taskname;
++ if (taskClass.isAnonymousClass()) {
++ taskname = taskClass.getName();
++ } else {
++ taskname = taskClass.getCanonicalName();
++ }
++
++ String name = "Task: " +taskname;
++ if (period > 0) {
++ name += " (interval:" + period +")";
++ } else {
++ name += " (Single)";
++ }
++
++ if (plugin == null) {
++ return Timings.ofSafe(null, name, TimingsManager.PLUGIN_GROUP_HANDLER);
++ }
++
++ return Timings.ofSafe(plugin, name);
++ }
++
++ /**
++ * Get a named timer for the specified entity type to track type specific timings.
++ * @param entity
++ * @return
++ */
++ public static Timing getEntityTimings(Entity entity) {
++ String entityType = entity.getClass().getName();
++ return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType, tickEntityTimer);
++ }
++
++ /**
++ * Get a named timer for the specified tile entity type to track type specific timings.
++ * @param entity
++ * @return
++ */
++ public static Timing getTileEntityTimings(TileEntity 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.getName());
++ }
++}
+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.World;
++
++/**
++ * Set of timers per world, to track world specific timings.
++ */
++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 chunkTicksBlocks;
++ public final Timing doVillages;
++ public final Timing doChunkMap;
++ 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 tracker;
++ public final Timing doTick;
++ public final Timing tickEntities;
++
++ public final Timing syncChunkLoadTimer;
++ public final Timing syncChunkLoadDataTimer;
++ public final Timing syncChunkLoadStructuresTimer;
++ public final Timing syncChunkLoadEntitiesTimer;
++ public final Timing syncChunkLoadTileEntitiesTimer;
++ public final Timing syncChunkLoadTileTicksTimer;
++ public final Timing syncChunkLoadPostTimer;
++
++ public WorldTimingsHandler(World server) {
++ String name = server.worldData.getName() +" - ";
++
++ 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");
++ chunkTicksBlocks = Timings.ofSafe(name + "Chunk Ticks - Blocks");
++ doVillages = Timings.ofSafe(name + "doVillages");
++ doChunkMap = Timings.ofSafe(name + "doChunkMap");
++ 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");
++
++ syncChunkLoadTimer = Timings.ofSafe(name + "syncChunkLoad");
++ syncChunkLoadDataTimer = Timings.ofSafe(name + "syncChunkLoad - Data");
++ syncChunkLoadStructuresTimer = Timings.ofSafe(name + "chunkLoad - Structures");
++ syncChunkLoadEntitiesTimer = Timings.ofSafe(name + "chunkLoad - Entities");
++ syncChunkLoadTileEntitiesTimer = Timings.ofSafe(name + "chunkLoad - TileEntities");
++ syncChunkLoadTileTicksTimer = Timings.ofSafe(name + "chunkLoad - TileTicks");
++ syncChunkLoadPostTimer = Timings.ofSafe(name + "chunkLoad - Post");
++
++ tracker = Timings.ofSafe(name + "tracker");
++ doTick = Timings.ofSafe(name + "doTick");
++ tickEntities = Timings.ofSafe(name + "tickEntities");
++ }
++}
diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java
index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
--- a/src/main/java/net/minecraft/server/Block.java
@@ -13,10 +204,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected boolean z;
protected boolean isTileEntity;
+ // Spigot start
-+ public org.spigotmc.timings.Timing timing;
-+ public org.spigotmc.timings.Timing getTiming() {
++ public co.aikar.timings.Timing timing;
++ public co.aikar.timings.Timing getTiming() {
+ if (timing == null) {
-+ timing = org.spigotmc.timings.SpigotTimings.getBlockTiming(this);
++ timing = co.aikar.timings.SpigotTimings.getBlockTiming(this);
+ }
+ return timing;
+ }
@@ -34,7 +225,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import org.bukkit.craftbukkit.LoggerOutputStream;
-import org.bukkit.craftbukkit.SpigotTimings; // Spigot
-+import org.spigotmc.timings.SpigotTimings; // Spigot
++import co.aikar.timings.SpigotTimings; // Spigot
import org.bukkit.event.server.ServerCommandEvent;
import org.bukkit.craftbukkit.util.Waitable;
import org.bukkit.event.server.RemoteServerCommandEvent;
@@ -47,8 +238,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import org.bukkit.entity.Painting;
import org.bukkit.entity.Vehicle;
-import org.spigotmc.CustomTimingsHandler; // Spigot
-+import org.spigotmc.timings.SpigotTimings; // Spigot
-+import org.spigotmc.timings.Timing; // Spigot
++import co.aikar.timings.SpigotTimings; // Spigot
++import co.aikar.timings.Timing; // Spigot
import org.bukkit.event.entity.EntityCombustByEntityEvent;
import org.bukkit.event.hanging.HangingBreakByEntityEvent;
import org.bukkit.event.painting.PaintingBreakByEntityEvent;
@@ -86,7 +277,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// CraftBukkit end
-import org.bukkit.craftbukkit.SpigotTimings; // Spigot
-+import org.spigotmc.timings.SpigotTimings; // Spigot
++import co.aikar.timings.SpigotTimings; // Spigot
public abstract class EntityLiving extends Entity {
@@ -157,7 +348,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import org.bukkit.craftbukkit.Main;
-import org.bukkit.craftbukkit.SpigotTimings; // Spigot
-+import org.spigotmc.timings.SpigotTimings; // Spigot
++import co.aikar.timings.SpigotTimings; // Spigot
// CraftBukkit end
public abstract class MinecraftServer implements Runnable, ICommandListener, IAsyncTaskHandler, IMojangStatistics {
@@ -175,7 +366,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
protected void A() throws ExceptionWorldConflict { // CraftBukkit - added throws
- SpigotTimings.serverTickTimer.startTiming(); // Spigot
-+ org.spigotmc.timings.TimingsManager.FULL_SERVER_TICK.startTiming(); // Spigot
++ co.aikar.timings.TimingsManager.FULL_SERVER_TICK.startTiming(); // Spigot
long i = System.nanoTime();
++this.ticks;
@@ -185,7 +376,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
org.spigotmc.WatchdogThread.tick(); // Spigot
- SpigotTimings.serverTickTimer.stopTiming(); // Spigot
- org.spigotmc.CustomTimingsHandler.tick(); // Spigot
-+ org.spigotmc.timings.TimingsManager.FULL_SERVER_TICK.stopTiming(); // Spigot
++ co.aikar.timings.TimingsManager.FULL_SERVER_TICK.stopTiming(); // Spigot
}
public void B() {
@@ -197,7 +388,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import org.bukkit.inventory.CraftingInventory;
import org.bukkit.inventory.InventoryView;
import org.bukkit.util.NumberConversions;
-+import org.spigotmc.timings.SpigotTimings; // Spigot
++import co.aikar.timings.SpigotTimings; // Spigot
// CraftBukkit end
import org.github.paperspigot.PaperSpigotConfig; // PaperSpigot
@@ -246,8 +437,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import org.apache.logging.log4j.Logger;
-import org.spigotmc.CustomTimingsHandler; // Spigot
-+import org.spigotmc.timings.SpigotTimings; // Spigot
-+import org.spigotmc.timings.Timing; // Spigot
++import co.aikar.timings.SpigotTimings; // Spigot
++import co.aikar.timings.Timing; // Spigot
import org.bukkit.inventory.InventoryHolder; // CraftBukkit
public abstract class TileEntity {
@@ -273,7 +464,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
import org.bukkit.generator.ChunkGenerator;
-+import org.spigotmc.timings.SpigotTimings;
++import co.aikar.timings.SpigotTimings;
import java.util.*;
import java.util.concurrent.Callable;
@@ -282,7 +473,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
public final org.github.paperspigot.PaperSpigotWorldConfig paperSpigotConfig; // PaperSpigot
- public final SpigotTimings.WorldTimingsHandler timings; // Spigot
-+ public final org.spigotmc.timings.WorldTimingsHandler timings; // Spigot
++ public final co.aikar.timings.WorldTimingsHandler timings; // Spigot
public CraftWorld getWorld() {
return this.world;
@@ -291,7 +482,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
// CraftBukkit end
this.keepSpawnInMemory = this.paperSpigotConfig.keepSpawnInMemory; // PaperSpigot
- timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings
-+ timings = new org.spigotmc.timings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings
++ timings = new co.aikar.timings.WorldTimingsHandler(this); // Spigot - code below can generate new world and access timings
this.entityLimiter = new org.spigotmc.TickLimiter(spigotConfig.entityMaxTickTime);
this.tileLimiter = new org.spigotmc.TickLimiter(spigotConfig.tileMaxTickTime);
}
@@ -314,7 +505,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
timings.entityTick.startTiming(); // Spigot
guardEntityList = true; // Spigot
// CraftBukkit start - Use field for loop variable
-+ org.spigotmc.timings.TimingHistory.entityTicks += this.entityList.size(); // Spigot
++ co.aikar.timings.TimingHistory.entityTicks += this.entityList.size(); // Spigot
int entitiesThisCycle = 0;
// PaperSpigot start - Disable tick limiters
//if (tickPosition < 0) tickPosition = 0;
@@ -338,7 +529,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
timings.tileEntityPending.stopTiming(); // Spigot
-+ org.spigotmc.timings.TimingHistory.tileEntityTicks += this.tileEntityList.size(); // Spigot
++ co.aikar.timings.TimingHistory.tileEntityTicks += this.tileEntityList.size(); // Spigot
+
this.methodProfiler.b();
this.methodProfiler.b();
@@ -355,7 +546,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
entity.lastPitch = entity.pitch;
if (flag && entity.ad) {
++entity.ticksLived;
-+ ++org.spigotmc.timings.TimingHistory.activatedEntityTicks; // Spigot
++ ++co.aikar.timings.TimingHistory.activatedEntityTicks; // Spigot
if (entity.vehicle != null) {
entity.ak();
} else {
@@ -433,7 +624,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
if (this.areChunksLoadedBetween(nextticklistentry.a.a(-b0, -b0, -b0), nextticklistentry.a.a(b0, b0, b0))) {
IBlockData iblockdata = this.getType(nextticklistentry.a);
-+ org.spigotmc.timings.Timing timing = iblockdata.getBlock().getTiming(); // Spigot
++ co.aikar.timings.Timing timing = iblockdata.getBlock().getTiming(); // Spigot
+ timing.startTiming(); // Spigot
if (iblockdata.getBlock().getMaterial() != Material.AIR && Block.a(iblockdata.getBlock(), nextticklistentry.a())) {
@@ -459,7 +650,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
DefaultPermissions.registerCorePermissions();
CraftDefaultPermissions.registerCorePermissions();
helpMap.initializeCommands();
-+ org.spigotmc.timings.Timings.reset(); // Spigot
++ co.aikar.timings.Timings.reset(); // Spigot
}
}
@@ -701,7 +892,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
return false;
- }});
-+ }}){{this.timings=org.spigotmc.timings.SpigotTimings.getCancelTasksTimer();}}; // Spigot
++ }}){{this.timings=co.aikar.timings.SpigotTimings.getCancelTasksTimer();}}; // Spigot
handle(task, 0l);
for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) {
if (taskPending == task) {
@@ -710,7 +901,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
}
}
- });
-+ }){{this.timings=org.spigotmc.timings.SpigotTimings.getCancelTasksTimer(plugin);}}; // Spigot
++ }){{this.timings=co.aikar.timings.SpigotTimings.getCancelTasksTimer(plugin);}}; // Spigot
handle(task, 0l);
for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) {
if (taskPending == task) {
@@ -719,7 +910,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
CraftScheduler.this.temp.clear();
}
- });
-+ }){{this.timings=org.spigotmc.timings.SpigotTimings.getCancelTasksTimer();}}; // Spigot
++ }){{this.timings=co.aikar.timings.SpigotTimings.getCancelTasksTimer();}}; // Spigot
handle(task, 0l);
for (CraftTask taskPending = head.getNext(); taskPending != null; taskPending = taskPending.getNext()) {
if (taskPending == task) {
@@ -743,8 +934,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import org.bukkit.Bukkit;
-import org.bukkit.craftbukkit.SpigotTimings; // Spigot
-import org.spigotmc.CustomTimingsHandler; // Spigot
-+import org.spigotmc.timings.SpigotTimings; // Spigot
-+import org.spigotmc.timings.Timing; // Spigot
++import co.aikar.timings.SpigotTimings; // Spigot
++import co.aikar.timings.Timing; // Spigot
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitTask;
@@ -835,7 +1026,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import net.minecraft.server.World;
-import org.bukkit.craftbukkit.SpigotTimings;
-import org.bukkit.entity.Creeper;
-+import org.spigotmc.timings.SpigotTimings;
++import co.aikar.timings.SpigotTimings;
+
public class ActivationRange
@@ -848,7 +1039,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import net.minecraft.server.Blocks;
import net.minecraft.server.World;
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
-+import org.spigotmc.timings.SpigotTimings;
++import co.aikar.timings.SpigotTimings;
// PaperSpigot start
import java.util.HashSet;
@@ -905,8 +1096,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
-+import org.spigotmc.timings.Timings;
-+import org.spigotmc.timings.TimingsManager;
++import co.aikar.timings.Timings;
++import co.aikar.timings.TimingsManager;
public class SpigotConfig
{
@@ -950,195 +1141,4 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
private static void nettyThreads()
{
int count = getInt( "settings.netty-threads", 4 );
-diff --git a/src/main/java/org/spigotmc/timings/SpigotTimings.java b/src/main/java/org/spigotmc/timings/SpigotTimings.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/SpigotTimings.java
-@@ -0,0 +0,0 @@
-+package org.spigotmc.timings;
-+
-+import net.minecraft.server.*;
-+import org.bukkit.plugin.Plugin;
-+import org.bukkit.scheduler.BukkitTask;
-+
-+import org.bukkit.craftbukkit.scheduler.CraftTask;
-+
-+public final class SpigotTimings {
-+
-+ public static final Timing playerListTimer = Timings.ofSafe("Player List");
-+ public static final Timing connectionTimer = Timings.ofSafe("Connection Handler");
-+ public static final Timing tickablesTimer = Timings.ofSafe("Tickables");
-+ public static final Timing schedulerTimer = Timings.ofSafe("Scheduler");
-+ 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 worldSaveTimer = Timings.ofSafe("World Save");
-+
-+ public static final Timing tickEntityTimer = Timings.ofSafe("## tickEntity");
-+ public static final Timing tickTileEntityTimer = Timings.ofSafe("## tickTileEntity");
-+
-+ public static final Timing processQueueTimer = Timings.ofSafe("processQueue");
-+
-+ public static final Timing playerCommandTimer = Timings.ofSafe("playerCommand");
-+
-+ public static final Timing entityActivationCheckTimer = Timings.ofSafe("entityActivationCheck");
-+ public static final Timing checkIfActiveTimer = Timings.ofSafe("checkIfActive");
-+
-+ public static final Timing antiXrayUpdateTimer = Timings.ofSafe("anti-xray - update");
-+ public static final Timing antiXrayObfuscateTimer = Timings.ofSafe("anti-xray - obfuscate");
-+
-+ private SpigotTimings() {}
-+
-+ /**
-+ * 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 null;
-+ }
-+ Plugin plugin;
-+
-+ Runnable task = ((CraftTask) bukkitTask).task;
-+
-+ final Class extends Runnable> taskClass = task.getClass();
-+ if (bukkitTask.getOwner() != null) {
-+ plugin = bukkitTask.getOwner();
-+ } else {
-+ plugin = TimingsManager.getPluginByClassloader(taskClass);
-+ }
-+
-+ final String taskname;
-+ if (taskClass.isAnonymousClass()) {
-+ taskname = taskClass.getName();
-+ } else {
-+ taskname = taskClass.getCanonicalName();
-+ }
-+
-+ String name = "Task: " +taskname;
-+ if (period > 0) {
-+ name += " (interval:" + period +")";
-+ } else {
-+ name += " (Single)";
-+ }
-+
-+ if (plugin == null) {
-+ return Timings.ofSafe(null, name, TimingsManager.PLUGIN_GROUP_HANDLER);
-+ }
-+
-+ return Timings.ofSafe(plugin, name);
-+ }
-+
-+ /**
-+ * Get a named timer for the specified entity type to track type specific timings.
-+ * @param entity
-+ * @return
-+ */
-+ public static Timing getEntityTimings(Entity entity) {
-+ String entityType = entity.getClass().getName();
-+ return Timings.ofSafe("Minecraft", "## tickEntity - " + entityType, tickEntityTimer);
-+ }
-+
-+ /**
-+ * Get a named timer for the specified tile entity type to track type specific timings.
-+ * @param entity
-+ * @return
-+ */
-+ public static Timing getTileEntityTimings(TileEntity 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.getName());
-+ }
-+}
-diff --git a/src/main/java/org/spigotmc/timings/WorldTimingsHandler.java b/src/main/java/org/spigotmc/timings/WorldTimingsHandler.java
-new file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
---- /dev/null
-+++ b/src/main/java/org/spigotmc/timings/WorldTimingsHandler.java
-@@ -0,0 +0,0 @@
-+package org.spigotmc.timings;
-+
-+import net.minecraft.server.World;
-+
-+/**
-+ * Set of timers per world, to track world specific timings.
-+ */
-+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 chunkTicksBlocks;
-+ public final Timing doVillages;
-+ public final Timing doChunkMap;
-+ 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 tracker;
-+ public final Timing doTick;
-+ public final Timing tickEntities;
-+
-+ public final Timing syncChunkLoadTimer;
-+ public final Timing syncChunkLoadDataTimer;
-+ public final Timing syncChunkLoadStructuresTimer;
-+ public final Timing syncChunkLoadEntitiesTimer;
-+ public final Timing syncChunkLoadTileEntitiesTimer;
-+ public final Timing syncChunkLoadTileTicksTimer;
-+ public final Timing syncChunkLoadPostTimer;
-+
-+ public WorldTimingsHandler(World server) {
-+ String name = server.worldData.getName() +" - ";
-+
-+ 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");
-+ chunkTicksBlocks = Timings.ofSafe(name + "Chunk Ticks - Blocks");
-+ doVillages = Timings.ofSafe(name + "doVillages");
-+ doChunkMap = Timings.ofSafe(name + "doChunkMap");
-+ 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");
-+
-+ syncChunkLoadTimer = Timings.ofSafe(name + "syncChunkLoad");
-+ syncChunkLoadDataTimer = Timings.ofSafe(name + "syncChunkLoad - Data");
-+ syncChunkLoadStructuresTimer = Timings.ofSafe(name + "chunkLoad - Structures");
-+ syncChunkLoadEntitiesTimer = Timings.ofSafe(name + "chunkLoad - Entities");
-+ syncChunkLoadTileEntitiesTimer = Timings.ofSafe(name + "chunkLoad - TileEntities");
-+ syncChunkLoadTileTicksTimer = Timings.ofSafe(name + "chunkLoad - TileTicks");
-+ syncChunkLoadPostTimer = Timings.ofSafe(name + "chunkLoad - Post");
-+
-+ tracker = Timings.ofSafe(name + "tracker");
-+ doTick = Timings.ofSafe(name + "doTick");
-+ tickEntities = Timings.ofSafe(name + "tickEntities");
-+ }
-+}
--
\ No newline at end of file