From e9950b70d348f2b6a3a97d21fab6678d6c1d06d6 Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 26 Feb 2013 12:21:40 -0500 Subject: [PATCH] Overhaul to Timings and Entity Activation Range This greatly extends the timings improvements I've done in recent commits, and brings timings to fully cover the entire tick. The timings system also now tracks when specific timings causes the server to lose TPS. The timings are also able to be turned on "on demand", meaning you do not need to restart the server to enable them. This commit also overhauls the Entity Activation Range feature, fixing bugs, adding more immunities, and improving the performance of it. It also fixes a regression with a recent Spigot commit that broke the entire Entity Activation Range feature. This commit had to move the Tick Loop patch before timings because there was a change done there to time the entire tick, so lots of renames. These 2 commits had to be bundled together to simplify applying them and reduce redundant conflict resolution. --- ...sHandler-for-adding-new-CraftBukkit-.patch | 233 ------- .../0003-Improved-Timings-System.patch | 411 +++++++++++++ ...Add-Custom-Timings-to-various-points.patch | 329 ---------- ...ation-sleep-for-as-long-as-possible.patch} | 6 +- .../0017-Improved-Timings-System.patch | 571 ++++++++++++++++++ ...ter-more-flexible-itemstack-merging.patch} | 10 +- ...> 0019-Add-oreobfuscator-for-Spigot.patch} | 12 +- ...er-of-LivingEntity-collision-checks.patch} | 8 +- ...es-in-chunks-being-processed-for-th.patch} | 4 +- ...d-maps-in-item-frames-upon-tracking.patch} | 4 +- ...e-and-warn-about-null-tile-entities.patch} | 8 +- ...n-Range-This-feature-gives-3-new-con.patch | 327 ---------- .../0024-Entity-Activation-Range.patch | 444 ++++++++++++++ ...-the-Metrics-system-to-be-closer-to-.patch | 25 +- .../0028-Watchdog-Thread.patch | 39 +- CraftBukkit-Patches/0029-Netty.patch | 12 +- ...xception-for-built-in-PluginChannels.patch | 20 +- 17 files changed, 1503 insertions(+), 960 deletions(-) delete mode 100644 Bukkit-Patches/0003-Add-CustomTimingsHandler-for-adding-new-CraftBukkit-.patch create mode 100644 Bukkit-Patches/0003-Improved-Timings-System.patch delete mode 100644 CraftBukkit-Patches/0016-Add-Custom-Timings-to-various-points.patch rename CraftBukkit-Patches/{0023-Tick-loop-optimization-sleep-for-as-long-as-possible.patch => 0016-Tick-loop-optimization-sleep-for-as-long-as-possible.patch} (98%) create mode 100644 CraftBukkit-Patches/0017-Improved-Timings-System.patch rename CraftBukkit-Patches/{0017-Better-more-flexible-itemstack-merging.patch => 0018-Better-more-flexible-itemstack-merging.patch} (95%) rename CraftBukkit-Patches/{0018-Add-oreobfuscator-for-Spigot.patch => 0019-Add-oreobfuscator-for-Spigot.patch} (98%) rename CraftBukkit-Patches/{0019-Reduce-number-of-LivingEntity-collision-checks.patch => 0020-Reduce-number-of-LivingEntity-collision-checks.patch} (87%) rename CraftBukkit-Patches/{0020-Only-count-entities-in-chunks-being-processed-for-th.patch => 0021-Only-count-entities-in-chunks-being-processed-for-th.patch} (98%) rename CraftBukkit-Patches/{0021-Only-send-maps-in-item-frames-upon-tracking.patch => 0022-Only-send-maps-in-item-frames-upon-tracking.patch} (98%) rename CraftBukkit-Patches/{0022-Detect-remove-and-warn-about-null-tile-entities.patch => 0023-Detect-remove-and-warn-about-null-tile-entities.patch} (87%) delete mode 100644 CraftBukkit-Patches/0024-Entity-Activation-Range-This-feature-gives-3-new-con.patch create mode 100644 CraftBukkit-Patches/0024-Entity-Activation-Range.patch diff --git a/Bukkit-Patches/0003-Add-CustomTimingsHandler-for-adding-new-CraftBukkit-.patch b/Bukkit-Patches/0003-Add-CustomTimingsHandler-for-adding-new-CraftBukkit-.patch deleted file mode 100644 index 3f5a288b2..000000000 --- a/Bukkit-Patches/0003-Add-CustomTimingsHandler-for-adding-new-CraftBukkit-.patch +++ /dev/null @@ -1,233 +0,0 @@ -From 60bbe254c90b77065770adc852e57e51b0b0ef81 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Wed, 9 Jan 2013 22:18:26 -0500 -Subject: [PATCH] Add CustomTimingsHandler for adding new CraftBukkit custom - timings - ---- - .../org/bukkit/command/defaults/ReloadCommand.java | 2 + - .../bukkit/command/defaults/TimingsCommand.java | 67 ++++++++++++++++++++-- - .../org/bukkit/event/CustomTimingsHandler.java | 60 +++++++++++++++++++ - 3 files changed, 123 insertions(+), 6 deletions(-) - create mode 100644 src/main/java/org/bukkit/event/CustomTimingsHandler.java - -diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -index fb3c90f..fffafa5 100644 ---- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java -@@ -6,6 +6,7 @@ import org.bukkit.Bukkit; - import org.bukkit.ChatColor; - import org.bukkit.command.Command; - import org.bukkit.command.CommandSender; -+import org.bukkit.event.CustomTimingsHandler; - - public class ReloadCommand extends BukkitCommand { - public ReloadCommand(String name) { -@@ -20,6 +21,7 @@ public class ReloadCommand extends BukkitCommand { - public boolean execute(CommandSender sender, String currentAlias, String[] args) { - if (!testPermission(sender)) return true; - -+ CustomTimingsHandler.reload(); // Spigot - Bukkit.reload(); - Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Reload complete."); - -diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java -index 94cd62c..7c1e601 100644 ---- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java -+++ b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java -@@ -10,6 +10,7 @@ import org.apache.commons.lang.Validate; - import org.bukkit.Bukkit; - import org.bukkit.ChatColor; - import org.bukkit.command.CommandSender; -+import org.bukkit.event.CustomTimingsHandler; - import org.bukkit.event.Event; - import org.bukkit.event.HandlerList; - import org.bukkit.plugin.Plugin; -@@ -18,15 +19,21 @@ import org.bukkit.plugin.TimedRegisteredListener; - import org.bukkit.util.StringUtil; - - import com.google.common.collect.ImmutableList; -+import java.io.ByteArrayOutputStream; -+import java.io.OutputStream; -+import java.net.HttpURLConnection; -+import java.net.URL; -+import java.net.URLEncoder; -+import java.util.logging.Level; - - public class TimingsCommand extends BukkitCommand { -- private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("merged", "reset", "separate"); -+ private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("merged", "reset", "separate", "paste"); // Spigot - - public static long timingStart = 0; // Spigot - public TimingsCommand(String name) { - super(name); - this.description = "Records timings for all plugin events"; -- this.usageMessage = "/timings "; -+ this.usageMessage = "/timings "; - this.setPermission("bukkit.command.timings"); - } - -@@ -43,6 +50,7 @@ public class TimingsCommand extends BukkitCommand { - } - - boolean separate = "separate".equals(args[0]); -+ boolean paste = "paste".equals(args[0]); - if ("reset".equals(args[0])) { - for (HandlerList handlerList : HandlerList.getHandlerLists()) { - for (RegisteredListener listener : handlerList.getRegisteredListeners()) { -@@ -51,9 +59,10 @@ public class TimingsCommand extends BukkitCommand { - } - } - } -+ CustomTimingsHandler.reload(); // Spigot - timingStart = System.nanoTime(); // Spigot - sender.sendMessage("Timings reset"); -- } else if ("merged".equals(args[0]) || separate) { -+ } else if ("merged".equals(args[0]) || separate || paste) { - - long sampleTime = System.nanoTime() - timingStart; // Spigot - int index = 0; -@@ -62,11 +71,12 @@ public class TimingsCommand extends BukkitCommand { - timingFolder.mkdirs(); - File timings = new File(timingFolder, "timings.txt"); - File names = null; -+ ByteArrayOutputStream bout = (paste) ? new ByteArrayOutputStream() : null; - while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); - PrintStream fileTimings = null; - PrintStream fileNames = null; - try { -- fileTimings = new PrintStream(timings); -+ fileTimings = (paste) ? new PrintStream(bout) : new PrintStream(timings); - if (separate) { - names = new File(timingFolder, "names" + index + ".txt"); - fileNames = new PrintStream(names); -@@ -95,8 +105,17 @@ public class TimingsCommand extends BukkitCommand { - } - fileTimings.println(" Total time " + totalTime + " (" + totalTime / 1000000000 + "s)"); - } -- fileTimings.println("Sample time " + sampleTime + " (" + sampleTime / 1000000000 + "s)"); // Spigot -- sender.sendMessage("Timings written to " + timings.getPath()); -+ -+ // Spigot start -+ CustomTimingsHandler.printTimings(fileTimings); -+ fileTimings.println("Sample time " + sampleTime + " (" + sampleTime / 1000000000 + "s)"); -+ if (paste) { -+ new PasteThread(sender, bout).start(); -+ } else { -+ sender.sendMessage("Timings written to " + timings.getPath()); -+ sender.sendMessage("Paste contents of file into form at http://aikar.co/timings.php to read results."); -+ } -+ // Spigot end - if (separate) sender.sendMessage("Names written to " + names.getPath()); - } catch (IOException e) { - } finally { -@@ -122,4 +141,40 @@ public class TimingsCommand extends BukkitCommand { - } - return ImmutableList.of(); - } -+ -+ 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 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 + "Your timings have been pasted to " + location); -+ sender.sendMessage(ChatColor.GREEN + "You can view the results 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); -+ } -+ } -+ } - } -diff --git a/src/main/java/org/bukkit/event/CustomTimingsHandler.java b/src/main/java/org/bukkit/event/CustomTimingsHandler.java -new file mode 100644 -index 0000000..ff56673 ---- /dev/null -+++ b/src/main/java/org/bukkit/event/CustomTimingsHandler.java -@@ -0,0 +1,60 @@ -+package org.bukkit.event; -+ -+ -+import org.bukkit.Bukkit; -+ -+import java.io.PrintStream; -+import java.util.ArrayList; -+ -+/** -+ * Extends RegisteredListener to include timing information -+ */ -+public class CustomTimingsHandler { -+ -+ private final String name; -+ public int count = 0; -+ public long totalTime = 0; -+ long start = 0; -+ -+ public static ArrayList allList = new ArrayList(); -+ public CustomTimingsHandler(String name) { -+ this.name = name; -+ allList.add(this); -+ } -+ -+ static public void printTimings(PrintStream printStream) { -+ printStream.println("Minecraft - ** indicates it's already counted by another timing"); -+ for (CustomTimingsHandler t : allList) { -+ long time = t.totalTime; -+ int count = t.count; -+ if (count == 0) continue; -+ long avg = time / count; -+ -+ printStream.println(" " + t.name + " Time: " + time + " Count: " + count + " Avg: " + avg); -+ } -+ } -+ -+ static public void reload() { -+ if (!Bukkit.getServer().getPluginManager().useTimings()) return; -+ for (CustomTimingsHandler t : allList) { -+ t.reset(); -+ } -+ } -+ -+ public void startTiming() { -+ if (!Bukkit.getServer().getPluginManager().useTimings()) return; -+ start = System.nanoTime(); -+ } -+ -+ public void stopTiming() { -+ if (!Bukkit.getServer().getPluginManager().useTimings()) return; -+ totalTime += System.nanoTime() - start; -+ count++; -+ } -+ -+ public void reset() { -+ count = 0; -+ totalTime = 0; -+ } -+} -+ --- -1.8.1-rc2 - diff --git a/Bukkit-Patches/0003-Improved-Timings-System.patch b/Bukkit-Patches/0003-Improved-Timings-System.patch new file mode 100644 index 000000000..39532219b --- /dev/null +++ b/Bukkit-Patches/0003-Improved-Timings-System.patch @@ -0,0 +1,411 @@ +From 1d2352eb83a0e0cd6ff7cd592999430d37a8513a Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Wed, 9 Jan 2013 22:18:26 -0500 +Subject: [PATCH] Improved Timings System + +Enables "Timings on Demand" so you can enable/disable timings without server restart. +Tracks timings on sync events a plugin registers (Single and Repeating) +Tracks how many ticks a timed area has caused the server to lose due to taking too long. +Enables automatically pasting to paste.ubuntu.com so you can quickly review the results on aikar.co/timings.php +--- + src/main/java/org/bukkit/CustomTimingsHandler.java | 134 +++++++++++++++++++++ + .../org/bukkit/command/defaults/ReloadCommand.java | 2 + + .../bukkit/command/defaults/TimingsCommand.java | 90 ++++++++++++-- + .../org/bukkit/plugin/TimedRegisteredListener.java | 12 +- + .../org/bukkit/plugin/java/JavaPluginLoader.java | 2 +- + 5 files changed, 227 insertions(+), 13 deletions(-) + create mode 100644 src/main/java/org/bukkit/CustomTimingsHandler.java + +diff --git a/src/main/java/org/bukkit/CustomTimingsHandler.java b/src/main/java/org/bukkit/CustomTimingsHandler.java +new file mode 100644 +index 0000000..8c00824 +--- /dev/null ++++ b/src/main/java/org/bukkit/CustomTimingsHandler.java +@@ -0,0 +1,134 @@ ++package org.bukkit; ++ ++import org.bukkit.event.HandlerList; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.plugin.RegisteredListener; ++import org.bukkit.plugin.TimedRegisteredListener; ++ ++import java.io.PrintStream; ++import java.util.concurrent.ConcurrentLinkedQueue; ++ ++/** ++ * Provides custom timing sections for /timings merged ++ */ ++public class CustomTimingsHandler { ++ ++ final public String name; ++ public long count = 0; ++ public long start = 0; ++ public long timingDepth = 0; ++ public long totalTime = 0; ++ public long curTickTotal = 0; ++ public long violations = 0; ++ CustomTimingsHandler parent = null; ++ ++ final public static ConcurrentLinkedQueue allList = new ConcurrentLinkedQueue(); ++ ++ public CustomTimingsHandler(String name) { ++ this.name = name; ++ allList.add(this); ++ } ++ public CustomTimingsHandler(String name, CustomTimingsHandler parent) { ++ this(name); ++ this.parent = parent; ++ } ++ ++ /** ++ * Prints the timings and extra data to the printstream ++ * @param printStream ++ */ ++ public static void printTimings(PrintStream printStream) { ++ printStream.println("Minecraft"); ++ for (CustomTimingsHandler timings : allList) { ++ long time = timings.totalTime; ++ long count = timings.count; ++ if (count == 0) continue; ++ 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); ++ } ++ ++ /** ++ * Resets all timings ++ */ ++ public static void reload() { ++ if (!Bukkit.getServer().getPluginManager().useTimings()) return; ++ for (CustomTimingsHandler timings : allList) { ++ timings.reset(); ++ } ++ } ++ ++ /** ++ * Ticked every tick by CraftBukkit to count the number of times a timer caused TPS loss. ++ */ ++ public static void tick() { ++ if (!Bukkit.getServer().getPluginManager().useTimings()) return; ++ for (CustomTimingsHandler timings : allList) { ++ if (timings.curTickTotal > 50000000) { ++ timings.violations += Math.ceil(timings.curTickTotal / 50000000); ++ } ++ timings.curTickTotal = 0; ++ } ++ ++ for (Plugin plugin : Bukkit.getPluginManager().getPlugins()) { ++ for (RegisteredListener listener : HandlerList.getRegisteredListeners(plugin)) { ++ if (listener instanceof TimedRegisteredListener) { ++ TimedRegisteredListener timings = (TimedRegisteredListener) listener; ++ if (timings.curTickTotal > 50000000) { ++ timings.violations += Math.ceil(timings.curTickTotal / 50000000); ++ } ++ timings.curTickTotal = 0; ++ } ++ } ++ } ++ } ++ ++ /** ++ * Starts timing to track a section of code. ++ */ ++ public void startTiming() { ++ if (!Bukkit.getServer().getPluginManager().useTimings()) return; ++ ++ if (++timingDepth != 1) { ++ return; // Already timing. ++ } ++ start = System.nanoTime(); ++ ++ if (parent != null && ++parent.timingDepth == 1) { ++ parent.start = start; ++ } ++ } ++ ++ public void stopTiming() { ++ if (!Bukkit.getServer().getPluginManager().useTimings()) return; ++ if (--timingDepth != 0 || start == 0) { ++ return; ++ } ++ long diff = System.nanoTime() - start; ++ totalTime += diff; ++ curTickTotal += diff; ++ count++; ++ start = 0; ++ if (parent != null) { ++ parent.stopTiming(); ++ } ++ } ++ ++ public void reset() { ++ count = 0; ++ violations = 0; ++ curTickTotal = 0; ++ totalTime = 0; ++ } ++} ++ +diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +index fb3c90f..89c8414 100644 +--- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +@@ -6,6 +6,7 @@ import org.bukkit.Bukkit; + import org.bukkit.ChatColor; + import org.bukkit.command.Command; + import org.bukkit.command.CommandSender; ++import org.bukkit.CustomTimingsHandler; + + public class ReloadCommand extends BukkitCommand { + public ReloadCommand(String name) { +@@ -20,6 +21,7 @@ public class ReloadCommand extends BukkitCommand { + public boolean execute(CommandSender sender, String currentAlias, String[] args) { + if (!testPermission(sender)) return true; + ++ CustomTimingsHandler.reload(); // Spigot + Bukkit.reload(); + Command.broadcastCommandMessage(sender, ChatColor.GREEN + "Reload complete."); + +diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +index 94cd62c..426f9b4 100644 +--- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java ++++ b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +@@ -10,40 +10,59 @@ import org.apache.commons.lang.Validate; + import org.bukkit.Bukkit; + import org.bukkit.ChatColor; + import org.bukkit.command.CommandSender; ++import org.bukkit.CustomTimingsHandler; + import org.bukkit.event.Event; + import org.bukkit.event.HandlerList; + import org.bukkit.plugin.Plugin; + import org.bukkit.plugin.RegisteredListener; ++import org.bukkit.plugin.SimplePluginManager; // Spigot + import org.bukkit.plugin.TimedRegisteredListener; + import org.bukkit.util.StringUtil; + + import com.google.common.collect.ImmutableList; ++import java.io.ByteArrayOutputStream; ++import java.io.OutputStream; ++import java.net.HttpURLConnection; ++import java.net.URL; ++import java.net.URLEncoder; ++import java.util.logging.Level; + + public class TimingsCommand extends BukkitCommand { +- private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("merged", "reset", "separate"); ++ private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("merged", "reset", "separate", "paste", "on", "off"); // Spigot + + public static long timingStart = 0; // Spigot + public TimingsCommand(String name) { + super(name); + this.description = "Records timings for all plugin events"; +- this.usageMessage = "/timings "; ++ this.usageMessage = "/timings "; // Spigot + this.setPermission("bukkit.command.timings"); + } + + @Override + public boolean execute(CommandSender sender, String currentAlias, String[] args) { + if (!testPermission(sender)) return true; +- if (args.length != 1) { ++ if (args.length < 1) { // Spigot + sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); + return false; + } +- if (!sender.getServer().getPluginManager().useTimings()) { ++ // Spigot start - this is dynamic now ++ /*if (!sender.getServer().getPluginManager().useTimings()) { + sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml"); + return true; ++ }*/ ++ if ("on".equals(args[0])) { ++ ((SimplePluginManager)Bukkit.getServer().getPluginManager()).useTimings(true); ++ sender.sendMessage("Enabled Timings"); ++ } else if ("off".equals(args[0])) { ++ ((SimplePluginManager)Bukkit.getServer().getPluginManager()).useTimings(false); ++ sender.sendMessage("Disabled Timings"); + } ++ // Spigot end + + boolean separate = "separate".equals(args[0]); +- if ("reset".equals(args[0])) { ++ boolean paste = "paste".equals(args[0]); // Spigot ++ if ("on".equals(args[0]) || "reset".equals(args[0])) { // Spigot ++ if (!"on".equals(args[0]) && !Bukkit.getServer().getPluginManager().useTimings()) {sender.sendMessage("Please enable timings by typing /timings on"); return true; } // Spigot + for (HandlerList handlerList : HandlerList.getHandlerLists()) { + for (RegisteredListener listener : handlerList.getRegisteredListeners()) { + if (listener instanceof TimedRegisteredListener) { +@@ -51,10 +70,11 @@ public class TimingsCommand extends BukkitCommand { + } + } + } ++ CustomTimingsHandler.reload(); // Spigot + timingStart = System.nanoTime(); // Spigot + sender.sendMessage("Timings reset"); +- } else if ("merged".equals(args[0]) || separate) { +- ++ } else if ("merged".equals(args[0]) || separate || paste) { // Spigot ++ if (!Bukkit.getServer().getPluginManager().useTimings()) {sender.sendMessage("Please enable timings by typing /timings on"); return true; } // Spigot + long sampleTime = System.nanoTime() - timingStart; // Spigot + int index = 0; + int pluginIdx = 0; +@@ -62,11 +82,12 @@ public class TimingsCommand extends BukkitCommand { + timingFolder.mkdirs(); + File timings = new File(timingFolder, "timings.txt"); + File names = null; ++ ByteArrayOutputStream bout = (paste) ? new ByteArrayOutputStream() : null; // Spigot + while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); + PrintStream fileTimings = null; + PrintStream fileNames = null; + try { +- fileTimings = new PrintStream(timings); ++ fileTimings = (paste) ? new PrintStream(bout) : new PrintStream(timings); + if (separate) { + names = new File(timingFolder, "names" + index + ".txt"); + fileNames = new PrintStream(names); +@@ -89,14 +110,23 @@ public class TimingsCommand extends BukkitCommand { + totalTime += time; + Event event = trl.getEvent(); + if (count > 0 && event != null) { +- fileTimings.println(" " + event.getClass().getSimpleName() + (trl.hasMultiple() ? " (and others)" : "") + " Time: " + time + " Count: " + count + " Avg: " + avg); ++ fileTimings.println(" " + event.getClass().getSimpleName() + (trl.hasMultiple() ? " (and others)" : "") + " Time: " + time + " Count: " + count + " Avg: " + avg + " Violations: " + trl.violations); // Spigot + } + } + } + fileTimings.println(" Total time " + totalTime + " (" + totalTime / 1000000000 + "s)"); + } +- fileTimings.println("Sample time " + sampleTime + " (" + sampleTime / 1000000000 + "s)"); // Spigot +- sender.sendMessage("Timings written to " + timings.getPath()); ++ ++ // Spigot start ++ CustomTimingsHandler.printTimings(fileTimings); ++ fileTimings.println("Sample time " + sampleTime + " (" + sampleTime / 1000000000 + "s)"); ++ if (paste) { ++ new PasteThread(sender, bout).start(); ++ } else { ++ sender.sendMessage("Timings written to " + timings.getPath()); ++ sender.sendMessage("Paste contents of file into form at http://aikar.co/timings.php to read results."); ++ } ++ // Spigot end + if (separate) sender.sendMessage("Names written to " + names.getPath()); + } catch (IOException e) { + } finally { +@@ -122,4 +152,42 @@ 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 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 + "Your timings have been pasted to " + location); ++ sender.sendMessage(ChatColor.GREEN + "You can view the results 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/plugin/TimedRegisteredListener.java b/src/main/java/org/bukkit/plugin/TimedRegisteredListener.java +index ed25e17..47dab3e 100644 +--- a/src/main/java/org/bukkit/plugin/TimedRegisteredListener.java ++++ b/src/main/java/org/bukkit/plugin/TimedRegisteredListener.java +@@ -1,5 +1,6 @@ + package org.bukkit.plugin; + ++import org.bukkit.Bukkit; // Spigot + import org.bukkit.event.Event; + import org.bukkit.event.EventException; + import org.bukkit.event.EventPriority; +@@ -11,6 +12,8 @@ import org.bukkit.event.Listener; + public class TimedRegisteredListener extends RegisteredListener { + private int count; + private long totalTime; ++ public long curTickTotal = 0; // Spigot ++ public long violations = 0; // Spigot + private Event event; + private boolean multiple = false; + +@@ -20,6 +23,7 @@ public class TimedRegisteredListener extends RegisteredListener { + + @Override + public void callEvent(Event event) throws EventException { ++ if (!Bukkit.getServer().getPluginManager().useTimings()) { super.callEvent(event);return; } // Spigot + if (event.isAsynchronous()) { + super.callEvent(event); + return; +@@ -33,7 +37,11 @@ public class TimedRegisteredListener extends RegisteredListener { + } + long start = System.nanoTime(); + super.callEvent(event); +- totalTime += System.nanoTime() - start; ++ // Spigot start ++ long diff = System.nanoTime() - start; ++ curTickTotal += diff; ++ totalTime += diff; ++ // Spigot end + } + + /** +@@ -42,6 +50,8 @@ public class TimedRegisteredListener extends RegisteredListener { + public void reset() { + count = 0; + totalTime = 0; ++ curTickTotal = 0; // Spigot ++ violations = 0; // Spigot + } + + /** +diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +index 10fc26a..9c7288e 100644 +--- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java ++++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +@@ -430,7 +430,7 @@ public class JavaPluginLoader implements PluginLoader { + } + } + }; +- if (useTimings) { ++ if (true) { // Spigot - TRL handles useTimings check now + eventSet.add(new TimedRegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); + } else { + eventSet.add(new RegisteredListener(listener, executor, eh.priority(), plugin, eh.ignoreCancelled())); +-- +1.8.1.1 + diff --git a/CraftBukkit-Patches/0016-Add-Custom-Timings-to-various-points.patch b/CraftBukkit-Patches/0016-Add-Custom-Timings-to-various-points.patch deleted file mode 100644 index ba814bd3c..000000000 --- a/CraftBukkit-Patches/0016-Add-Custom-Timings-to-various-points.patch +++ /dev/null @@ -1,329 +0,0 @@ -From ede0d69949d7d00980598f1944de83052162deb4 Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Thu, 10 Jan 2013 00:18:11 -0500 -Subject: [PATCH] Add Custom Timings to various points - ---- - .../net/minecraft/server/ChunkProviderServer.java | 4 ++++ - .../java/net/minecraft/server/EntityLiving.java | 21 +++++++++++++++++++++ - .../java/net/minecraft/server/PlayerConnection.java | 7 +++++++ - src/main/java/net/minecraft/server/World.java | 9 +++++++++ - src/main/java/net/minecraft/server/WorldServer.java | 4 ++++ - .../java/org/bukkit/event/WorldTimingsHandler.java | 20 ++++++++++++++++++++ - 6 files changed, 65 insertions(+) - create mode 100644 src/main/java/org/bukkit/event/WorldTimingsHandler.java - -diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java -index c0bab0f..279ba9e 100644 ---- a/src/main/java/net/minecraft/server/ChunkProviderServer.java -+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java -@@ -15,6 +15,7 @@ import org.bukkit.craftbukkit.chunkio.ChunkIOExecutor; - import org.bukkit.craftbukkit.util.LongHash; - import org.bukkit.craftbukkit.util.LongHashSet; - import org.bukkit.craftbukkit.util.LongObjectHashMap; -+import org.bukkit.event.CustomTimingsHandler; - import org.bukkit.event.world.ChunkUnloadEvent; - // CraftBukkit end - -@@ -28,6 +29,7 @@ public class ChunkProviderServer implements IChunkProvider { - public boolean forceChunkLoad = false; // true -> false - public LongObjectHashMap chunks = new LongObjectHashMap(); - public WorldServer world; -+ static private CustomTimingsHandler syncChunkLoadTimer = new CustomTimingsHandler("syncChunkLoad"); // Spigot - // CraftBukkit end - - public ChunkProviderServer(WorldServer worldserver, IChunkLoader ichunkloader, IChunkProvider ichunkprovider) { -@@ -103,6 +105,7 @@ public class ChunkProviderServer implements IChunkProvider { - // CraftBukkit end - - if (chunk == null) { -+ syncChunkLoadTimer.startTiming(); // Spigot - chunk = this.loadChunk(i, j); - if (chunk == null) { - if (this.chunkProvider == null) { -@@ -141,6 +144,7 @@ public class ChunkProviderServer implements IChunkProvider { - // CraftBukkit end - - chunk.a(this, this, i, j); -+ syncChunkLoadTimer.stopTiming(); // Spigot - } - - // CraftBukkit start - If we didn't need to load the chunk run the callback now -diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index 7d2e633..b2481aa 100644 ---- a/src/main/java/net/minecraft/server/EntityLiving.java -+++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -8,6 +8,7 @@ import java.util.Random; - - // CraftBukkit start - import org.bukkit.craftbukkit.event.CraftEventFactory; -+import org.bukkit.event.CustomTimingsHandler; - import org.bukkit.event.entity.EntityDamageByBlockEvent; - import org.bukkit.event.entity.EntityDamageEvent; - import org.bukkit.event.entity.EntityRegainHealthEvent; -@@ -110,6 +111,14 @@ public abstract class EntityLiving extends Entity { - public int expToDrop = 0; - public int maxAirTicks = 300; - public int maxHealth = this.getMaxHealth(); -+ // Spigot Start -+ public static CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** entityBaseTick"); -+ public static CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** entityAI"); -+ public static CustomTimingsHandler timerEntityAIJump = new CustomTimingsHandler("** entityAIJump"); -+ public static CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** entityAIMove"); -+ public static CustomTimingsHandler timerEntityAILoot = new CustomTimingsHandler("** entityAILoot"); -+ public static CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** entityTickRest"); -+ // Spigot End - // CraftBukkit end - - public EntityLiving(World world) { -@@ -505,6 +514,7 @@ public abstract class EntityLiving extends Entity { - } - - public void j_() { -+ timerEntityBaseTick.startTiming(); // Spigot - super.j_(); - if (!this.world.isStatic) { - int i; -@@ -531,7 +541,9 @@ public abstract class EntityLiving extends Entity { - } - } - -+ timerEntityBaseTick.stopTiming(); // Spigot - this.c(); -+ timerEntityTickRest.startTiming(); // Spigot - double d0 = this.locX - this.lastX; - double d1 = this.locZ - this.lastZ; - float f = (float) (d0 * d0 + d1 * d1); -@@ -622,6 +634,7 @@ public abstract class EntityLiving extends Entity { - - this.world.methodProfiler.b(); - this.aD += f2; -+ timerEntityTickRest.stopTiming(); // Spigot - } - - // CraftBukkit start - delegate so we can handle providing a reason for health being regained -@@ -1228,6 +1241,7 @@ public abstract class EntityLiving extends Entity { - } - - public void c() { -+ timerEntityAI.startTiming(); // Spigot - if (this.bV > 0) { - --this.bV; - } -@@ -1279,9 +1293,11 @@ public abstract class EntityLiving extends Entity { - this.az = this.yaw; - } - } -+ timerEntityAI.stopTiming(); // Spigot - - this.world.methodProfiler.b(); - this.world.methodProfiler.a("jump"); -+ timerEntityAIJump.startTiming(); // Spigot - if (this.bF) { - if (!this.H() && !this.J()) { - if (this.onGround && this.bV == 0) { -@@ -1295,8 +1311,10 @@ public abstract class EntityLiving extends Entity { - this.bV = 0; - } - -+ timerEntityAIJump.stopTiming(); // Spigot - this.world.methodProfiler.b(); - this.world.methodProfiler.a("travel"); -+ timerEntityAIMove.startTiming(); // Spigot - this.bC *= 0.98F; - this.bD *= 0.98F; - this.bE *= 0.9F; -@@ -1305,6 +1323,7 @@ public abstract class EntityLiving extends Entity { - this.aN *= this.bB(); - this.e(this.bC, this.bD); - this.aN = f; -+ timerEntityAIMove.stopTiming(); // Spigot - this.world.methodProfiler.b(); - this.world.methodProfiler.a("push"); - if (!this.world.isStatic) { -@@ -1313,6 +1332,7 @@ public abstract class EntityLiving extends Entity { - - this.world.methodProfiler.b(); - this.world.methodProfiler.a("looting"); -+ timerEntityAILoot.startTiming(); // Spigot - // CraftBukkit - Don't run mob pickup code on players - if (!this.world.isStatic && !(this instanceof EntityPlayer) && this.canPickUpLoot && !this.bc && this.world.getGameRules().getBoolean("mobGriefing")) { - List list = this.world.a(EntityItem.class, this.boundingBox.grow(1.0D, 0.0D, 1.0D)); -@@ -1377,6 +1397,7 @@ public abstract class EntityLiving extends Entity { - } - } - -+ timerEntityAILoot.stopTiming(); // Spigot - this.world.methodProfiler.b(); - } - -diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 43a24f5..7ca0acf 100644 ---- a/src/main/java/net/minecraft/server/PlayerConnection.java -+++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -25,6 +25,7 @@ import org.bukkit.craftbukkit.util.Waitable; - import org.bukkit.craftbukkit.entity.CraftPlayer; - import org.bukkit.craftbukkit.event.CraftEventFactory; - import org.bukkit.entity.Player; -+import org.bukkit.event.CustomTimingsHandler; - import org.bukkit.event.Event; - import org.bukkit.event.block.Action; - import org.bukkit.event.block.SignChangeEvent; -@@ -68,6 +69,7 @@ public class PlayerConnection extends Connection { - private double q; - public boolean checkMovement = true; // CraftBukkit - private -> public - private IntHashMap s = new IntHashMap(); -+ static private CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("playerCommand"); // Spigot - - public PlayerConnection(MinecraftServer minecraftserver, INetworkManager inetworkmanager, EntityPlayer entityplayer) { - this.minecraftServer = minecraftserver; -@@ -976,6 +978,7 @@ public class PlayerConnection extends Connection { - // CraftBukkit end - - private void handleCommand(String s) { -+ playerCommandTimer.startTiming(); // Spigot - // CraftBukkit start - CraftPlayer player = this.getPlayer(); - -@@ -983,19 +986,23 @@ public class PlayerConnection extends Connection { - this.server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { -+ playerCommandTimer.stopTiming(); // Spigot - return; - } - - try { - if (server.logCommands) logger.info(event.getPlayer().getName() + " issued server command: " + event.getMessage()); // Spigot - if (this.server.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) { -+ playerCommandTimer.stopTiming(); // Spigot - return; - } - } catch (org.bukkit.command.CommandException ex) { - player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); - Logger.getLogger(PlayerConnection.class.getName()).log(Level.SEVERE, null, ex); -+ playerCommandTimer.stopTiming(); // Spigot - return; - } -+ playerCommandTimer.stopTiming(); // Spigot - // CraftBukkit end - - /* CraftBukkit start - No longer needed as we have already handled it in server.dispatchServerCommand above. -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 41f4f31..c914461 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -14,6 +14,7 @@ import java.util.concurrent.Callable; - import org.bukkit.Bukkit; - import org.bukkit.craftbukkit.util.LongHashSet; - import org.bukkit.craftbukkit.util.UnsafeList; -+import org.bukkit.event.WorldTimingsHandler; - import org.bukkit.generator.ChunkGenerator; - import org.bukkit.craftbukkit.CraftServer; - import org.bukkit.craftbukkit.CraftWorld; -@@ -114,6 +115,7 @@ public abstract class World implements IBlockAccess { - final Object chunkLock = new Object(); - private byte chunkTickRadius; - -+ public WorldTimingsHandler timings; // Spigot - public CraftWorld getWorld() { - return this.world; - } -@@ -193,6 +195,7 @@ public abstract class World implements IBlockAccess { - this.a(); - - this.getServer().addWorld(this.world); // CraftBukkit -+ timings = new WorldTimingsHandler(this); // Spigot - } - - protected abstract IChunkProvider j(); -@@ -1204,6 +1207,7 @@ public abstract class World implements IBlockAccess { - CrashReport crashreport; - CrashReportSystemDetails crashreportsystemdetails; - -+ timings.entityBaseTick.startTiming(); // Spigot - for (i = 0; i < this.i.size(); ++i) { - entity = (Entity) this.i.get(i); - // CraftBukkit start - fixed an NPE, don't process entities in chunks queued for unload -@@ -1258,7 +1262,9 @@ public abstract class World implements IBlockAccess { - - this.f.clear(); - this.methodProfiler.c("regular"); -+ timings.entityBaseTick.stopTiming(); // Spigot - -+ timings.entityTick.startTiming(); // Spigot - for (i = 0; i < this.entityList.size(); ++i) { - entity = (Entity) this.entityList.get(i); - -@@ -1311,7 +1317,9 @@ public abstract class World implements IBlockAccess { - this.methodProfiler.b(); - } - -+ timings.entityTick.stopTiming(); // Spigot - this.methodProfiler.c("tileEntities"); -+ timings.tileEntityTick.startTiming(); // Spigot - this.M = true; - Iterator iterator = this.tileEntityList.iterator(); - -@@ -1390,6 +1398,7 @@ public abstract class World implements IBlockAccess { - this.a.clear(); - } - -+ timings.tileEntityTick.stopTiming(); // Spigot - this.methodProfiler.b(); - this.methodProfiler.b(); - } -diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java -index 4aa2a19..6cb3e24 100644 ---- a/src/main/java/net/minecraft/server/WorldServer.java -+++ b/src/main/java/net/minecraft/server/WorldServer.java -@@ -157,9 +157,12 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate - // CraftBukkit start - Only call spawner if we have players online and the world allows for mobs or animals - long time = this.worldData.getTime(); - if (this.getGameRules().getBoolean("doMobSpawning") && (this.allowMonsters || this.allowAnimals) && (this instanceof WorldServer && this.players.size() > 0)) { -+ timings.mobSpawn.startTiming(); // Spigot - SpawnerCreature.spawnEntities(this, this.allowMonsters && (this.ticksPerMonsterSpawns != 0 && time % this.ticksPerMonsterSpawns == 0L), this.allowAnimals && (this.ticksPerAnimalSpawns != 0 && time % this.ticksPerAnimalSpawns == 0L), this.worldData.getTime() % 400L == 0L); -+ timings.mobSpawn.stopTiming(); // Spigot - } - // CraftBukkit end -+ timings.doTickRest.startTiming(); // Spigot - this.methodProfiler.c("chunkSource"); - this.chunkProvider.unloadChunks(); - int j = this.a(1.0F); -@@ -186,6 +189,7 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate - this.V(); - - this.getWorld().processChunkGC(); // CraftBukkit -+ timings.doTickRest.stopTiming(); // Spigot - } - - public BiomeMeta a(EnumCreatureType enumcreaturetype, int i, int j, int k) { -diff --git a/src/main/java/org/bukkit/event/WorldTimingsHandler.java b/src/main/java/org/bukkit/event/WorldTimingsHandler.java -new file mode 100644 -index 0000000..bb0c191 ---- /dev/null -+++ b/src/main/java/org/bukkit/event/WorldTimingsHandler.java -@@ -0,0 +1,20 @@ -+package org.bukkit.event; -+ -+import net.minecraft.server.World; -+ -+public class WorldTimingsHandler { -+ public CustomTimingsHandler mobSpawn; -+ public CustomTimingsHandler doTickRest; -+ public CustomTimingsHandler entityBaseTick; -+ public CustomTimingsHandler entityTick; -+ public CustomTimingsHandler tileEntityTick; -+ public WorldTimingsHandler(World server) { -+ String name = server.worldData.getName() +" - "; -+ -+ mobSpawn = new CustomTimingsHandler(name + "mobSpawn"); -+ doTickRest = new CustomTimingsHandler(name + "doTickRest"); -+ entityBaseTick = new CustomTimingsHandler(name + "entityBaseTick"); -+ entityTick = new CustomTimingsHandler(name + "entityTick"); -+ tileEntityTick = new CustomTimingsHandler(name + "tileEntityTick"); -+ } -+} --- -1.8.1-rc2 - diff --git a/CraftBukkit-Patches/0023-Tick-loop-optimization-sleep-for-as-long-as-possible.patch b/CraftBukkit-Patches/0016-Tick-loop-optimization-sleep-for-as-long-as-possible.patch similarity index 98% rename from CraftBukkit-Patches/0023-Tick-loop-optimization-sleep-for-as-long-as-possible.patch rename to CraftBukkit-Patches/0016-Tick-loop-optimization-sleep-for-as-long-as-possible.patch index 61ff2534e..a4c32f825 100644 --- a/CraftBukkit-Patches/0023-Tick-loop-optimization-sleep-for-as-long-as-possible.patch +++ b/CraftBukkit-Patches/0016-Tick-loop-optimization-sleep-for-as-long-as-possible.patch @@ -1,4 +1,4 @@ -From 5edc0ce11f85c023f0d9afb33dc152d0e26bd15f Mon Sep 17 00:00:00 2001 +From fa1eeb2d804ba81c94d259d60df735627eae989f Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 3 Feb 2013 12:28:17 +1100 Subject: [PATCH] Tick loop optimization - sleep for as long as possible. @@ -82,7 +82,7 @@ index 4bdf8aa..128016f 100644 this.a((CrashReport) null); } diff --git a/src/main/java/org/bukkit/craftbukkit/Spigot.java b/src/main/java/org/bukkit/craftbukkit/Spigot.java -index 5827820..1ead152 100644 +index 4a4f949..db46037 100644 --- a/src/main/java/org/bukkit/craftbukkit/Spigot.java +++ b/src/main/java/org/bukkit/craftbukkit/Spigot.java @@ -6,6 +6,8 @@ import org.bukkit.configuration.file.YamlConfiguration; @@ -136,5 +136,5 @@ index 0000000..f114a31 + } +} -- -1.8.1-rc2 +1.8.1.1 diff --git a/CraftBukkit-Patches/0017-Improved-Timings-System.patch b/CraftBukkit-Patches/0017-Improved-Timings-System.patch new file mode 100644 index 000000000..d0b71f429 --- /dev/null +++ b/CraftBukkit-Patches/0017-Improved-Timings-System.patch @@ -0,0 +1,571 @@ +From 7d318ee4bf7783ec9bca927195e5ee11d4490964 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 10 Jan 2013 00:18:11 -0500 +Subject: [PATCH] Improved Timings System + +Tracks nearly every point of minecraft internals and plugin events to give a good quick overview on what is causing TPS loss. +--- + .../net/minecraft/server/ChunkProviderServer.java | 2 + + src/main/java/net/minecraft/server/Entity.java | 5 + + .../java/net/minecraft/server/EntityLiving.java | 10 ++ + .../java/net/minecraft/server/MinecraftServer.java | 17 +++- + .../net/minecraft/server/PlayerConnection.java | 5 + + src/main/java/net/minecraft/server/TileEntity.java | 2 + + src/main/java/net/minecraft/server/World.java | 17 ++++ + .../java/net/minecraft/server/WorldServer.java | 4 + + .../java/org/bukkit/craftbukkit/SpigotTimings.java | 111 +++++++++++++++++++++ + .../bukkit/craftbukkit/scheduler/CraftTask.java | 18 ++++ + 10 files changed, 190 insertions(+), 1 deletion(-) + create mode 100644 src/main/java/org/bukkit/craftbukkit/SpigotTimings.java + +diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java +index c0bab0f..5772932 100644 +--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java ++++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java +@@ -103,6 +103,7 @@ public class ChunkProviderServer implements IChunkProvider { + // CraftBukkit end + + if (chunk == null) { ++ org.bukkit.craftbukkit.SpigotTimings.syncChunkLoadTimer.startTiming(); // Spigot + chunk = this.loadChunk(i, j); + if (chunk == null) { + if (this.chunkProvider == null) { +@@ -141,6 +142,7 @@ public class ChunkProviderServer implements IChunkProvider { + // CraftBukkit end + + chunk.a(this, this, i, j); ++ org.bukkit.craftbukkit.SpigotTimings.syncChunkLoadTimer.stopTiming(); // Spigot + } + + // CraftBukkit start - If we didn't need to load the chunk run the callback now +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index d0a58f8..bf9108a 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -15,6 +15,7 @@ import org.bukkit.block.BlockFace; + import org.bukkit.entity.LivingEntity; + import org.bukkit.entity.Painting; + import org.bukkit.entity.Vehicle; ++import org.bukkit.CustomTimingsHandler; // Spigot + import org.bukkit.event.entity.EntityCombustByEntityEvent; + import org.bukkit.event.painting.PaintingBreakByEntityEvent; + import org.bukkit.event.vehicle.VehicleBlockCollisionEvent; +@@ -111,6 +112,8 @@ public abstract class Entity { + public UUID uniqueId = UUID.randomUUID(); // CraftBukkit + public boolean valid = false; // CraftBukkit + ++ public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot ++ + public Entity(World world) { + this.id = entityCount++; + this.l = 1.0D; +@@ -424,6 +427,7 @@ public abstract class Entity { + + public void move(double d0, double d1, double d2) { + if (d0 == 0 && d1 == 0 && d2 == 0) { return; } // Spigot ++ org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.startTiming(); // Spigot + if (this.Y) { + this.boundingBox.d(d0, d1, d2); + this.locX = (this.boundingBox.a + this.boundingBox.d) / 2.0D; +@@ -729,6 +733,7 @@ public abstract class Entity { + + this.world.methodProfiler.b(); + } ++ org.bukkit.craftbukkit.SpigotTimings.entityMoveTimer.stopTiming(); // Spigot + } + + protected void D() { +diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java +index 7d2e633..bd1aeaa 100644 +--- a/src/main/java/net/minecraft/server/EntityLiving.java ++++ b/src/main/java/net/minecraft/server/EntityLiving.java +@@ -505,6 +505,7 @@ public abstract class EntityLiving extends Entity { + } + + public void j_() { ++ org.bukkit.craftbukkit.SpigotTimings.timerEntityBaseTick.startTiming(); // Spigot + super.j_(); + if (!this.world.isStatic) { + int i; +@@ -531,7 +532,9 @@ public abstract class EntityLiving extends Entity { + } + } + ++ org.bukkit.craftbukkit.SpigotTimings.timerEntityBaseTick.stopTiming(); // Spigot + this.c(); ++ org.bukkit.craftbukkit.SpigotTimings.timerEntityTickRest.startTiming(); // Spigot + double d0 = this.locX - this.lastX; + double d1 = this.locZ - this.lastZ; + float f = (float) (d0 * d0 + d1 * d1); +@@ -622,6 +625,7 @@ public abstract class EntityLiving extends Entity { + + this.world.methodProfiler.b(); + this.aD += f2; ++ org.bukkit.craftbukkit.SpigotTimings.timerEntityTickRest.stopTiming(); // Spigot + } + + // CraftBukkit start - delegate so we can handle providing a reason for health being regained +@@ -1228,6 +1232,7 @@ public abstract class EntityLiving extends Entity { + } + + public void c() { ++ org.bukkit.craftbukkit.SpigotTimings.timerEntityAI.startTiming(); // Spigot + if (this.bV > 0) { + --this.bV; + } +@@ -1279,6 +1284,7 @@ public abstract class EntityLiving extends Entity { + this.az = this.yaw; + } + } ++ org.bukkit.craftbukkit.SpigotTimings.timerEntityAI.stopTiming(); // Spigot + + this.world.methodProfiler.b(); + this.world.methodProfiler.a("jump"); +@@ -1297,6 +1303,7 @@ public abstract class EntityLiving extends Entity { + + this.world.methodProfiler.b(); + this.world.methodProfiler.a("travel"); ++ org.bukkit.craftbukkit.SpigotTimings.timerEntityAIMove.startTiming(); // Spigot + this.bC *= 0.98F; + this.bD *= 0.98F; + this.bE *= 0.9F; +@@ -1305,11 +1312,14 @@ public abstract class EntityLiving extends Entity { + this.aN *= this.bB(); + this.e(this.bC, this.bD); + this.aN = f; ++ org.bukkit.craftbukkit.SpigotTimings.timerEntityAIMove.stopTiming(); // Spigot + this.world.methodProfiler.b(); + this.world.methodProfiler.a("push"); ++ org.bukkit.craftbukkit.SpigotTimings.timerEntityAICollision.startTiming(); // Spigot + if (!this.world.isStatic) { + this.bd(); + } ++ org.bukkit.craftbukkit.SpigotTimings.timerEntityAICollision.stopTiming(); // Spigot + + this.world.methodProfiler.b(); + this.world.methodProfiler.a("looting"); +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 128016f..aa6a14a 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -6,7 +6,6 @@ import java.security.KeyPair; + import java.text.SimpleDateFormat; + import java.util.ArrayList; + import java.util.Date; +-import java.util.Iterator; + import java.util.List; + import java.util.concurrent.Callable; + import java.util.logging.Level; +@@ -21,6 +20,7 @@ import jline.console.ConsoleReader; + import joptsimple.OptionSet; + + import org.bukkit.World.Environment; ++import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.util.Waitable; + import org.bukkit.event.server.RemoteServerCommandEvent; + import org.bukkit.event.world.WorldSaveEvent; +@@ -417,7 +417,10 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + currentTPS = (currentTPS * 0.95) + (1E9 / (curTime - lastTick) * 0.05); + lastTick = curTime; + MinecraftServer.currentTick++; ++ SpigotTimings.serverTickTimer.startTiming(); + this.q(); ++ SpigotTimings.serverTickTimer.stopTiming(); ++ org.bukkit.CustomTimingsHandler.tick(); + } + // Spigot end + } else { +@@ -517,6 +520,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + this.methodProfiler.a("levels"); + + // CraftBukkit start - only send timeupdates to the people in that world ++ SpigotTimings.schedulerTimer.startTiming(); // Spigot + this.server.getScheduler().mainThreadHeartbeat(this.ticks); + + // Run tasks that are waiting on processing +@@ -524,7 +528,10 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + processQueue.remove().run(); + } + ++ SpigotTimings.schedulerTimer.stopTiming(); // Spigot ++ SpigotTimings.chunkIOTickTimer.startTiming(); // Spigot + org.bukkit.craftbukkit.chunkio.ChunkIOExecutor.tick(); ++ SpigotTimings.chunkIOTickTimer.stopTiming(); // Spigot + + // Send timeupdates to everyone, it will get the right time from the world the player is in. + if (this.ticks % 20 == 0) { +@@ -576,7 +583,9 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + + this.methodProfiler.b(); + this.methodProfiler.a("tracker"); ++ worldserver.timings.tracker.startTiming(); // Spigot + worldserver.getTracker().updatePlayers(); ++ worldserver.timings.tracker.stopTiming(); // Spigot + this.methodProfiler.b(); + this.methodProfiler.b(); + // } // CraftBukkit +@@ -585,14 +594,20 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo + } + + this.methodProfiler.c("connection"); ++ SpigotTimings.connectionTimer.startTiming(); // Spigot + this.ae().b(); ++ SpigotTimings.connectionTimer.stopTiming(); // Spigot + this.methodProfiler.c("players"); ++ SpigotTimings.playerListTimer.startTiming(); // Spigot + this.t.tick(); ++ SpigotTimings.playerListTimer.stopTiming(); // Spigot + this.methodProfiler.c("tickables"); + ++ SpigotTimings.tickablesTimer.startTiming(); // Spigot + for (i = 0; i < this.p.size(); ++i) { + ((IUpdatePlayerListBox) this.p.get(i)).a(); + } ++ SpigotTimings.tickablesTimer.stopTiming(); // Spigot + + this.methodProfiler.b(); + } +diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java +index 43a24f5..d2c2305 100644 +--- a/src/main/java/net/minecraft/server/PlayerConnection.java ++++ b/src/main/java/net/minecraft/server/PlayerConnection.java +@@ -976,6 +976,7 @@ public class PlayerConnection extends Connection { + // CraftBukkit end + + private void handleCommand(String s) { ++ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.startTiming(); // Spigot + // CraftBukkit start + CraftPlayer player = this.getPlayer(); + +@@ -983,19 +984,23 @@ public class PlayerConnection extends Connection { + this.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { ++ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot + return; + } + + try { + if (server.logCommands) logger.info(event.getPlayer().getName() + " issued server command: " + event.getMessage()); // Spigot + if (this.server.dispatchCommand(event.getPlayer(), event.getMessage().substring(1))) { ++ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot + return; + } + } catch (org.bukkit.command.CommandException ex) { + player.sendMessage(org.bukkit.ChatColor.RED + "An internal error occurred while attempting to perform this command"); + Logger.getLogger(PlayerConnection.class.getName()).log(Level.SEVERE, null, ex); ++ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot + return; + } ++ org.bukkit.craftbukkit.SpigotTimings.playerCommandTimer.stopTiming(); // Spigot + // CraftBukkit end + + /* CraftBukkit start - No longer needed as we have already handled it in server.dispatchServerCommand above. +diff --git a/src/main/java/net/minecraft/server/TileEntity.java b/src/main/java/net/minecraft/server/TileEntity.java +index d8eb6b9..b6b0d5f 100644 +--- a/src/main/java/net/minecraft/server/TileEntity.java ++++ b/src/main/java/net/minecraft/server/TileEntity.java +@@ -4,10 +4,12 @@ import java.util.HashMap; + import java.util.Map; + import java.util.concurrent.Callable; + ++import org.bukkit.CustomTimingsHandler; // Spigot + import org.bukkit.inventory.InventoryHolder; // CraftBukkit + + public class TileEntity { + ++ public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getTileEntityTimings(this); // Spigot + private static Map a = new HashMap(); + private static Map b = new HashMap(); + public World world; // CraftBukkit - protected -> public +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 41f4f31..ec1a08f 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -13,6 +13,7 @@ import java.util.concurrent.Callable; + // CraftBukkit start + import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.util.LongHashSet; ++import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.util.UnsafeList; + import org.bukkit.generator.ChunkGenerator; + import org.bukkit.craftbukkit.CraftServer; +@@ -114,6 +115,8 @@ public abstract class World implements IBlockAccess { + final Object chunkLock = new Object(); + private byte chunkTickRadius; + ++ public final SpigotTimings.WorldTimingsHandler timings; // Spigot ++ + public CraftWorld getWorld() { + return this.world; + } +@@ -193,6 +196,7 @@ public abstract class World implements IBlockAccess { + this.a(); + + this.getServer().addWorld(this.world); // CraftBukkit ++ timings = new SpigotTimings.WorldTimingsHandler(this); // Spigot + } + + protected abstract IChunkProvider j(); +@@ -1259,6 +1263,7 @@ public abstract class World implements IBlockAccess { + this.f.clear(); + this.methodProfiler.c("regular"); + ++ timings.entityTick.startTiming(); // Spigot + for (i = 0; i < this.entityList.size(); ++i) { + entity = (Entity) this.entityList.get(i); + +@@ -1281,7 +1286,9 @@ public abstract class World implements IBlockAccess { + this.methodProfiler.a("tick"); + if (!entity.dead) { + try { ++ SpigotTimings.tickEntityTimer.startTiming(); // Spigot + this.playerJoinedWorld(entity); ++ SpigotTimings.tickEntityTimer.stopTiming(); // Spigot + } catch (Throwable throwable1) { + crashreport = CrashReport.a(throwable1, "Ticking entity"); + crashreportsystemdetails = crashreport.a("Entity being ticked"); +@@ -1311,7 +1318,9 @@ public abstract class World implements IBlockAccess { + this.methodProfiler.b(); + } + ++ timings.entityTick.stopTiming(); // Spigot + this.methodProfiler.c("tileEntities"); ++ timings.tileEntityTick.startTiming(); // Spigot + this.M = true; + Iterator iterator = this.tileEntityList.iterator(); + +@@ -1326,8 +1335,11 @@ public abstract class World implements IBlockAccess { + + if (!tileentity.r() && tileentity.o() && this.isLoaded(tileentity.x, tileentity.y, tileentity.z)) { + try { ++ tileentity.tickTimer.startTiming(); // Spigot + tileentity.g(); ++ tileentity.tickTimer.stopTiming(); // Spigot + } catch (Throwable throwable2) { ++ tileentity.tickTimer.stopTiming(); // Spigot + crashreport = CrashReport.a(throwable2, "Ticking tile entity"); + crashreportsystemdetails = crashreport.a("Tile entity being ticked"); + if (tileentity == null) { +@@ -1352,6 +1364,8 @@ public abstract class World implements IBlockAccess { + } + } + ++ timings.tileEntityTick.stopTiming(); // Spigot ++ timings.tileEntityPending.startTiming(); // Spigot + this.M = false; + if (!this.b.isEmpty()) { + this.tileEntityList.removeAll(this.b); +@@ -1390,6 +1404,7 @@ public abstract class World implements IBlockAccess { + this.a.clear(); + } + ++ timings.tileEntityPending.stopTiming(); // Spigot + this.methodProfiler.b(); + this.methodProfiler.b(); + } +@@ -1412,6 +1427,7 @@ public abstract class World implements IBlockAccess { + byte b0 = 32; + + if (!flag || this.d(i - b0, 0, j - b0, i + b0, 0, j + b0)) { ++ entity.tickTimer.startTiming(); // Spigot + entity.T = entity.locX; + entity.U = entity.locY; + entity.V = entity.locZ; +@@ -1473,6 +1489,7 @@ public abstract class World implements IBlockAccess { + entity.passenger = null; + } + } ++ entity.tickTimer.stopTiming(); // Spigot + } + } + +diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java +index 4aa2a19..6cb3e24 100644 +--- a/src/main/java/net/minecraft/server/WorldServer.java ++++ b/src/main/java/net/minecraft/server/WorldServer.java +@@ -157,9 +157,12 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate + // CraftBukkit start - Only call spawner if we have players online and the world allows for mobs or animals + long time = this.worldData.getTime(); + if (this.getGameRules().getBoolean("doMobSpawning") && (this.allowMonsters || this.allowAnimals) && (this instanceof WorldServer && this.players.size() > 0)) { ++ timings.mobSpawn.startTiming(); // Spigot + SpawnerCreature.spawnEntities(this, this.allowMonsters && (this.ticksPerMonsterSpawns != 0 && time % this.ticksPerMonsterSpawns == 0L), this.allowAnimals && (this.ticksPerAnimalSpawns != 0 && time % this.ticksPerAnimalSpawns == 0L), this.worldData.getTime() % 400L == 0L); ++ timings.mobSpawn.stopTiming(); // Spigot + } + // CraftBukkit end ++ timings.doTickRest.startTiming(); // Spigot + this.methodProfiler.c("chunkSource"); + this.chunkProvider.unloadChunks(); + int j = this.a(1.0F); +@@ -186,6 +189,7 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate + this.V(); + + this.getWorld().processChunkGC(); // CraftBukkit ++ timings.doTickRest.stopTiming(); // Spigot + } + + public BiomeMeta a(EnumCreatureType enumcreaturetype, int i, int j, int k) { +diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +new file mode 100644 +index 0000000..df837a3 +--- /dev/null ++++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +@@ -0,0 +1,111 @@ ++package org.bukkit.craftbukkit; ++ ++import net.minecraft.server.*; ++import org.bukkit.CustomTimingsHandler; ++import org.bukkit.plugin.Plugin; ++import org.bukkit.scheduler.BukkitTask; ++ ++import java.util.HashMap; ++ ++public class SpigotTimings { ++ ++ public static final CustomTimingsHandler serverTickTimer = new CustomTimingsHandler("** Full Server Tick"); ++ public static final CustomTimingsHandler playerListTimer = new CustomTimingsHandler("Player List"); ++ public static final CustomTimingsHandler connectionTimer = new CustomTimingsHandler("Connection"); ++ public static final CustomTimingsHandler tickablesTimer = new CustomTimingsHandler("Tickables"); ++ public static final CustomTimingsHandler schedulerTimer = new CustomTimingsHandler("Scheduler"); ++ public static final CustomTimingsHandler chunkIOTickTimer = new CustomTimingsHandler("ChunkIOTick"); ++ public static final CustomTimingsHandler syncChunkLoadTimer = new CustomTimingsHandler("syncChunkLoad"); ++ ++ public static final CustomTimingsHandler entityMoveTimer = new CustomTimingsHandler("** entityMove"); ++ public static final CustomTimingsHandler tickEntityTimer = new CustomTimingsHandler("** tickEntity"); ++ public static final CustomTimingsHandler activatedEntityTimer = new CustomTimingsHandler("** activatedTickEntity"); ++ public static final CustomTimingsHandler tickTileEntityTimer = new CustomTimingsHandler("** tickTileEntity"); ++ ++ public static final CustomTimingsHandler timerEntityBaseTick = new CustomTimingsHandler("** livingEntityBaseTick"); ++ public static final CustomTimingsHandler timerEntityAI = new CustomTimingsHandler("** livingEntityAI"); ++ public static final CustomTimingsHandler timerEntityAICollision = new CustomTimingsHandler("** livingEntityAICollision"); ++ public static final CustomTimingsHandler timerEntityAIMove = new CustomTimingsHandler("** livingEntityAIMove"); ++ public static final CustomTimingsHandler timerEntityTickRest = new CustomTimingsHandler("** livingEntityTickRest"); ++ ++ public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); ++ ++ public static final HashMap entityTypeTimingMap = new HashMap(); ++ public static final HashMap tileEntityTypeTimingMap = new HashMap(); ++ public static final HashMap pluginTaskTimingMap = new HashMap(); ++ ++ /** ++ * Gets a timer associated with a plugins tasks. ++ * @param task ++ * @param period ++ * @return ++ */ ++ public static CustomTimingsHandler getPluginTaskTimings(BukkitTask task, long period) { ++ String plugin = task.getOwner().getDescription().getFullName(); ++ if (period > 0) { ++ String name = "Task: " + plugin +" Id:(interval:" + period + ":id:"+task.getTaskId()+")"; ++ return new CustomTimingsHandler(name); ++ } else { ++ String name = "Task: " + plugin + " Id:(Single)"; ++ CustomTimingsHandler result = pluginTaskTimingMap.get(name); ++ if (result == null) { ++ result = new CustomTimingsHandler(name); ++ pluginTaskTimingMap.put(name, result); ++ } ++ return result; ++ } ++ } ++ ++ /** ++ * Get a named timer for the specified entity type to track type specific timings. ++ * @param entity ++ * @return ++ */ ++ public static CustomTimingsHandler getEntityTimings(Entity entity) { ++ String entityType = entity.getClass().getSimpleName(); ++ CustomTimingsHandler result = entityTypeTimingMap.get(entityType); ++ if (result == null) { ++ result = new CustomTimingsHandler("** tickEntity - " + entityType, activatedEntityTimer); ++ entityTypeTimingMap.put(entityType, result); ++ } ++ return result; ++ } ++ ++ /** ++ * Get a named timer for the specified tile entity type to track type specific timings. ++ * @param entity ++ * @return ++ */ ++ public static CustomTimingsHandler getTileEntityTimings(TileEntity entity) { ++ String entityType = entity.getClass().getSimpleName(); ++ CustomTimingsHandler result = tileEntityTypeTimingMap.get(entityType); ++ if (result == null) { ++ result = new CustomTimingsHandler("** tickTileEntity - " + entityType, tickTileEntityTimer); ++ tileEntityTypeTimingMap.put(entityType, result); ++ } ++ return result; ++ } ++ ++ /** ++ * Set of timers per world, to track world specific timings. ++ */ ++ public static class WorldTimingsHandler { ++ public final CustomTimingsHandler mobSpawn; ++ public final CustomTimingsHandler doTickRest; ++ public final CustomTimingsHandler entityTick; ++ public final CustomTimingsHandler tileEntityTick; ++ public final CustomTimingsHandler tileEntityPending; ++ public final CustomTimingsHandler tracker; ++ ++ public WorldTimingsHandler(World server) { ++ String name = server.worldData.getName() +" - "; ++ ++ mobSpawn = new CustomTimingsHandler(name + "mobSpawn"); ++ doTickRest = new CustomTimingsHandler(name + "doTickRest"); ++ entityTick = new CustomTimingsHandler(name + "entityTick"); ++ tileEntityTick = new CustomTimingsHandler(name + "tileEntityTick"); ++ tileEntityPending = new CustomTimingsHandler(name + "tileEntityPending"); ++ tracker = new CustomTimingsHandler(name + "tracker"); ++ } ++ } ++} +diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +index 55db3ff..df134e3 100644 +--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java ++++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftTask.java +@@ -1,6 +1,8 @@ + package org.bukkit.craftbukkit.scheduler; + + import org.bukkit.Bukkit; ++import org.bukkit.craftbukkit.SpigotTimings; // Spigot ++import org.bukkit.CustomTimingsHandler; // Spigot + import org.bukkit.plugin.Plugin; + import org.bukkit.scheduler.BukkitTask; + +@@ -22,6 +24,7 @@ class CraftTask implements BukkitTask, Runnable { + private final Plugin plugin; + private final int id; + ++ CustomTimingsHandler timings = null; // Spigot + CraftTask() { + this(null, null, -1, -1); + } +@@ -50,7 +53,22 @@ class CraftTask implements BukkitTask, Runnable { + } + + public void run() { ++ // Spigot start - Wrap custom timings on Tasks ++ if (!Bukkit.getServer().getPluginManager().useTimings()) { ++ task.run(); ++ return; ++ } ++ if (timings == null && this.getOwner() != null && this.isSync()) { ++ timings = SpigotTimings.getPluginTaskTimings(this, period); ++ } ++ if (timings != null) { ++ timings.startTiming(); ++ } + task.run(); ++ if (timings != null) { ++ timings.stopTiming(); ++ } ++ // Spigot end + } + + long getPeriod() { +-- +1.8.1.1 + diff --git a/CraftBukkit-Patches/0017-Better-more-flexible-itemstack-merging.patch b/CraftBukkit-Patches/0018-Better-more-flexible-itemstack-merging.patch similarity index 95% rename from CraftBukkit-Patches/0017-Better-more-flexible-itemstack-merging.patch rename to CraftBukkit-Patches/0018-Better-more-flexible-itemstack-merging.patch index 30e62bf03..1f01abe02 100644 --- a/CraftBukkit-Patches/0017-Better-more-flexible-itemstack-merging.patch +++ b/CraftBukkit-Patches/0018-Better-more-flexible-itemstack-merging.patch @@ -1,4 +1,4 @@ -From f36116f21a496382c52e7cd3f0f97820c183fc49 Mon Sep 17 00:00:00 2001 +From a21753931b6180bc32da505ed261fce5ea0461c9 Mon Sep 17 00:00:00 2001 From: md_5 Date: Fri, 25 Jan 2013 18:24:54 +1100 Subject: [PATCH] Better + more flexible itemstack merging @@ -40,10 +40,10 @@ index a7baa0f..5e3ac84 100644 } } else { diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index c914461..88007c3 100644 +index ec1a08f..2fe9b1d 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java -@@ -923,31 +923,8 @@ public abstract class World implements IBlockAccess { +@@ -924,31 +924,8 @@ public abstract class World implements IBlockAccess { event = CraftEventFactory.callCreatureSpawnEvent((EntityLiving) entity, spawnReason); } else if (entity instanceof EntityItem) { event = CraftEventFactory.callItemSpawnEvent((EntityItem) entity); @@ -77,7 +77,7 @@ index c914461..88007c3 100644 EntityExperienceOrb xp = (EntityExperienceOrb) entity; double radius = this.getWorld().expMergeRadius; if (radius > 0) { -@@ -962,8 +939,8 @@ public abstract class World implements IBlockAccess { +@@ -963,8 +940,8 @@ public abstract class World implements IBlockAccess { } } } @@ -89,5 +89,5 @@ index c914461..88007c3 100644 event = CraftEventFactory.callProjectileLaunchEvent(entity); } -- -1.8.1-rc2 +1.8.1.1 diff --git a/CraftBukkit-Patches/0018-Add-oreobfuscator-for-Spigot.patch b/CraftBukkit-Patches/0019-Add-oreobfuscator-for-Spigot.patch similarity index 98% rename from CraftBukkit-Patches/0018-Add-oreobfuscator-for-Spigot.patch rename to CraftBukkit-Patches/0019-Add-oreobfuscator-for-Spigot.patch index f3cba7f2e..20ac57715 100644 --- a/CraftBukkit-Patches/0018-Add-oreobfuscator-for-Spigot.patch +++ b/CraftBukkit-Patches/0019-Add-oreobfuscator-for-Spigot.patch @@ -1,4 +1,4 @@ -From f7efe872d9e6c29ebdc4f8c9857a8724eee1300d Mon Sep 17 00:00:00 2001 +From 57dc2265b21dba57997f39f0ba07f6ca8a1fff5d Mon Sep 17 00:00:00 2001 From: lishid Date: Sat, 16 Feb 2013 10:05:25 +1100 Subject: [PATCH] Add oreobfuscator for Spigot. @@ -170,7 +170,7 @@ index 94e07fe..21bd64a 100644 public int cactusGrowthModifier = 100; diff --git a/src/main/java/org/bukkit/craftbukkit/OrebfuscatorManager.java b/src/main/java/org/bukkit/craftbukkit/OrebfuscatorManager.java new file mode 100644 -index 0000000..fe14f6d +index 0000000..5213f99 --- /dev/null +++ b/src/main/java/org/bukkit/craftbukkit/OrebfuscatorManager.java @@ -0,0 +1,146 @@ @@ -180,7 +180,7 @@ index 0000000..fe14f6d +import java.util.List; +import net.minecraft.server.Block; +import net.minecraft.server.World; -+import org.bukkit.event.CustomTimingsHandler; ++import org.bukkit.CustomTimingsHandler; + +public class OrebfuscatorManager { + @@ -321,10 +321,10 @@ index 0000000..fe14f6d + } +} diff --git a/src/main/java/org/bukkit/craftbukkit/Spigot.java b/src/main/java/org/bukkit/craftbukkit/Spigot.java -index 4a4f949..3bfeb49 100644 +index db46037..ad65bca 100644 --- a/src/main/java/org/bukkit/craftbukkit/Spigot.java +++ b/src/main/java/org/bukkit/craftbukkit/Spigot.java -@@ -13,6 +13,14 @@ public class Spigot { +@@ -15,6 +15,14 @@ public class Spigot { server.commandComplete = configuration.getBoolean("settings.command-complete", true); server.spamGuardExclusions = configuration.getStringList("settings.spam-exclusions"); @@ -354,5 +354,5 @@ index 0c92b66..78e9a66 100644 + disabled-worlds: + - world_the_end -- -1.8.1-rc2 +1.8.1.1 diff --git a/CraftBukkit-Patches/0019-Reduce-number-of-LivingEntity-collision-checks.patch b/CraftBukkit-Patches/0020-Reduce-number-of-LivingEntity-collision-checks.patch similarity index 87% rename from CraftBukkit-Patches/0019-Reduce-number-of-LivingEntity-collision-checks.patch rename to CraftBukkit-Patches/0020-Reduce-number-of-LivingEntity-collision-checks.patch index 9eaf78251..1973d4a3f 100644 --- a/CraftBukkit-Patches/0019-Reduce-number-of-LivingEntity-collision-checks.patch +++ b/CraftBukkit-Patches/0020-Reduce-number-of-LivingEntity-collision-checks.patch @@ -1,4 +1,4 @@ -From aedb805a7d9546c33994de3acee0da1814c0f6b5 Mon Sep 17 00:00:00 2001 +From a9525c7ac96f2692c584fcbd9c6469271e226364 Mon Sep 17 00:00:00 2001 From: Aikar Date: Fri, 18 Jan 2013 19:31:14 -0500 Subject: [PATCH] Reduce number of LivingEntity collision checks. @@ -8,10 +8,10 @@ Subject: [PATCH] Reduce number of LivingEntity collision checks. 1 file changed, 8 insertions(+) diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java -index b2481aa..bbbb008 100644 +index bd1aeaa..01b16ac 100644 --- a/src/main/java/net/minecraft/server/EntityLiving.java +++ b/src/main/java/net/minecraft/server/EntityLiving.java -@@ -1402,12 +1402,20 @@ public abstract class EntityLiving extends Entity { +@@ -1391,12 +1391,20 @@ public abstract class EntityLiving extends Entity { } protected void bd() { @@ -33,5 +33,5 @@ index b2481aa..bbbb008 100644 this.o(entity); } -- -1.8.1-rc2 +1.8.1.1 diff --git a/CraftBukkit-Patches/0020-Only-count-entities-in-chunks-being-processed-for-th.patch b/CraftBukkit-Patches/0021-Only-count-entities-in-chunks-being-processed-for-th.patch similarity index 98% rename from CraftBukkit-Patches/0020-Only-count-entities-in-chunks-being-processed-for-th.patch rename to CraftBukkit-Patches/0021-Only-count-entities-in-chunks-being-processed-for-th.patch index 3f4ebfcf6..45050799b 100644 --- a/CraftBukkit-Patches/0020-Only-count-entities-in-chunks-being-processed-for-th.patch +++ b/CraftBukkit-Patches/0021-Only-count-entities-in-chunks-being-processed-for-th.patch @@ -1,4 +1,4 @@ -From 7a0b264ffa3d6c7d4110f3e25059cc3f1bffee88 Mon Sep 17 00:00:00 2001 +From 0699ed06c2f350269703b4f2c62a268c80e1d9d2 Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 29 Jan 2013 13:25:53 -0500 Subject: [PATCH] Only count entities in chunks being processed for the spawn @@ -105,5 +105,5 @@ index 9b3e262..2173af7 100644 continue label110; } -- -1.8.1-rc2 +1.8.1.1 diff --git a/CraftBukkit-Patches/0021-Only-send-maps-in-item-frames-upon-tracking.patch b/CraftBukkit-Patches/0022-Only-send-maps-in-item-frames-upon-tracking.patch similarity index 98% rename from CraftBukkit-Patches/0021-Only-send-maps-in-item-frames-upon-tracking.patch rename to CraftBukkit-Patches/0022-Only-send-maps-in-item-frames-upon-tracking.patch index e70cccbd8..ea0ce39ea 100644 --- a/CraftBukkit-Patches/0021-Only-send-maps-in-item-frames-upon-tracking.patch +++ b/CraftBukkit-Patches/0022-Only-send-maps-in-item-frames-upon-tracking.patch @@ -1,4 +1,4 @@ -From d2a991ef24ccf92299160afc6a56128eed966733 Mon Sep 17 00:00:00 2001 +From 14f2f48d062b71bdd20a50cb8bbd3a7a8a0d3621 Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 19 Feb 2013 17:26:20 -0500 Subject: [PATCH] Only send maps in item frames upon tracking @@ -85,5 +85,5 @@ index a026c4c..75c146d 100644 } } -- -1.8.1-rc2 +1.8.1.1 diff --git a/CraftBukkit-Patches/0022-Detect-remove-and-warn-about-null-tile-entities.patch b/CraftBukkit-Patches/0023-Detect-remove-and-warn-about-null-tile-entities.patch similarity index 87% rename from CraftBukkit-Patches/0022-Detect-remove-and-warn-about-null-tile-entities.patch rename to CraftBukkit-Patches/0023-Detect-remove-and-warn-about-null-tile-entities.patch index e13c2db69..a482c74c9 100644 --- a/CraftBukkit-Patches/0022-Detect-remove-and-warn-about-null-tile-entities.patch +++ b/CraftBukkit-Patches/0023-Detect-remove-and-warn-about-null-tile-entities.patch @@ -1,4 +1,4 @@ -From 04cff8e45e1fe99b3679b15d672c41ac1de31ffb Mon Sep 17 00:00:00 2001 +From 5f8e123bf8262bf21389a5cac3396188c7097463 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 3 Feb 2013 09:20:19 +1100 Subject: [PATCH] Detect, remove and warn about null tile entities. @@ -8,10 +8,10 @@ Subject: [PATCH] Detect, remove and warn about null tile entities. 1 file changed, 7 insertions(+) diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 88007c3..9f05a52 100644 +index 2fe9b1d..4fc1233 100644 --- a/src/main/java/net/minecraft/server/World.java +++ b/src/main/java/net/minecraft/server/World.java -@@ -1302,6 +1302,13 @@ public abstract class World implements IBlockAccess { +@@ -1303,6 +1303,13 @@ public abstract class World implements IBlockAccess { while (iterator.hasNext()) { TileEntity tileentity = (TileEntity) iterator.next(); @@ -26,5 +26,5 @@ index 88007c3..9f05a52 100644 ChunkProviderServer chunkProviderServer = ((WorldServer) this).chunkProviderServer; if (chunkProviderServer.unloadQueue.contains(tileentity.x >> 4, tileentity.z >> 4)) { -- -1.8.1-rc2 +1.8.1.1 diff --git a/CraftBukkit-Patches/0024-Entity-Activation-Range-This-feature-gives-3-new-con.patch b/CraftBukkit-Patches/0024-Entity-Activation-Range-This-feature-gives-3-new-con.patch deleted file mode 100644 index ee2fd4788..000000000 --- a/CraftBukkit-Patches/0024-Entity-Activation-Range-This-feature-gives-3-new-con.patch +++ /dev/null @@ -1,327 +0,0 @@ -From 45fe88e1961a395c0330f1056ef602444cb963eb Mon Sep 17 00:00:00 2001 -From: Aikar -Date: Sat, 16 Feb 2013 19:45:09 +1100 -Subject: [PATCH] Entity Activation Range# This feature gives 3 new - configurable ranges that if an entity of the matching type is outside of this - radius of any player, will tick at 5% of its normal rate. - -This will drastically cut down on tick timings for entities that are not in range of a user to actually be "used". -This change can have dramatic impact on gameplay if configured too low. Balance according to your servers desired gameplay. ---- - src/main/java/net/minecraft/server/Entity.java | 8 ++ - .../java/net/minecraft/server/EntityArrow.java | 2 +- - src/main/java/net/minecraft/server/World.java | 3 +- - .../java/org/bukkit/craftbukkit/CraftWorld.java | 13 ++ - src/main/java/org/bukkit/craftbukkit/Spigot.java | 149 +++++++++++++++++++++ - .../java/org/bukkit/event/WorldTimingsHandler.java | 2 + - src/main/resources/configurations/bukkit.yml | 3 + - 7 files changed, 178 insertions(+), 2 deletions(-) - -diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index d0a58f8..9da5035 100644 ---- a/src/main/java/net/minecraft/server/Entity.java -+++ b/src/main/java/net/minecraft/server/Entity.java -@@ -111,6 +111,13 @@ public abstract class Entity { - public UUID uniqueId = UUID.randomUUID(); // CraftBukkit - public boolean valid = false; // CraftBukkit - -+ // Spigot start -+ public boolean inWater = false; -+ public final byte activationType = org.bukkit.craftbukkit.Spigot.initializeEntityActivationType(this); -+ public final boolean defaultActivationState = org.bukkit.craftbukkit.Spigot.initializeEntityActivationState(this); -+ public boolean isActivated = defaultActivationState; -+ // Spigot end -+ - public Entity(World world) { - this.id = entityCount++; - this.l = 1.0D; -@@ -862,6 +869,7 @@ public abstract class Entity { - this.ad = false; - } - -+ this.inWater = this.ad; // Spigot - return this.ad; - } - -diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java -index 916b9dc..bdd18f6 100644 ---- a/src/main/java/net/minecraft/server/EntityArrow.java -+++ b/src/main/java/net/minecraft/server/EntityArrow.java -@@ -16,7 +16,7 @@ public class EntityArrow extends Entity implements IProjectile { - private int f = -1; - private int g = 0; - private int h = 0; -- private boolean inGround = false; -+ public boolean inGround = false; // Spigot - private -> public - public int fromPlayer = 0; - public int shake = 0; - public Entity shooter; -diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java -index 9f05a52..b1ccf1f 100644 ---- a/src/main/java/net/minecraft/server/World.java -+++ b/src/main/java/net/minecraft/server/World.java -@@ -1241,6 +1241,7 @@ public abstract class World implements IBlockAccess { - this.methodProfiler.c("regular"); - timings.entityBaseTick.stopTiming(); // Spigot - -+ org.bukkit.craftbukkit.Spigot.activateEntities(this); // Spigot - timings.entityTick.startTiming(); // Spigot - for (i = 0; i < this.entityList.size(); ++i) { - entity = (Entity) this.entityList.get(i); -@@ -1404,7 +1405,7 @@ public abstract class World implements IBlockAccess { - int j = MathHelper.floor(entity.locZ); - byte b0 = 32; - -- if (!flag || this.d(i - b0, 0, j - b0, i + b0, 0, j + b0)) { -+ if (entity instanceof EntityFireworks || !flag || this.d(i - b0, 0, j - b0, i + b0, 0, j + b0)) { // Spigot - Not safe to skip a firework. - entity.T = entity.locX; - entity.U = entity.locY; - entity.V = entity.locZ; -diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -index 21bd64a..a083ae4 100644 ---- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java -@@ -100,6 +100,10 @@ public class CraftWorld implements World { - treeGrowthModifier = configuration.getInt("world-settings.default.tree-growth-modifier", treeGrowthModifier); - mushroomGrowthModifier = configuration.getInt("world-settings.default.mushroom-growth-modifier", mushroomGrowthModifier); - -+ miscEntityActivationRange = configuration.getInt("world-settings.default.entity-activation-range-misc", miscEntityActivationRange); -+ animalEntityActivationRange = configuration.getInt("world-settings.default.entity-activation-range-animals", animalEntityActivationRange); -+ monsterEntityActivationRange = configuration.getInt("world-settings.default.entity-activation-range-monsters", monsterEntityActivationRange); -+ - //override defaults with world specific, if they exist - growthPerTick = configuration.getInt("world-settings." + name + ".growth-chunks-per-tick", growthPerTick); - itemMergeRadius = configuration.getDouble("world-settings." + name + ".item-merge-radius", itemMergeRadius); -@@ -121,6 +125,10 @@ public class CraftWorld implements World { - - obfuscated = !world.getServer().orebfuscatorDisabledWorlds.contains(name); - -+ miscEntityActivationRange = configuration.getInt("world-settings." + name + ".entity-activation-range-misc", miscEntityActivationRange); -+ animalEntityActivationRange = configuration.getInt("world-settings." + name + ".entity-activation-range-animals", animalEntityActivationRange); -+ monsterEntityActivationRange = configuration.getInt("world-settings." + name + ".entity-activation-range-monsters", monsterEntityActivationRange); -+ - server.getLogger().info("-------------- Spigot ----------------"); - server.getLogger().info("-------- World Settings For [" + name + "] --------"); - server.getLogger().info("Growth Per Chunk: " + growthPerTick); -@@ -138,6 +146,7 @@ public class CraftWorld implements World { - server.getLogger().info("Mushroom Growth Modifier: " + mushroomGrowthModifier); - server.getLogger().info("View distance: " + viewDistance); - server.getLogger().info("Oreobfuscator: " + obfuscated); -+ server.getLogger().info("Entity Activation Range: An " + animalEntityActivationRange + " / Mo " + monsterEntityActivationRange + " / Mi " + miscEntityActivationRange); - server.getLogger().info("-------------------------------------------------"); - // Spigot end - } -@@ -158,6 +167,10 @@ public class CraftWorld implements World { - public int sugarGrowthModifier = 100; - public int treeGrowthModifier = 100; - public int mushroomGrowthModifier = 100; -+ -+ public int miscEntityActivationRange = 0; -+ public int animalEntityActivationRange = 0; -+ public int monsterEntityActivationRange = 0; - // Spigot end - - public Block getBlockAt(int x, int y, int z) { -diff --git a/src/main/java/org/bukkit/craftbukkit/Spigot.java b/src/main/java/org/bukkit/craftbukkit/Spigot.java -index ad65bca..bc28d7b 100644 ---- a/src/main/java/org/bukkit/craftbukkit/Spigot.java -+++ b/src/main/java/org/bukkit/craftbukkit/Spigot.java -@@ -1,7 +1,10 @@ - package org.bukkit.craftbukkit; - -+import java.util.ArrayList; -+import net.minecraft.server.*; - import org.bukkit.command.SimpleCommandMap; - import org.bukkit.configuration.file.YamlConfiguration; -+import java.util.List; - - public class Spigot { - -@@ -26,5 +29,151 @@ public class Spigot { - if (server.chunkGCPeriod == 0) { - server.getLogger().severe("[Spigot] You should not disable chunk-gc, unexpected behaviour may occur!"); - } -+ -+ } -+ -+ /** -+ * Initializes an entities type on construction to specify what group this -+ * entity is in for activation ranges. -+ * -+ * @param entity -+ * @return group id -+ */ -+ public static byte initializeEntityActivationType(Entity entity) { -+ if (entity instanceof EntityMonster || entity instanceof EntitySlime) { -+ return 1; // Monster -+ } else if (entity instanceof EntityCreature || entity instanceof EntityAmbient) { -+ return 2; // Animal -+ } else { -+ return 3; // Misc -+ } -+ } -+ -+ /** -+ * These entities are excluded from Activation range checks. -+ * -+ * @param entity -+ * @return boolean If it should always tick. -+ */ -+ public static boolean initializeEntityActivationState(Entity entity) { -+ if (entity instanceof EntityHuman -+ || entity instanceof EntityArrow -+ || entity instanceof EntityProjectile -+ || entity instanceof EntityEnderDragon -+ || entity instanceof EntityComplexPart -+ || entity instanceof EntityWither -+ || entity instanceof EntityFireball -+ || entity instanceof EntityWeather -+ || entity instanceof EntityTNTPrimed -+ || entity instanceof EntityEnderCrystal -+ || entity instanceof EntityFireworks) { -+ return true; -+ } -+ return false; -+ } -+ -+ /** -+ * Utility method to grow an AABB without creating a new AABB or touching -+ * the pool, so we can re-use ones we have. -+ * -+ * @param target -+ * @param source -+ * @param x -+ * @param y -+ * @param z -+ */ -+ public static void growBB(AxisAlignedBB target, AxisAlignedBB source, int x, int y, int z) { -+ target.a = source.a - x; -+ target.b = source.b - y; -+ target.c = source.c - z; -+ target.d = source.d + x; -+ target.e = source.e + y; -+ target.f = source.f + z; -+ } -+ -+ /** -+ * Find what entities are in range of the players in the world and set -+ * active if in range. -+ * -+ * @param world -+ */ -+ public static void activateEntities(World world) { -+ final int miscActivationRange = world.getWorld().miscEntityActivationRange; -+ final int animalActivationRange = world.getWorld().animalEntityActivationRange; -+ final int monsterActivationRange = world.getWorld().monsterEntityActivationRange; -+ -+ -+ world.timings.activationCheck.startTiming(); -+ int maxRange = Math.max(monsterActivationRange, animalActivationRange); -+ maxRange = Math.max(maxRange, miscActivationRange); -+ if (miscActivationRange == 0 || animalActivationRange == 0 || monsterActivationRange == 0) { -+ // One of them is disabled, set to view-distance -+ maxRange = world.getWorld().viewDistance << 4; -+ } else { -+ maxRange = Math.min(world.getWorld().viewDistance << 4, maxRange); // Do not tick on edge of unloaded chunks - vanilla behavior. -+ } -+ -+ AxisAlignedBB maxBB = AxisAlignedBB.a(0, 0, 0, 0, 0, 0); -+ AxisAlignedBB miscBB = AxisAlignedBB.a(0, 0, 0, 0, 0, 0); -+ AxisAlignedBB animalBB = AxisAlignedBB.a(0, 0, 0, 0, 0, 0); -+ AxisAlignedBB monsterBB = AxisAlignedBB.a(0, 0, 0, 0, 0, 0); -+ -+ for (Entity player : new ArrayList(world.players)) { -+ growBB(maxBB, player.boundingBox, maxRange, 256, maxRange); -+ growBB(miscBB, player.boundingBox, miscActivationRange, 256, miscActivationRange); -+ growBB(animalBB, player.boundingBox, animalActivationRange, 256, animalActivationRange); -+ growBB(monsterBB, player.boundingBox, monsterActivationRange, 256, monsterActivationRange); -+ -+ final List list = world.getEntities(player, maxBB); -+ for (Entity entity : list) { -+ if (!entity.defaultActivationState) { -+ boolean isInRange = false; -+ switch (entity.activationType) { -+ case 1: -+ if (monsterActivationRange == 0 || monsterBB.a(entity.boundingBox)) { -+ isInRange = true; -+ } -+ break; -+ case 2: -+ if (animalActivationRange == 0 || animalBB.a(entity.boundingBox)) { -+ isInRange = true; -+ } -+ break; -+ case 3: -+ default: -+ if (miscActivationRange == 0 || miscBB.a(entity.boundingBox)) { -+ isInRange = true; -+ } -+ } -+ -+ entity.isActivated = isInRange; -+ } -+ } -+ } -+ world.timings.activationCheck.stopTiming(); -+ } -+ -+ /** -+ * If an entity is not in range, do some more checks to see if we should -+ * give it a shot. -+ * -+ * @param entity -+ * @return -+ */ -+ public static boolean checkIfActive(Entity entity) { -+ // quick checks. -+ if (entity.ticksLived % 20 == 0 || !entity.onGround || entity.inWater || entity.passenger != null || entity.vehicle != null) { -+ return true; -+ } -+ // special cases. -+ if (entity instanceof EntityAnimal) { -+ EntityAnimal animal = (EntityAnimal) entity; -+ if (animal.isBaby() || animal.r() /*love*/) { -+ return true; -+ } -+ return (entity instanceof EntitySheep && ((EntitySheep) entity).isSheared()); -+ } -+ return (entity instanceof EntityArrow && !((EntityArrow) entity).inGround); -+ - } - } -diff --git a/src/main/java/org/bukkit/event/WorldTimingsHandler.java b/src/main/java/org/bukkit/event/WorldTimingsHandler.java -index bb0c191..6a4a05e 100644 ---- a/src/main/java/org/bukkit/event/WorldTimingsHandler.java -+++ b/src/main/java/org/bukkit/event/WorldTimingsHandler.java -@@ -8,6 +8,7 @@ public class WorldTimingsHandler { - public CustomTimingsHandler entityBaseTick; - public CustomTimingsHandler entityTick; - public CustomTimingsHandler tileEntityTick; -+ public CustomTimingsHandler activationCheck; - public WorldTimingsHandler(World server) { - String name = server.worldData.getName() +" - "; - -@@ -16,5 +17,6 @@ public class WorldTimingsHandler { - entityBaseTick = new CustomTimingsHandler(name + "entityBaseTick"); - entityTick = new CustomTimingsHandler(name + "entityTick"); - tileEntityTick = new CustomTimingsHandler(name + "tileEntityTick"); -+ activationCheck = new CustomTimingsHandler("** " + name + "activateEntities"); - } - } -diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml -index 78e9a66..54e28db 100644 ---- a/src/main/resources/configurations/bukkit.yml -+++ b/src/main/resources/configurations/bukkit.yml -@@ -46,6 +46,9 @@ world-settings: - sugar-growth-modifier: 100 - tree-growth-modifier: 100 - mushroom-growth-modifier: 100 -+ entity-activation-range-animals: 48 -+ entity-activation-range-monsters: 48 -+ entity-activation-range-misc: 16 - world: - growth-chunks-per-tick: 1000 - world_nether: --- -1.8.1-rc2 - diff --git a/CraftBukkit-Patches/0024-Entity-Activation-Range.patch b/CraftBukkit-Patches/0024-Entity-Activation-Range.patch new file mode 100644 index 000000000..56d7d3837 --- /dev/null +++ b/CraftBukkit-Patches/0024-Entity-Activation-Range.patch @@ -0,0 +1,444 @@ +From a4fdbca267e36d8b233d2922a0104b208c3af50d Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Sun, 3 Feb 2013 05:10:21 -0500 +Subject: [PATCH] Entity Activation Range + +This feature gives 3 new configurable ranges that if an entity of the matching type is outside of this radius of any player, will tick at 5% of its normal rate. + +This will drastically cut down on tick timings for entities that are not in range of a user to actually be "used". +This change can have dramatic impact on gameplay if configured too low. Balance according to your servers desired gameplay. +--- + src/main/java/net/minecraft/server/Entity.java | 9 +- + .../java/net/minecraft/server/EntityArrow.java | 2 +- + src/main/java/net/minecraft/server/EntityItem.java | 5 +- + src/main/java/net/minecraft/server/World.java | 14 +- + .../java/org/bukkit/craftbukkit/CraftWorld.java | 15 +- + src/main/java/org/bukkit/craftbukkit/Spigot.java | 219 +++++++++++++++++++++ + .../java/org/bukkit/craftbukkit/SpigotTimings.java | 3 + + src/main/resources/configurations/bukkit.yml | 3 + + 8 files changed, 259 insertions(+), 11 deletions(-) + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index bf9108a..807b4d1 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -89,7 +89,7 @@ public abstract class Entity { + public int ticksLived; + public int maxFireTicks; + public int fireTicks; // CraftBukkit - private -> public +- protected boolean ad; ++ public boolean ad; // Spigot - private -> public isInWater - If this renames, update Spigot.checkEntityImmunities + public int noDamageTicks; + private boolean justCreated; + protected boolean fireProof; +@@ -112,8 +112,14 @@ public abstract class Entity { + public UUID uniqueId = UUID.randomUUID(); // CraftBukkit + public boolean valid = false; // CraftBukkit + ++ // Spigot start + public CustomTimingsHandler tickTimer = org.bukkit.craftbukkit.SpigotTimings.getEntityTimings(this); // Spigot + ++ public final byte activationType = org.bukkit.craftbukkit.Spigot.initializeEntityActivationType(this); ++ public final boolean defaultActivationState; ++ public long activatedTick = 0; ++ // Spigot end ++ + public Entity(World world) { + this.id = entityCount++; + this.l = 1.0D; +@@ -150,6 +156,7 @@ public abstract class Entity { + this.invulnerable = false; + this.as = EnumEntitySize.SIZE_2; + this.world = world; ++ this.defaultActivationState = org.bukkit.craftbukkit.Spigot.initializeEntityActivationState(this, world.getWorld()); // Spigot + this.setPosition(0.0D, 0.0D, 0.0D); + if (world != null) { + this.dimension = world.worldProvider.dimension; +diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java +index 916b9dc..bdd18f6 100644 +--- a/src/main/java/net/minecraft/server/EntityArrow.java ++++ b/src/main/java/net/minecraft/server/EntityArrow.java +@@ -16,7 +16,7 @@ public class EntityArrow extends Entity implements IProjectile { + private int f = -1; + private int g = 0; + private int h = 0; +- private boolean inGround = false; ++ public boolean inGround = false; // Spigot - private -> public + public int fromPlayer = 0; + public int shake = 0; + public Entity shooter; +diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java +index 5e3ac84..fdfd763 100644 +--- a/src/main/java/net/minecraft/server/EntityItem.java ++++ b/src/main/java/net/minecraft/server/EntityItem.java +@@ -100,8 +100,9 @@ public class EntityItem extends Entity { + if (this.onGround) { + this.motY *= -0.5D; + } +- } // Spigot +- ++this.age; ++ } ++ this.age = ticksLived; ++ // Spigot + if (!this.world.isStatic && this.age >= 6000) { + // CraftBukkit start + if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) { +diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java +index 4fc1233..7d2bad3 100644 +--- a/src/main/java/net/minecraft/server/World.java ++++ b/src/main/java/net/minecraft/server/World.java +@@ -13,6 +13,7 @@ import java.util.concurrent.Callable; + // CraftBukkit start + import org.bukkit.Bukkit; + import org.bukkit.craftbukkit.util.LongHashSet; ++import org.bukkit.craftbukkit.Spigot; // Spigot + import org.bukkit.craftbukkit.SpigotTimings; // Spigot + import org.bukkit.craftbukkit.util.UnsafeList; + import org.bukkit.generator.ChunkGenerator; +@@ -1240,6 +1241,7 @@ public abstract class World implements IBlockAccess { + this.f.clear(); + this.methodProfiler.c("regular"); + ++ org.bukkit.craftbukkit.Spigot.activateEntities(this); // Spigot + timings.entityTick.startTiming(); // Spigot + for (i = 0; i < this.entityList.size(); ++i) { + entity = (Entity) this.entityList.get(i); +@@ -1406,12 +1408,12 @@ public abstract class World implements IBlockAccess { + } + + public void entityJoinedWorld(Entity entity, boolean flag) { +- int i = MathHelper.floor(entity.locX); +- int j = MathHelper.floor(entity.locZ); +- byte b0 = 32; +- +- if (!flag || this.d(i - b0, 0, j - b0, i + b0, 0, j + b0)) { +- entity.tickTimer.startTiming(); // Spigot ++ // Spigot start ++ if (!Spigot.checkIfActive(entity)) { ++ entity.ticksLived++; ++ } else { ++ entity.tickTimer.startTiming(); ++ // Spigot end + entity.T = entity.locX; + entity.U = entity.locY; + entity.V = entity.locZ; +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +index 21bd64a..33df602 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +@@ -100,10 +100,14 @@ public class CraftWorld implements World { + treeGrowthModifier = configuration.getInt("world-settings.default.tree-growth-modifier", treeGrowthModifier); + mushroomGrowthModifier = configuration.getInt("world-settings.default.mushroom-growth-modifier", mushroomGrowthModifier); + ++ miscEntityActivationRange = configuration.getInt("world-settings.default.entity-activation-range-misc"); ++ animalEntityActivationRange = configuration.getInt("world-settings.default.entity-activation-range-animals"); ++ monsterEntityActivationRange = configuration.getInt("world-settings.default.entity-activation-range-monsters"); ++ + //override defaults with world specific, if they exist + growthPerTick = configuration.getInt("world-settings." + name + ".growth-chunks-per-tick", growthPerTick); + itemMergeRadius = configuration.getDouble("world-settings." + name + ".item-merge-radius", itemMergeRadius); +- expMergeRadius = configuration.getDouble("world-settings." + name + ".exp-merge-radius", expMergeRadius); ++ expMergeRadius = configuration.getDouble("world-settings." + name + ".exp-merge-radius", expMergeRadius); + randomLightingUpdates = configuration.getBoolean("world-settings." + name + ".random-light-updates", randomLightingUpdates); + mobSpawnRange = configuration.getInt("world-settings." + name + ".mob-spawn-range", mobSpawnRange); + aggregateTicks = Math.max(1, configuration.getInt("world-settings." + name + ".aggregate-chunkticks", aggregateTicks)); +@@ -121,6 +125,10 @@ public class CraftWorld implements World { + + obfuscated = !world.getServer().orebfuscatorDisabledWorlds.contains(name); + ++ miscEntityActivationRange = configuration.getInt("world-settings." + name + ".entity-activation-range-misc", miscEntityActivationRange); ++ animalEntityActivationRange = configuration.getInt("world-settings." + name + ".entity-activation-range-animals", animalEntityActivationRange); ++ monsterEntityActivationRange = configuration.getInt("world-settings." + name + ".entity-activation-range-monsters", monsterEntityActivationRange); ++ + server.getLogger().info("-------------- Spigot ----------------"); + server.getLogger().info("-------- World Settings For [" + name + "] --------"); + server.getLogger().info("Growth Per Chunk: " + growthPerTick); +@@ -138,6 +146,7 @@ public class CraftWorld implements World { + server.getLogger().info("Mushroom Growth Modifier: " + mushroomGrowthModifier); + server.getLogger().info("View distance: " + viewDistance); + server.getLogger().info("Oreobfuscator: " + obfuscated); ++ server.getLogger().info("Entity Activation Range: An " + animalEntityActivationRange + " / Mo " + monsterEntityActivationRange + " / Mi " + miscEntityActivationRange); + server.getLogger().info("-------------------------------------------------"); + // Spigot end + } +@@ -158,6 +167,10 @@ public class CraftWorld implements World { + public int sugarGrowthModifier = 100; + public int treeGrowthModifier = 100; + public int mushroomGrowthModifier = 100; ++ ++ public int miscEntityActivationRange = 16; ++ public int animalEntityActivationRange = 32; ++ public int monsterEntityActivationRange = 32; + // Spigot end + + public Block getBlockAt(int x, int y, int z) { +diff --git a/src/main/java/org/bukkit/craftbukkit/Spigot.java b/src/main/java/org/bukkit/craftbukkit/Spigot.java +index ad65bca..572527f 100644 +--- a/src/main/java/org/bukkit/craftbukkit/Spigot.java ++++ b/src/main/java/org/bukkit/craftbukkit/Spigot.java +@@ -1,9 +1,16 @@ + package org.bukkit.craftbukkit; + ++import net.minecraft.server.*; + import org.bukkit.command.SimpleCommandMap; + import org.bukkit.configuration.file.YamlConfiguration; + ++import java.util.List; ++ + public class Spigot { ++ static AxisAlignedBB maxBB = AxisAlignedBB.a(0,0,0,0,0,0); ++ static AxisAlignedBB miscBB = AxisAlignedBB.a(0,0,0,0,0,0); ++ static AxisAlignedBB animalBB = AxisAlignedBB.a(0,0,0,0,0,0); ++ static AxisAlignedBB monsterBB = AxisAlignedBB.a(0,0,0,0,0,0); + + public static void initialize(CraftServer server, SimpleCommandMap commandMap, YamlConfiguration configuration) { + commandMap.register("bukkit", new org.bukkit.craftbukkit.command.TicksPerSecondCommand("tps")); +@@ -26,5 +33,217 @@ public class Spigot { + if (server.chunkGCPeriod == 0) { + server.getLogger().severe("[Spigot] You should not disable chunk-gc, unexpected behaviour may occur!"); + } ++ ++ } ++ ++ /** ++ * Initializes an entities type on construction to specify what group this ++ * entity is in for activation ranges. ++ * @param entity ++ * @return group id ++ */ ++ public static byte initializeEntityActivationType(Entity entity) { ++ if (entity instanceof EntityMonster || entity instanceof EntitySlime) { ++ return 1; // Monster ++ } else if (entity instanceof EntityCreature || entity instanceof EntityAmbient) { ++ return 2; // Animal ++ } else { ++ return 3; // Misc ++ } ++ } ++ ++ /** ++ * These entities are excluded from Activation range checks. ++ * ++ * @param entity ++ * @param world ++ * @return boolean If it should always tick. ++ */ ++ public static boolean initializeEntityActivationState(Entity entity, CraftWorld world) { ++ if ( (entity.activationType == 3 && world.miscEntityActivationRange == 0) ++ || (entity.activationType == 2 && world.animalEntityActivationRange == 0) ++ || (entity.activationType == 1 && world.monsterEntityActivationRange == 0) ++ || entity instanceof EntityHuman ++ || entity instanceof EntityItemFrame ++ || entity instanceof EntityProjectile ++ || entity instanceof EntityEnderDragon ++ || entity instanceof EntityComplexPart ++ || entity instanceof EntityWither ++ || entity instanceof EntityFireball ++ || entity instanceof EntityWeather ++ || entity instanceof EntityTNTPrimed ++ || entity instanceof EntityEnderCrystal ++ || entity instanceof EntityFireworks ++ ) { ++ return true; ++ } ++ ++ return false; ++ } ++ ++ /** ++ * Utility method to grow an AABB without creating a new AABB or touching ++ * the pool, so we can re-use ones we have. ++ * @param target ++ * @param source ++ * @param x ++ * @param y ++ * @param z ++ */ ++ public static void growBB(AxisAlignedBB target, AxisAlignedBB source, int x, int y, int z) { ++ target.a = source.a - x; ++ target.b = source.b - y; ++ target.c = source.c - z; ++ target.d = source.d + x; ++ target.e = source.e + y; ++ target.f = source.f + z; ++ } ++ ++ /** ++ * Find what entities are in range of the players in the world and set ++ * active if in range. ++ * @param world ++ */ ++ public static void activateEntities(World world) { ++ SpigotTimings.entityActivationCheckTimer.startTiming(); ++ final int miscActivationRange = world.getWorld().miscEntityActivationRange; ++ final int animalActivationRange = world.getWorld().animalEntityActivationRange; ++ final int monsterActivationRange = world.getWorld().monsterEntityActivationRange; ++ ++ int maxRange = Math.max(monsterActivationRange, animalActivationRange); ++ maxRange = Math.max(maxRange, miscActivationRange); ++ maxRange = Math.min((world.getWorld().viewDistance << 4) - 8, maxRange); ++ ++ for (Entity player : (List) world.players) { ++ ++ player.activatedTick = MinecraftServer.currentTick; ++ growBB(maxBB, player.boundingBox, maxRange, 256, maxRange); ++ growBB(miscBB, player.boundingBox, miscActivationRange, 256, miscActivationRange); ++ growBB(animalBB, player.boundingBox, animalActivationRange, 256, animalActivationRange); ++ growBB(monsterBB, player.boundingBox, monsterActivationRange, 256, monsterActivationRange); ++ ++ int i = MathHelper.floor(maxBB.a / 16.0D); ++ int j = MathHelper.floor(maxBB.d / 16.0D); ++ int k = MathHelper.floor(maxBB.c / 16.0D); ++ int l = MathHelper.floor(maxBB.f / 16.0D); ++ ++ for (int i1 = i; i1 <= j; ++i1) { ++ for (int j1 = k; j1 <= l; ++j1) { ++ if (world.getWorld().isChunkLoaded(i1, j1)) { ++ activateChunkEntities(world.getChunkAt(i1, j1)); ++ } ++ } ++ } ++ } ++ SpigotTimings.entityActivationCheckTimer.stopTiming(); ++ } ++ ++ /** ++ * Checks for the activation state of all entities in this chunk. ++ * @param chunk ++ */ ++ private static void activateChunkEntities(Chunk chunk) { ++ for (List slice : chunk.entitySlices) { ++ for (Entity entity : slice) { ++ if (MinecraftServer.currentTick > entity.activatedTick) { ++ if (entity.defaultActivationState) { ++ entity.activatedTick = MinecraftServer.currentTick; ++ continue; ++ } ++ switch (entity.activationType) { ++ case 1: ++ if (monsterBB.a(entity.boundingBox)) { ++ entity.activatedTick = MinecraftServer.currentTick; ++ } ++ break; ++ case 2: ++ if (animalBB.a(entity.boundingBox)) { ++ entity.activatedTick = MinecraftServer.currentTick; ++ } ++ break; ++ case 3: ++ default: ++ if (miscBB.a(entity.boundingBox)) { ++ entity.activatedTick = MinecraftServer.currentTick; ++ } ++ } ++ } ++ } ++ } ++ } ++ ++ /** ++ * If an entity is not in range, do some more checks to see if we should ++ * give it a shot. ++ * @param entity ++ * @return ++ */ ++ public static boolean checkEntityImmunities(Entity entity) { ++ // quick checks. ++ if (entity.ad /* isInWater */ || entity.fireTicks > 0) { ++ return true; ++ } ++ if (!(entity instanceof EntityArrow)) { ++ if (!entity.onGround || entity.passenger != null ++ || entity.vehicle != null) { ++ return true; ++ } ++ } else if (!((EntityArrow) entity).inGround) { ++ return true; ++ } ++ // special cases. ++ if (entity instanceof EntityLiving) { ++ EntityLiving living = (EntityLiving) entity; ++ if (living.attackTicks > 0 || living.hurtTicks > 0 || living.effects.size() > 0) { ++ return true; ++ } ++ if (entity instanceof EntityCreature && ((EntityCreature) entity).target != null) { ++ return true; ++ } ++ if (entity instanceof EntityAnimal) { ++ EntityAnimal animal = (EntityAnimal) entity; ++ if (animal.isBaby() || animal.r() /*love*/) { ++ return true; ++ } ++ if (entity instanceof EntitySheep && ((EntitySheep) entity).isSheared()) { ++ return true; ++ } ++ } ++ } ++ return false; ++ } ++ ++ /** ++ * Checks if the entity is active for this tick. ++ * @param entity ++ * @return ++ */ ++ public static boolean checkIfActive(Entity entity) { ++ SpigotTimings.checkIfActiveTimer.startTiming(); ++ int x = MathHelper.floor(entity.locX); ++ int z = MathHelper.floor(entity.locZ); ++ // Make sure not on edge of unloaded chunk ++ if (!entity.world.areChunksLoaded(x, 0, z, 16)) { ++ SpigotTimings.checkIfActiveTimer.stopTiming(); ++ return false; ++ } ++ boolean isActive = entity.activatedTick >= MinecraftServer.currentTick || entity.defaultActivationState; ++ ++ // Should this entity tick? ++ if (!isActive) { ++ if ((MinecraftServer.currentTick - entity.activatedTick - 1) % 20 == 0) { ++ // Check immunities every 20 ticks. ++ if (checkEntityImmunities(entity)) { ++ // Triggered some sort of immunity, give 20 full ticks before we check again. ++ entity.activatedTick = MinecraftServer.currentTick + 20; ++ } ++ isActive = true; ++ } ++ // Add a little performance juice to active entities. Skip 1/4 if not immune. ++ } else if (!entity.defaultActivationState && entity.ticksLived % 4 == 0 && !checkEntityImmunities(entity)) { ++ isActive = false; ++ } ++ SpigotTimings.checkIfActiveTimer.stopTiming(); ++ return isActive; + } + } +diff --git a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +index df837a3..9a1bcc5 100644 +--- a/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java ++++ b/src/main/java/org/bukkit/craftbukkit/SpigotTimings.java +@@ -30,6 +30,9 @@ public class SpigotTimings { + + public static final CustomTimingsHandler playerCommandTimer = new CustomTimingsHandler("** playerCommand"); + ++ public static final CustomTimingsHandler entityActivationCheckTimer = new CustomTimingsHandler("entityActivationCheck"); ++ public static final CustomTimingsHandler checkIfActiveTimer = new CustomTimingsHandler("** checkIfActive"); ++ + public static final HashMap entityTypeTimingMap = new HashMap(); + public static final HashMap tileEntityTypeTimingMap = new HashMap(); + public static final HashMap pluginTaskTimingMap = new HashMap(); +diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml +index 78e9a66..e568bf6 100644 +--- a/src/main/resources/configurations/bukkit.yml ++++ b/src/main/resources/configurations/bukkit.yml +@@ -46,6 +46,9 @@ world-settings: + sugar-growth-modifier: 100 + tree-growth-modifier: 100 + mushroom-growth-modifier: 100 ++ entity-activation-range-animals: 32 ++ entity-activation-range-monsters: 32 ++ entity-activation-range-misc: 16 + world: + growth-chunks-per-tick: 1000 + world_nether: +-- +1.8.1.1 + diff --git a/CraftBukkit-Patches/0027-Metrics.-Rewrite-the-Metrics-system-to-be-closer-to-.patch b/CraftBukkit-Patches/0027-Metrics.-Rewrite-the-Metrics-system-to-be-closer-to-.patch index 093d480e7..e4bcb5a19 100644 --- a/CraftBukkit-Patches/0027-Metrics.-Rewrite-the-Metrics-system-to-be-closer-to-.patch +++ b/CraftBukkit-Patches/0027-Metrics.-Rewrite-the-Metrics-system-to-be-closer-to-.patch @@ -1,27 +1,28 @@ -From ec31c15be3a7f53f13ec8e75a0480b3b956a16be Mon Sep 17 00:00:00 2001 +From 678a6d96738e6fa5ac3cacfc80ab621d3d99554e Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 23 Feb 2013 08:58:35 +1100 Subject: [PATCH] Metrics. Rewrite the Metrics system to be closer to the Bukkit version. --- - src/main/java/org/bukkit/craftbukkit/Spigot.java | 17 + + src/main/java/org/bukkit/craftbukkit/Spigot.java | 19 + src/main/java/org/spigotmc/Metrics.java | 645 +++++++++++++++++++++++ - 2 files changed, 662 insertions(+) + 2 files changed, 664 insertions(+) create mode 100644 src/main/java/org/spigotmc/Metrics.java diff --git a/src/main/java/org/bukkit/craftbukkit/Spigot.java b/src/main/java/org/bukkit/craftbukkit/Spigot.java -index bc28d7b..ced4bd4 100644 +index 572527f..3171411 100644 --- a/src/main/java/org/bukkit/craftbukkit/Spigot.java +++ b/src/main/java/org/bukkit/craftbukkit/Spigot.java -@@ -1,12 +1,19 @@ +@@ -1,10 +1,16 @@ package org.bukkit.craftbukkit; +import java.io.IOException; - import java.util.ArrayList; ++import java.util.ArrayList; import net.minecraft.server.*; import org.bukkit.command.SimpleCommandMap; import org.bukkit.configuration.file.YamlConfiguration; + import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; @@ -29,12 +30,18 @@ index bc28d7b..ced4bd4 100644 +import org.spigotmc.Metrics; public class Spigot { + static AxisAlignedBB maxBB = AxisAlignedBB.a(0,0,0,0,0,0); +@@ -12,6 +18,9 @@ public class Spigot { + static AxisAlignedBB animalBB = AxisAlignedBB.a(0,0,0,0,0,0); + static AxisAlignedBB monsterBB = AxisAlignedBB.a(0,0,0,0,0,0); + + public static boolean tabPing = false; + private static Metrics metrics; - ++ public static void initialize(CraftServer server, SimpleCommandMap commandMap, YamlConfiguration configuration) { commandMap.register("bukkit", new org.bukkit.craftbukkit.command.TicksPerSecondCommand("tps")); -@@ -30,6 +37,16 @@ public class Spigot { + +@@ -34,6 +43,16 @@ public class Spigot { server.getLogger().severe("[Spigot] You should not disable chunk-gc, unexpected behaviour may occur!"); } @@ -704,5 +711,5 @@ index 0000000..f1690a2 +} \ No newline at end of file -- -1.8.1-rc2 +1.8.1.1 diff --git a/CraftBukkit-Patches/0028-Watchdog-Thread.patch b/CraftBukkit-Patches/0028-Watchdog-Thread.patch index e97fe782b..da4b0cba2 100644 --- a/CraftBukkit-Patches/0028-Watchdog-Thread.patch +++ b/CraftBukkit-Patches/0028-Watchdog-Thread.patch @@ -1,31 +1,31 @@ -From bcc479e29c57f5e24066b2971a911e1e0aab02c7 Mon Sep 17 00:00:00 2001 +From 5a0d969c584b848bd8fcb62f4b3178c071801edb Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 23 Feb 2013 12:33:20 +1100 Subject: [PATCH] Watchdog Thread. --- .../java/net/minecraft/server/MinecraftServer.java | 2 + - src/main/java/org/bukkit/craftbukkit/Spigot.java | 77 +++++++++++++++++- + src/main/java/org/bukkit/craftbukkit/Spigot.java | 76 +++++++++++++++++- src/main/java/org/spigotmc/RestartCommand.java | 23 ++++++ src/main/java/org/spigotmc/WatchdogThread.java | 93 ++++++++++++++++++++++ src/main/resources/configurations/bukkit.yml | 3 + - 5 files changed, 196 insertions(+), 2 deletions(-) + 5 files changed, 195 insertions(+), 2 deletions(-) create mode 100644 src/main/java/org/spigotmc/RestartCommand.java create mode 100644 src/main/java/org/spigotmc/WatchdogThread.java diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 128016f..3a6b620 100644 +index aa6a14a..6005fac 100644 --- a/src/main/java/net/minecraft/server/MinecraftServer.java +++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -418,6 +418,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo - lastTick = curTime; - MinecraftServer.currentTick++; +@@ -421,6 +421,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo this.q(); + SpigotTimings.serverTickTimer.stopTiming(); + org.bukkit.CustomTimingsHandler.tick(); + org.spigotmc.WatchdogThread.tick(); } // Spigot end } else { -@@ -445,6 +446,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo +@@ -448,6 +449,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo this.a(crashreport); } finally { try { @@ -34,7 +34,7 @@ index 128016f..3a6b620 100644 this.isStopped = true; } catch (Throwable throwable1) { diff --git a/src/main/java/org/bukkit/craftbukkit/Spigot.java b/src/main/java/org/bukkit/craftbukkit/Spigot.java -index ced4bd4..15acc97 100644 +index 3171411..6f54f7e 100644 --- a/src/main/java/org/bukkit/craftbukkit/Spigot.java +++ b/src/main/java/org/bukkit/craftbukkit/Spigot.java @@ -1,5 +1,6 @@ @@ -44,8 +44,8 @@ index ced4bd4..15acc97 100644 import java.io.IOException; import java.util.ArrayList; import net.minecraft.server.*; -@@ -7,16 +8,20 @@ import org.bukkit.command.SimpleCommandMap; - import org.bukkit.configuration.file.YamlConfiguration; +@@ -8,9 +9,11 @@ import org.bukkit.configuration.file.YamlConfiguration; + import java.util.List; import java.util.logging.Level; -import java.util.logging.Logger; @@ -56,9 +56,8 @@ index ced4bd4..15acc97 100644 +import org.spigotmc.WatchdogThread; public class Spigot { -+ - public static boolean tabPing = false; - private static Metrics metrics; + static AxisAlignedBB maxBB = AxisAlignedBB.a(0,0,0,0,0,0); +@@ -23,6 +26,7 @@ public class Spigot { public static void initialize(CraftServer server, SimpleCommandMap commandMap, YamlConfiguration configuration) { commandMap.register("bukkit", new org.bukkit.craftbukkit.command.TicksPerSecondCommand("tps")); @@ -66,7 +65,7 @@ index ced4bd4..15acc97 100644 server.whitelistMessage = configuration.getString("settings.whitelist-message", server.whitelistMessage); server.stopMessage = configuration.getString("settings.stop-message", server.stopMessage); -@@ -25,12 +30,21 @@ public class Spigot { +@@ -31,12 +35,21 @@ public class Spigot { server.commandComplete = configuration.getBoolean("settings.command-complete", true); server.spamGuardExclusions = configuration.getStringList("settings.spam-exclusions"); @@ -89,9 +88,9 @@ index ced4bd4..15acc97 100644 } if (server.chunkGCPeriod == 0) { -@@ -193,4 +207,63 @@ public class Spigot { - return (entity instanceof EntityArrow && !((EntityArrow) entity).inGround); - +@@ -265,4 +278,63 @@ public class Spigot { + SpigotTimings.checkIfActiveTimer.stopTiming(); + return isActive; } + + public static void restart() { @@ -282,7 +281,7 @@ index 0000000..10390b8 + } +} diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml -index 54e28db..e04ebce 100644 +index e568bf6..7c18391 100644 --- a/src/main/resources/configurations/bukkit.yml +++ b/src/main/resources/configurations/bukkit.yml @@ -31,6 +31,9 @@ settings: @@ -296,5 +295,5 @@ index 54e28db..e04ebce 100644 default: growth-chunks-per-tick: 650 -- -1.8.1-rc2 +1.8.1.1 diff --git a/CraftBukkit-Patches/0029-Netty.patch b/CraftBukkit-Patches/0029-Netty.patch index 4ef5def86..ba72d05e0 100644 --- a/CraftBukkit-Patches/0029-Netty.patch +++ b/CraftBukkit-Patches/0029-Netty.patch @@ -1,4 +1,4 @@ -From d8aa2999094cf94e7a231d7ff5bd0b034ba5ba8a Mon Sep 17 00:00:00 2001 +From 9f7d30b2630ab0b4f7f3f650456f08dd6c6409b6 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 14 Feb 2013 17:32:20 +1100 Subject: [PATCH] Netty @@ -223,10 +223,10 @@ index 58d30eb..e4e5049 100644 // CraftBukkit end this.pendingConnection = pendingconnection; diff --git a/src/main/java/org/bukkit/craftbukkit/Spigot.java b/src/main/java/org/bukkit/craftbukkit/Spigot.java -index 15acc97..dbc3e48 100644 +index 6f54f7e..2ba6c14 100644 --- a/src/main/java/org/bukkit/craftbukkit/Spigot.java +++ b/src/main/java/org/bukkit/craftbukkit/Spigot.java -@@ -18,6 +18,8 @@ public class Spigot { +@@ -23,6 +23,8 @@ public class Spigot { public static boolean tabPing = false; private static Metrics metrics; @@ -235,7 +235,7 @@ index 15acc97..dbc3e48 100644 public static void initialize(CraftServer server, SimpleCommandMap commandMap, YamlConfiguration configuration) { commandMap.register("bukkit", new org.bukkit.craftbukkit.command.TicksPerSecondCommand("tps")); -@@ -53,6 +55,12 @@ public class Spigot { +@@ -58,6 +60,12 @@ public class Spigot { tabPing = configuration.getBoolean("settings.tab-ping", tabPing); @@ -1185,7 +1185,7 @@ index 0000000..5dc3754 + DATA; +} diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml -index e04ebce..7ccac52 100644 +index 7c18391..45a8a00 100644 --- a/src/main/resources/configurations/bukkit.yml +++ b/src/main/resources/configurations/bukkit.yml @@ -34,6 +34,8 @@ settings: @@ -1198,5 +1198,5 @@ index e04ebce..7ccac52 100644 default: growth-chunks-per-tick: 650 -- -1.8.1-rc2 +1.8.1.1 diff --git a/CraftBukkit-Patches/0030-Kick-player-on-exception-for-built-in-PluginChannels.patch b/CraftBukkit-Patches/0030-Kick-player-on-exception-for-built-in-PluginChannels.patch index 653ade811..1db74c8f1 100644 --- a/CraftBukkit-Patches/0030-Kick-player-on-exception-for-built-in-PluginChannels.patch +++ b/CraftBukkit-Patches/0030-Kick-player-on-exception-for-built-in-PluginChannels.patch @@ -1,4 +1,4 @@ -From 90a010f980ef943857f4437f64e76761ad6c37d3 Mon Sep 17 00:00:00 2001 +From f79f9c8a4b8dea443b5477c742d76f4ca8a780bb Mon Sep 17 00:00:00 2001 From: Eimref Date: Wed, 6 Feb 2013 18:59:07 -0500 Subject: [PATCH] Kick player on exception for built-in PluginChannels; Fixes @@ -9,10 +9,10 @@ Subject: [PATCH] Kick player on exception for built-in PluginChannels; Fixes 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java -index 7ca0acf..d1e0207 100644 +index d2c2305..b960a87 100644 --- a/src/main/java/net/minecraft/server/PlayerConnection.java +++ b/src/main/java/net/minecraft/server/PlayerConnection.java -@@ -1483,6 +1483,7 @@ public class PlayerConnection extends Connection { +@@ -1481,6 +1481,7 @@ public class PlayerConnection extends Connection { } } catch (Exception exception) { exception.printStackTrace(); @@ -20,7 +20,7 @@ index 7ca0acf..d1e0207 100644 } } else if ("MC|BSign".equals(packet250custompayload.tag)) { try { -@@ -1500,9 +1501,8 @@ public class PlayerConnection extends Connection { +@@ -1498,9 +1499,8 @@ public class PlayerConnection extends Connection { itemstack1.id = Item.WRITTEN_BOOK.id; } } catch (Exception exception1) { @@ -32,7 +32,7 @@ index 7ca0acf..d1e0207 100644 } } else { int i; -@@ -1518,6 +1518,7 @@ public class PlayerConnection extends Connection { +@@ -1516,6 +1516,7 @@ public class PlayerConnection extends Connection { } } catch (Exception exception2) { exception2.printStackTrace(); @@ -40,7 +40,7 @@ index 7ca0acf..d1e0207 100644 } } else { int j; -@@ -1541,6 +1542,7 @@ public class PlayerConnection extends Connection { +@@ -1539,6 +1540,7 @@ public class PlayerConnection extends Connection { } } catch (Exception exception3) { exception3.printStackTrace(); @@ -48,7 +48,7 @@ index 7ca0acf..d1e0207 100644 } } else { this.player.sendMessage(this.player.a("advMode.notAllowed", new Object[0])); -@@ -1564,6 +1566,7 @@ public class PlayerConnection extends Connection { +@@ -1562,6 +1564,7 @@ public class PlayerConnection extends Connection { } } catch (Exception exception4) { exception4.printStackTrace(); @@ -56,7 +56,7 @@ index 7ca0acf..d1e0207 100644 } } } else if ("MC|ItemName".equals(packet250custompayload.tag) && this.player.activeContainer instanceof ContainerAnvil) { -@@ -1588,6 +1591,7 @@ public class PlayerConnection extends Connection { +@@ -1586,6 +1589,7 @@ public class PlayerConnection extends Connection { } } catch (UnsupportedEncodingException ex) { Logger.getLogger(PlayerConnection.class.getName()).log(Level.SEVERE, "Could not parse REGISTER payload in plugin message packet", ex); @@ -64,7 +64,7 @@ index 7ca0acf..d1e0207 100644 } } else if (packet250custompayload.tag.equals("UNREGISTER")) { try { -@@ -1597,6 +1601,7 @@ public class PlayerConnection extends Connection { +@@ -1595,6 +1599,7 @@ public class PlayerConnection extends Connection { } } catch (UnsupportedEncodingException ex) { Logger.getLogger(PlayerConnection.class.getName()).log(Level.SEVERE, "Could not parse UNREGISTER payload in plugin message packet", ex); @@ -73,5 +73,5 @@ index 7ca0acf..d1e0207 100644 } else { server.getMessenger().dispatchIncomingMessage(player.getBukkitEntity(), packet250custompayload.tag, packet250custompayload.data); -- -1.8.1-rc2 +1.8.1.1