diff --git a/Spigot-API-Patches/Timings-v2.patch b/Spigot-API-Patches/Timings-v2.patch
index 869a3c073e..6c81ecccf7 100644
--- a/Spigot-API-Patches/Timings-v2.patch
+++ b/Spigot-API-Patches/Timings-v2.patch
@@ -6,7 +6,7 @@ Subject: [PATCH] Timings v2
 
 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
+index 00000000..4d8b633e
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/FullServerTickHandler.java
 @@ -0,0 +0,0 @@
@@ -85,6 +85,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +            TimingsManager.HISTORY.add(new TimingHistory());
 +            TimingsManager.resetTimings();
 +        }
++        TimingsExport.reportTimings();
 +    }
 +
 +    boolean isViolated() {
@@ -93,7 +94,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..8c43e206
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/NullTimingHandler.java
 @@ -0,0 +0,0 @@
@@ -160,7 +161,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..96057fc7
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimedEventExecutor.java
 @@ -0,0 +0,0 @@
@@ -247,7 +248,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..8b2d1b82
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/Timing.java
 @@ -0,0 +0,0 @@
@@ -325,7 +326,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..f222d6b7
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingData.java
 @@ -0,0 +0,0 @@
@@ -451,7 +452,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..916b6f9d
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingHandler.java
 @@ -0,0 +0,0 @@
@@ -666,7 +667,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..389875b3
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingHistory.java
 @@ -0,0 +0,0 @@
@@ -1014,7 +1015,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..0e114eb3
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingHistoryEntry.java
 @@ -0,0 +0,0 @@
@@ -1075,7 +1076,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..623dda49
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingIdentifier.java
 @@ -0,0 +0,0 @@
@@ -1183,7 +1184,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..483e3669
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/Timings.java
 @@ -0,0 +0,0 @@
@@ -1221,7 +1222,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import java.util.Queue;
 +import java.util.logging.Level;
 +
-+@SuppressWarnings("UnusedDeclaration")
++@SuppressWarnings({"UnusedDeclaration", "WeakerAccess", "SameParameterValue"})
 +public final class Timings {
 +
 +    private static final int MAX_HISTORY_FRAMES = 12;
@@ -1430,7 +1431,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +        if (sender == null) {
 +            sender = Bukkit.getConsoleSender();
 +        }
-+        TimingsExport.reportTimings(sender);
++        // Schedule report for end of tick
++        TimingsExport.requestingReport.add(sender);
 +    }
 +
 +    /*
@@ -1462,7 +1464,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..56b10e89
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingsCommand.java
 @@ -0,0 +0,0 @@
@@ -1565,7 +1567,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +                "merged".equalsIgnoreCase(arg) ||
 +                "separate".equalsIgnoreCase(arg)
 +            ) {
-+            TimingsExport.reportTimings(sender);
++            Timings.generateReport(sender);
 +        } else {
 +            sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage);
 +        }
@@ -1587,7 +1589,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..9dd36419
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingsExport.java
 @@ -0,0 +0,0 @@
@@ -1617,6 +1619,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +package co.aikar.timings;
 +
 +import com.google.common.base.Function;
++import com.google.common.collect.Lists;
 +import com.google.common.collect.Sets;
 +import org.apache.commons.lang.StringUtils;
 +import org.bukkit.Bukkit;
@@ -1624,6 +1627,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +import org.bukkit.Material;
 +import org.bukkit.command.CommandSender;
 +import org.bukkit.command.ConsoleCommandSender;
++import org.bukkit.command.MultiMessageCommandSender;
 +import org.bukkit.command.RemoteConsoleCommandSender;
 +import org.bukkit.configuration.ConfigurationSection;
 +import org.bukkit.configuration.MemorySection;
@@ -1658,6 +1662,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    private final Map out;
 +    private final TimingHistory[] history;
 +    private static long lastReport = 0;
++    final static List<CommandSender> requestingReport = Lists.newArrayList();
 +
 +    private TimingsExport(CommandSender sender, Map out, TimingHistory[] history) {
 +        super("Timings paste thread");
@@ -1667,11 +1672,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +
 +    /**
-+     * Builds an XML report of the timings to be uploaded for parsing.
-+     *
-+     * @param sender Who to report to
++     * Checks if any pending reports are being requested, and builds one if needed.
 +     */
-+    static void reportTimings(CommandSender sender) {
++    static void reportTimings() {
++        if (requestingReport.isEmpty()) {
++            return;
++        }
++        CommandSender sender = new MultiMessageCommandSender(requestingReport);
++        requestingReport.clear();
 +        long now = System.currentTimeMillis();
 +        final long lastReportDiff = now - lastReport;
 +        if (lastReportDiff < 60000) {
@@ -1981,7 +1989,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..58ed35e0
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/TimingsManager.java
 @@ -0,0 +0,0 @@
@@ -2183,7 +2191,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..5edaba12
 --- /dev/null
 +++ b/src/main/java/co/aikar/timings/UnsafeTimingHandler.java
 @@ -0,0 +0,0 @@
@@ -2240,7 +2248,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..5fdf7c4c
 --- /dev/null
 +++ b/src/main/java/co/aikar/util/JSONUtil.java
 @@ -0,0 +0,0 @@
@@ -2369,7 +2377,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..79fa9d52
 --- /dev/null
 +++ b/src/main/java/co/aikar/util/LoadingIntMap.java
 @@ -0,0 +0,0 @@
@@ -2445,7 +2453,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..a9f29199
 --- /dev/null
 +++ b/src/main/java/co/aikar/util/LoadingMap.java
 @@ -0,0 +0,0 @@
@@ -2783,7 +2791,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +}
 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
+index 00000000..3a288d2a
 --- /dev/null
 +++ b/src/main/java/co/aikar/util/MRUMapCache.java
 @@ -0,0 +0,0 @@
@@ -2888,7 +2896,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    }
 +}
 diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+index 5b6413be..7fd544eb 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 {
@@ -2900,7 +2908,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      /**
 diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+index 120dba25..77cfe561 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 {
@@ -2933,7 +2941,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
           * 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
+index 08a9739f..347d2189 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 {
@@ -2963,7 +2971,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              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
+index 3f07d7f4..f89ad075 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 {
@@ -2984,8 +2992,128 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      private static boolean inRange(int i, int j, int k) {
          return i >= j && i <= k;
      }
+diff --git a/src/main/java/org/bukkit/command/MultiMessageCommandSender.java b/src/main/java/org/bukkit/command/MultiMessageCommandSender.java
+new file mode 100644
+index 00000000..7b512fd4
+--- /dev/null
++++ b/src/main/java/org/bukkit/command/MultiMessageCommandSender.java
+@@ -0,0 +0,0 @@
++package org.bukkit.command;
++
++import com.google.common.collect.Lists;
++import org.apache.commons.lang.NotImplementedException;
++import org.apache.commons.lang.Validate;
++import org.bukkit.Bukkit;
++import org.bukkit.Server;
++import org.bukkit.permissions.Permission;
++import org.bukkit.permissions.PermissionAttachment;
++import org.bukkit.permissions.PermissionAttachmentInfo;
++import org.bukkit.plugin.Plugin;
++
++import java.util.List;
++import java.util.Set;
++
++/**
++ * Used for proxying messages to multiple senders.
++ * Do not use this for anything else but messages.
++ */
++public class MultiMessageCommandSender implements CommandSender {
++    private final List<CommandSender> senders;
++
++    public MultiMessageCommandSender(List<CommandSender> senders) {
++        Validate.notNull(senders);
++        Validate.notEmpty(senders);
++
++        this.senders = Lists.newArrayList(senders);
++    }
++
++    @Override
++    public void sendMessage(String message) {
++        senders.forEach((sender) -> sender.sendMessage(message));
++    }
++
++    @Override
++    public void sendMessage(String[] messages) {
++        senders.forEach((sender) -> sender.sendMessage(messages));
++    }
++
++    @Override
++    public Server getServer() {
++        return Bukkit.getServer();
++    }
++
++    @Override
++    public String getName() {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public boolean isOp() {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public void setOp(boolean value) {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public boolean isPermissionSet(String name) {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public boolean isPermissionSet(Permission perm) {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public boolean hasPermission(String name) {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public boolean hasPermission(Permission perm) {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value) {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public PermissionAttachment addAttachment(Plugin plugin) {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public PermissionAttachment addAttachment(Plugin plugin, String name, boolean value, int ticks) {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public PermissionAttachment addAttachment(Plugin plugin, int ticks) {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public void removeAttachment(PermissionAttachment attachment) {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public void recalculatePermissions() {
++        throw new NotImplementedException();
++    }
++
++    @Override
++    public Set<PermissionAttachmentInfo> getEffectivePermissions() {
++        throw new NotImplementedException();
++    }
++}
 diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644
+index 5965514a..466757b9 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 {
@@ -3020,7 +3148,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
              // Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false)
 diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java
 deleted file mode 100644
-index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000
+index a8f61f2d..00000000
 --- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java
 +++ /dev/null
 @@ -0,0 +0,0 @@
@@ -3278,7 +3406,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 -    // 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
+index 5a2dc327..5fbad9f5 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
@@ -3294,7 +3422,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
  
      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
+index 10561864..4ee123e4 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 {
@@ -3351,7 +3479,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      }
  }
 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
+index 80c6a72e..759c4617 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;
@@ -3400,7 +3528,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
                  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
+index 4cffa137..b2cbf9e4 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;
@@ -3414,7 +3542,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
      private final Map<String, Class<?>> classes = new java.util.concurrent.ConcurrentHashMap<String, Class<?>>(); // 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
+index 5ca863b3..04804706 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;
@@ -3426,7 +3554,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000
 +    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
+index 8d982974..7e89b97b 100644
 --- a/src/main/java/org/spigotmc/CustomTimingsHandler.java
 +++ b/src/main/java/org/spigotmc/CustomTimingsHandler.java
 @@ -0,0 +0,0 @@