From a4b61ccc752cb8753c905c89156203b19b0871a0 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 2 Jun 2013 10:36:24 +1000 Subject: [PATCH 01/30] POM Changes --- pom.xml | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/pom.xml b/pom.xml index 4c5937ab..2e5420b4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,42 +1,21 @@ 4.0.0 - org.bukkit - bukkit + org.spigotmc + spigot-api 1.7.10-R0.1-SNAPSHOT - Bukkit - http://www.bukkit.org + Spigot-API + http://www.spigotmc.org UTF-8 - - scm:git:git@github.com:Bukkit/Bukkit.git - scm:git:git://github.com/Bukkit/Bukkit.git - https://github.com/Bukkit/Bukkit/tree/master/ - - - - jenkins - http://ci.bukkit.org - - - - - jd.bukkit.org - file:///home/javadocs/public_html/ - - - repobo-rel - repo.bukkit.org Releases - http://repo.bukkit.org/content/repositories/releases/ - - - repobo-snap - repo.bukkit.org Snapshots - http://repo.bukkit.org/content/repositories/snapshots/ - - + + org.spigotmc + spigot-parent + dev-SNAPSHOT + ../pom.xml + From ed13cc87470b8bf254cecef36d6675af4bbf120e Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 2 Jun 2013 10:42:57 +1000 Subject: [PATCH 02/30] Spigot Timings Adds performance tracking timings all around the Minecraft Server, and improves the usability of the /timings command Plugins can track their own timings with CustomTimingsHandler --- src/main/java/org/bukkit/Bukkit.java | 1 + src/main/java/org/bukkit/command/Command.java | 3 + .../org/bukkit/command/SimpleCommandMap.java | 4 + .../command/defaults/TimingsCommand.java | 133 +++++++++++++- .../bukkit/plugin/SimplePluginManager.java | 1 + .../bukkit/plugin/java/JavaPluginLoader.java | 7 +- .../org/spigotmc/CustomTimingsHandler.java | 165 ++++++++++++++++++ 7 files changed, 309 insertions(+), 5 deletions(-) create mode 100644 src/main/java/org/spigotmc/CustomTimingsHandler.java diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java index 1eaf92d7..7b25817e 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -301,6 +301,7 @@ public static MapView createMap(World world) { */ public static void reload() { server.reload(); + org.spigotmc.CustomTimingsHandler.reload(); // Spigot } /** diff --git a/src/main/java/org/bukkit/command/Command.java b/src/main/java/org/bukkit/command/Command.java index 87c33d9c..31e4f667 100644 --- a/src/main/java/org/bukkit/command/Command.java +++ b/src/main/java/org/bukkit/command/Command.java @@ -31,6 +31,7 @@ public abstract class Command { protected String usageMessage; private String permission; private String permissionMessage; + public org.spigotmc.CustomTimingsHandler timings; // Spigot protected Command(String name) { this(name, "", "/" + name, new ArrayList()); @@ -44,6 +45,7 @@ protected Command(String name, String description, String usageMessage, List(aliases); + this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot } /** @@ -200,6 +202,7 @@ public String getLabel() { public boolean setLabel(String name) { this.nextLabel = name; if (!isRegistered()) { + this.timings = new org.spigotmc.CustomTimingsHandler("** Command: " + name); // Spigot this.label = name; return true; } diff --git a/src/main/java/org/bukkit/command/SimpleCommandMap.java b/src/main/java/org/bukkit/command/SimpleCommandMap.java index d75380c8..f15b95da 100644 --- a/src/main/java/org/bukkit/command/SimpleCommandMap.java +++ b/src/main/java/org/bukkit/command/SimpleCommandMap.java @@ -176,11 +176,15 @@ public boolean dispatch(CommandSender sender, String commandLine) throws Command } try { + target.timings.startTiming(); // Spigot // Note: we don't return the result of target.execute as thats success / failure, we return handled (true) or not handled (false) target.execute(sender, sentCommandLabel, Arrays_copyOfRange(args, 1, args.length)); + target.timings.stopTiming(); // Spigot } catch (CommandException ex) { + target.timings.stopTiming(); // Spigot throw ex; } catch (Throwable ex) { + target.timings.stopTiming(); // Spigot throw new CommandException("Unhandled exception executing '" + commandLine + "' in " + target, ex); } diff --git a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java index 05cfcb01..22926d63 100644 --- a/src/main/java/org/bukkit/command/defaults/TimingsCommand.java +++ b/src/main/java/org/bukkit/command/defaults/TimingsCommand.java @@ -19,23 +19,97 @@ import com.google.common.collect.ImmutableList; +// Spigot start +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; + +import org.bukkit.command.RemoteConsoleCommandSender; +import org.bukkit.plugin.SimplePluginManager; +import org.spigotmc.CustomTimingsHandler; +// Spigot end + public class TimingsCommand extends BukkitCommand { - private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("merged", "reset", "separate"); + private static final List TIMINGS_SUBCOMMANDS = ImmutableList.of("report", "reset", "on", "off", "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.description = "Manages Spigot Timings data to see performance of the server."; // Spigot + this.usageMessage = "/timings "; // Spigot this.setPermission("bukkit.command.timings"); } + // Spigot start - redesigned Timings Command + public void executeSpigotTimings(CommandSender sender, String[] args) { + if ( "on".equals( args[0] ) ) + { + ( (SimplePluginManager) Bukkit.getPluginManager() ).useTimings( true ); + CustomTimingsHandler.reload(); + sender.sendMessage( "Enabled Timings & Reset" ); + return; + } else if ( "off".equals( args[0] ) ) + { + ( (SimplePluginManager) Bukkit.getPluginManager() ).useTimings( false ); + sender.sendMessage( "Disabled Timings" ); + return; + } + + if ( !Bukkit.getPluginManager().useTimings() ) + { + sender.sendMessage( "Please enable timings by typing /timings on" ); + return; + } + + boolean paste = "paste".equals( args[0] ); + if ("reset".equals(args[0])) { + CustomTimingsHandler.reload(); + sender.sendMessage("Timings reset"); + } else if ("merged".equals(args[0]) || "report".equals(args[0]) || paste) { + long sampleTime = System.nanoTime() - timingStart; + int index = 0; + File timingFolder = new File("timings"); + timingFolder.mkdirs(); + File timings = new File(timingFolder, "timings.txt"); + ByteArrayOutputStream bout = ( paste ) ? new ByteArrayOutputStream() : null; + while (timings.exists()) timings = new File(timingFolder, "timings" + (++index) + ".txt"); + PrintStream fileTimings = null; + try { + fileTimings = ( paste ) ? new PrintStream( bout ) : new PrintStream( timings ); + + CustomTimingsHandler.printTimings(fileTimings); + fileTimings.println( "Sample time " + sampleTime + " (" + sampleTime / 1E9 + "s)" ); + + if ( paste ) + { + new PasteThread( sender, bout ).start(); + return; + } + + sender.sendMessage("Timings written to " + timings.getPath()); + sender.sendMessage( "Paste contents of file into form at http://www.spigotmc.org/go/timings to read results." ); + + } catch (IOException e) { + } finally { + if (fileTimings != null) { + fileTimings.close(); + } + } + } + } + // Spigot end + @Override public boolean execute(CommandSender sender, String currentAlias, String[] args) { if (!testPermission(sender)) return true; - if (args.length != 1) { + if (args.length < 1) { // Spigot sender.sendMessage(ChatColor.RED + "Usage: " + usageMessage); return false; } + if (true) { executeSpigotTimings(sender, args); return true; } // Spigot if (!sender.getServer().getPluginManager().useTimings()) { sender.sendMessage("Please enable timings by setting \"settings.plugin-profiling\" to true in bukkit.yml"); return true; @@ -118,4 +192,55 @@ public List tabComplete(CommandSender sender, String alias, String[] arg } return ImmutableList.of(); } + + // Spigot start + private static class PasteThread extends Thread + { + + private final CommandSender sender; + private final ByteArrayOutputStream bout; + + public PasteThread(CommandSender sender, ByteArrayOutputStream bout) + { + super( "Timings paste thread" ); + this.sender = sender; + this.bout = bout; + } + + @Override + public synchronized void start() { + if (sender instanceof RemoteConsoleCommandSender) { + run(); + } else { + super.start(); + } + } + + @Override + public void run() + { + try + { + HttpURLConnection con = (HttpURLConnection) new URL( "http://paste.ubuntu.com/" ).openConnection(); + con.setDoOutput( true ); + con.setRequestMethod( "POST" ); + con.setInstanceFollowRedirects( false ); + + OutputStream out = con.getOutputStream(); + out.write( "poster=Spigot&syntax=text&content=".getBytes( "UTF-8" ) ); + out.write( URLEncoder.encode( bout.toString( "UTF-8" ), "UTF-8" ).getBytes( "UTF-8" ) ); + out.close(); + con.getInputStream().close(); + + String location = con.getHeaderField( "Location" ); + String pasteID = location.substring( "http://paste.ubuntu.com/".length(), location.length() - 1 ); + sender.sendMessage( ChatColor.GREEN + "View timings results can be viewed at http://www.spigotmc.org/go/timings?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/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java index d2fe422c..1d519080 100644 --- a/src/main/java/org/bukkit/plugin/SimplePluginManager.java +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -295,6 +295,7 @@ public Plugin[] loadPlugins(File directory) { } } + org.bukkit.command.defaults.TimingsCommand.timingStart = System.nanoTime(); // Spigot return result.toArray(new Plugin[result.size()]); } diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java index b178c0d1..6611342a 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java @@ -39,6 +39,7 @@ import org.bukkit.plugin.RegisteredListener; import org.bukkit.plugin.TimedRegisteredListener; import org.bukkit.plugin.UnknownDependencyException; +import org.spigotmc.CustomTimingsHandler; // Spigot import org.yaml.snakeyaml.error.YAMLException; /** @@ -49,6 +50,7 @@ public final class JavaPluginLoader implements PluginLoader { private final Pattern[] fileFilters = new Pattern[] { Pattern.compile("\\.jar$"), }; private final Map> classes = new HashMap>(); private final Map loaders = new LinkedHashMap(); + public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot /** * This class was not meant to be constructed explicitly @@ -283,13 +285,16 @@ public Map, Set> createRegisteredList } } + final CustomTimingsHandler timings = new CustomTimingsHandler("Plugin: " + plugin.getDescription().getFullName() + " Event: " + listener.getClass().getName() + "::" + method.getName()+"("+eventClass.getSimpleName()+")", pluginParentTimer); // Spigot EventExecutor executor = new EventExecutor() { public void execute(Listener listener, Event event) throws EventException { try { if (!eventClass.isAssignableFrom(event.getClass())) { return; } + timings.startTiming(); // Spigot method.invoke(listener, event); + timings.stopTiming(); // Spigot } catch (InvocationTargetException ex) { throw new EventException(ex.getCause()); } catch (Throwable t) { @@ -297,7 +302,7 @@ public void execute(Listener listener, Event event) throws EventException { } } }; - if (useTimings) { + if (false) { // Spigot - RL 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())); diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java new file mode 100644 index 00000000..8d982974 --- /dev/null +++ b/src/main/java/org/spigotmc/CustomTimingsHandler.java @@ -0,0 +1,165 @@ +package org.spigotmc; + +import org.bukkit.command.defaults.TimingsCommand; +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.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.bukkit.Bukkit; +import org.bukkit.World; + +/** + * Provides custom timing sections for /timings merged. + */ +public class CustomTimingsHandler +{ + + private static Queue HANDLERS = new ConcurrentLinkedQueue(); + /*========================================================================*/ + private final String name; + private final CustomTimingsHandler parent; + private long count = 0; + private long start = 0; + private long timingDepth = 0; + private long totalTime = 0; + private long curTickTotal = 0; + private long violations = 0; + + public CustomTimingsHandler(String name) + { + this( name, null ); + } + + public CustomTimingsHandler(String name, CustomTimingsHandler parent) + { + this.name = name; + this.parent = parent; + HANDLERS.add( this ); + } + + /** + * Prints the timings and extra data to the given stream. + * + * @param printStream + */ + public static void printTimings(PrintStream printStream) + { + printStream.println( "Minecraft" ); + for ( CustomTimingsHandler timings : HANDLERS ) + { + long time = timings.totalTime; + long count = timings.count; + if ( count == 0 ) + { + continue; + } + 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.getPluginManager().useTimings() ) + { + for ( CustomTimingsHandler timings : HANDLERS ) + { + timings.reset(); + } + } + TimingsCommand.timingStart = System.nanoTime(); + } + + /** + * Ticked every tick by CraftBukkit to count the number of times a timer + * caused TPS loss. + */ + public static void tick() + { + if ( Bukkit.getPluginManager().useTimings() ) + { + for ( CustomTimingsHandler timings : HANDLERS ) + { + if ( timings.curTickTotal > 50000000 ) + { + timings.violations += Math.ceil( timings.curTickTotal / 50000000 ); + } + timings.curTickTotal = 0; + timings.timingDepth = 0; // incase reset messes this up + } + } + } + + /** + * Starts timing to track a section of code. + */ + public void startTiming() + { + // If second condtion fails we are already timing + if ( Bukkit.getPluginManager().useTimings() && ++timingDepth == 1 ) + { + start = System.nanoTime(); + if ( parent != null && ++parent.timingDepth == 1 ) + { + parent.start = start; + } + } + } + + /** + * Stops timing a section of code. + */ + public void stopTiming() + { + if ( Bukkit.getPluginManager().useTimings() ) + { + if ( --timingDepth != 0 || start == 0 ) + { + return; + } + long diff = System.nanoTime() - start; + totalTime += diff; + curTickTotal += diff; + count++; + start = 0; + if ( parent != null ) + { + parent.stopTiming(); + } + } + } + + /** + * Reset this timer, setting all values to zero. + */ + public void reset() + { + count = 0; + violations = 0; + curTickTotal = 0; + totalTime = 0; + start = 0; + timingDepth = 0; + } +} From d03c0561e83dde724e68cbf80ad2d0385e1303ee Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 4 Mar 2013 18:31:20 +1100 Subject: [PATCH 03/30] Add PlayerItemDamageEvent --- .../event/player/PlayerItemDamageEvent.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java diff --git a/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java b/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java new file mode 100644 index 00000000..38a72ab8 --- /dev/null +++ b/src/main/java/org/bukkit/event/player/PlayerItemDamageEvent.java @@ -0,0 +1,54 @@ +package org.bukkit.event.player; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.inventory.ItemStack; + +public class PlayerItemDamageEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private final ItemStack item; + private int damage; + private boolean cancelled = false; + + public PlayerItemDamageEvent(Player player, ItemStack what, int damage) { + super(player); + this.item = what; + this.damage = damage; + } + + public ItemStack getItem() { + return item; + } + + /** + * Gets the amount of durability damage this item will be taking. + * + * @return durability change + */ + public int getDamage() { + return damage; + } + + public void setDamage(int damage) { + this.damage = damage; + } + + public boolean isCancelled() { + return cancelled; + } + + public void setCancelled(boolean cancel) { + this.cancelled = cancel; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} From 27c287bd36afc7229602d897fd6ff98c5f0cbf72 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 2 Jun 2013 15:20:49 +1000 Subject: [PATCH 04/30] BungeeCord Support --- src/main/java/org/bukkit/entity/Player.java | 19 +++++++++++++ .../bukkit/event/player/PlayerLoginEvent.java | 27 ++++++++++++++++--- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java index fe8a0bd7..e851b985 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1035,4 +1035,23 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline * @see Player#setHealthScaled(boolean) */ public double getHealthScale(); + + // Spigot start + public class Spigot extends Entity.Spigot + { + + /** + * Gets the connection address of this player, regardless of whether it + * has been spoofed or not. + * + * @return the player's connection address + */ + public InetSocketAddress getRawAddress() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + } + + Spigot spigot(); + // Spigot end } diff --git a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java index b74b7b89..081e994a 100644 --- a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java +++ b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java @@ -14,6 +14,7 @@ public class PlayerLoginEvent extends PlayerEvent { private final String hostname; private Result result = Result.ALLOWED; private String message = ""; + private final InetAddress realAddress; // Spigot /** * @deprecated Address should be provided in other constructor @@ -40,10 +41,17 @@ public PlayerLoginEvent(final Player player, final String hostname) { * @param address The address the player used to connect, provided for * timing issues */ - public PlayerLoginEvent(final Player player, final String hostname, final InetAddress address) { + public PlayerLoginEvent(final Player player, final String hostname, final InetAddress address, final InetAddress realAddress) { // Spigot super(player); this.hostname = hostname; this.address = address; + // Spigot start + this.realAddress = realAddress; + } + + public PlayerLoginEvent(final Player player, final String hostname, final InetAddress address) { + this(player, hostname, address, address); + // Spigot end } /** @@ -52,7 +60,7 @@ public PlayerLoginEvent(final Player player, final String hostname, final InetAd */ @Deprecated public PlayerLoginEvent(final Player player, final Result result, final String message) { - this(player, "", null, result, message); + this(player, "", null, result, message, null); // Spigot } /** @@ -65,12 +73,23 @@ public PlayerLoginEvent(final Player player, final Result result, final String m * @param result The result status for this event * @param message The message to be displayed if result denies login */ - public PlayerLoginEvent(final Player player, String hostname, final InetAddress address, final Result result, final String message) { - this(player, hostname, address); + public PlayerLoginEvent(final Player player, String hostname, final InetAddress address, final Result result, final String message, final InetAddress realAddress) { // Spigot + this(player, hostname, address, realAddress); // Spigot this.result = result; this.message = message; } + // Spigot start + /** + * Gets the connection address of this player, regardless of whether it has been spoofed or not. + * + * @return the player's connection address + */ + public InetAddress getRealAddress() { + return realAddress; + } + // Spigot end + /** * Gets the current result of the login, as an enum * From c7f688c441d9b68a21e4370f71209ff9f9114ced Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 2 Jun 2013 15:08:24 +1000 Subject: [PATCH 05/30] Add Arrow API --- src/main/java/org/bukkit/entity/Arrow.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/org/bukkit/entity/Arrow.java b/src/main/java/org/bukkit/entity/Arrow.java index e49eef07..e7a32f79 100644 --- a/src/main/java/org/bukkit/entity/Arrow.java +++ b/src/main/java/org/bukkit/entity/Arrow.java @@ -39,4 +39,20 @@ public interface Arrow extends Projectile { * @param critical whether or not it should be critical */ public void setCritical(boolean critical); + + public class Spigot extends Entity.Spigot + { + + public double getDamage() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + public void setDamage(double damage) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + } + + Spigot spigot(); } From d6d83112f5f6fc26b93bb2cdb7694466d6fbf040 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 2 Jun 2013 15:57:09 +1000 Subject: [PATCH 06/30] Add Particle API --- src/main/java/org/bukkit/Effect.java | 206 +++++++++++++++++++- src/main/java/org/bukkit/World.java | 50 +++++ src/main/java/org/bukkit/entity/Player.java | 5 + src/test/java/org/bukkit/EffectTest.java | 6 +- 4 files changed, 258 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/bukkit/Effect.java b/src/main/java/org/bukkit/Effect.java index 2474a2d9..37f29e2e 100644 --- a/src/main/java/org/bukkit/Effect.java +++ b/src/main/java/org/bukkit/Effect.java @@ -5,6 +5,7 @@ import com.google.common.collect.Maps; import org.bukkit.block.BlockFace; +import org.bukkit.material.MaterialData; import org.bukkit.potion.Potion; /** @@ -79,27 +80,188 @@ public enum Effect { /** * The flames seen on a mobspawner; a visual effect. */ - MOBSPAWNER_FLAMES(2004, Type.VISUAL); + MOBSPAWNER_FLAMES(2004, Type.VISUAL), + /** + * The spark that comes off a fireworks + */ + FIREWORKS_SPARK("fireworksSpark", Type.PARTICLE), + /** + * Critical hit particles + */ + CRIT("crit", Type.PARTICLE), + /** + * Blue critical hit particles + */ + MAGIC_CRIT("magicCrit", Type.PARTICLE), + /** + * Multicolored potion effect particles + */ + POTION_SWIRL("mobSpell", Type.PARTICLE), + /** + * Multicolored potion effect particles that are slightly transparent + */ + POTION_SWIRL_TRANSPARENT("mobSpellAmbient", Type.PARTICLE), + /** + * A puff of white potion swirls + */ + SPELL("spell", Type.PARTICLE), + /** + * A puff of white stars + */ + INSTANT_SPELL("instantSpell", Type.PARTICLE), + /** + * A puff of purple particles + */ + WITCH_MAGIC("witchMagic", Type.PARTICLE), + /** + * The note that appears above note blocks + */ + NOTE("note", Type.PARTICLE), + /** + * The particles shown at nether portals + */ + PORTAL("portal", Type.PARTICLE), + /** + * The symbols that fly towards the enchantment table + */ + FLYING_GLYPH("enchantmenttable", Type.PARTICLE), + /** + * Fire particles + */ + FLAME("flame", Type.PARTICLE), + /** + * The particles that pop out of lava + */ + LAVA_POP("lava", Type.PARTICLE), + /** + * A small gray square + */ + FOOTSTEP("footstep", Type.PARTICLE), + /** + * Water particles + */ + SPLASH("splash", Type.PARTICLE), + /** + * Smoke particles + */ + PARTICLE_SMOKE("smoke", Type.PARTICLE), + /** + * The biggest explosion particle effect + */ + EXPLOSION_HUGE("hugeexplosion", Type.PARTICLE), + /** + * A larger version of the explode particle + */ + EXPLOSION_LARGE("largeexplode", Type.PARTICLE), + /** + * Explosion particles + */ + EXPLOSION("explode", Type.PARTICLE), + /** + * Small gray particles + */ + VOID_FOG("depthsuspend", Type.PARTICLE), + /** + * Small gray particles + */ + SMALL_SMOKE("townaura", Type.PARTICLE), + /** + * A puff of white smoke + */ + CLOUD("cloud", Type.PARTICLE), + /** + * Multicolored dust particles + */ + COLOURED_DUST("reddust", Type.PARTICLE), + /** + * Snowball breaking + */ + SNOWBALL_BREAK("snowballpoof", Type.PARTICLE), + /** + * The water drip particle that appears on blocks under water + */ + WATERDRIP("dripWater", Type.PARTICLE), + /** + * The lava drip particle that appears on blocks under lava + */ + LAVADRIP("dripLava", Type.PARTICLE), + /** + * White particles + */ + SNOW_SHOVEL("snowshovel", Type.PARTICLE), + /** + * The particle shown when a slime jumps + */ + SLIME("slime", Type.PARTICLE), + /** + * The particle that appears when breading animals + */ + HEART("heart", Type.PARTICLE), + /** + * The particle that appears when hitting a villager + */ + VILLAGER_THUNDERCLOUD("angryVillager", Type.PARTICLE), + /** + * The particle that appears when trading with a villager + */ + HAPPY_VILLAGER("happyVillager", Type.PARTICLE), + /** + * The smoke particles that appears on blazes, minecarts + * with furnaces and fire + */ + LARGE_SMOKE("largesmoke", Type.PARTICLE), + /** + * The particles generated when a tool breaks. + * This particle requires a Material so that the client can select the correct texture. + */ + ITEM_BREAK("iconcrack", Type.PARTICLE, Material.class), + /** + * The particles generated while breaking a block. + * This particle requires a Material and data value so that the client can select the correct texture. + */ + TILE_BREAK("blockcrack", Type.PARTICLE, MaterialData.class), + /** + * The particles generated while sprinting a block + * This particle requires a Material and data value so that the client can select the correct texture. + */ + TILE_DUST("blockdust", Type.PARTICLE, MaterialData.class); private final int id; private final Type type; private final Class data; private static final Map BY_ID = Maps.newHashMap(); + private static final Map BY_NAME = Maps.newHashMap(); + private final String particleName; - Effect(int id, Type type) { + private Effect(int id, Type type) { this(id,type,null); } - Effect(int id, Type type, Class data) { + private Effect(int id, Type type, Class data) { this.id = id; this.type = type; this.data = data; + particleName = null; + } + + private Effect(String particleName, Type type, Class data) { + this.particleName = particleName; + this.type = type; + id = 0; + this.data = data; + } + + private Effect(String particleName, Type type) { + this.particleName = particleName; + this.type = type; + id = 0; + this.data = null; } /** * Gets the ID for this effect. * - * @return ID of this effect + * @return if this Effect isn't of type PARTICLE it returns ID of this effect * @deprecated Magic value */ @Deprecated @@ -107,6 +269,15 @@ public int getId() { return this.id; } + /** + * Returns the effect's name. This returns null if the effect is not a particle + * + * @return The effect's name + */ + public String getName() { + return particleName; + } + /** * @return The type of the effect. */ @@ -115,8 +286,7 @@ public Type getType() { } /** - * @return The class which represents data for this effect, or null if - * none + * @return if this Effect isn't of type PARTICLE it returns the class which represents data for this effect, or null if none */ public Class getData() { return this.data; @@ -136,12 +306,32 @@ public static Effect getById(int id) { static { for (Effect effect : values()) { - BY_ID.put(effect.id, effect); + if (effect.type != Type.PARTICLE) { + BY_ID.put(effect.id, effect); + } + } + } + + /** + * Gets the Effect associated with the given name. + * + * @param name name of the Effect to return + * @return Effect with the given name + */ + public static Effect getByName(String name) { + return BY_NAME.get(name); + } + + static { + for (Effect effect : values()) { + if (effect.type == Type.PARTICLE) { + BY_NAME.put(effect.particleName, effect); + } } } /** * Represents the type of an effect. */ - public enum Type {SOUND, VISUAL} + public enum Type {SOUND, VISUAL, PARTICLE} } diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java index 9bf2c41b..6cf3ff06 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -1155,6 +1155,56 @@ public interface World extends PluginMessageRecipient, Metadatable { */ public boolean isGameRule(String rule); + // Spigot start + public class Spigot + { + + /** + * Plays an effect to all players within a default radius around a given + * location. + * + * @param location the {@link Location} around which players must be to + * see the effect + * @param effect the {@link Effect} + * @throws IllegalArgumentException if the location or effect is null. + * It also throws when the effect requires a material or a material data + */ + public void playEffect(Location location, Effect effect) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + /** + * Plays an effect to all players within a default radius around a given + * location. The effect will use the provided material (and material + * data if required). The particle's position on the client will be the + * given location, adjusted on each axis by a normal distribution with + * mean 0 and standard deviation given in the offset parameters, each + * particle has independently calculated offsets. The effect will have + * the given speed and particle count if the effect is a particle. Some + * effect will create multiple particles. + * + * @param location the {@link Location} around which players must be to + * see the effect + * @param effect effect the {@link Effect} + * @param id the item/block/data id for the effect + * @param data the data value of the block/item for the effect + * @param offsetX the amount to be randomly offset by in the X axis + * @param offsetY the amount to be randomly offset by in the Y axis + * @param offsetZ the amount to be randomly offset by in the Z axis + * @param speed the speed of the particles + * @param particleCount the number of particles + * @param radius the radius around the location + */ + public void playEffect(Location location, Effect effect, int id, int data, float offsetX, float offsetY, float offsetZ, float speed, int particleCount, int radius) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + } + + Spigot spigot(); + // Spigot end + /** * Represents various map environment types that a world may be */ diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java index e851b985..c6bb7872 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1050,6 +1050,11 @@ public InetSocketAddress getRawAddress() { throw new UnsupportedOperationException( "Not supported yet." ); } + + public void playEffect(Location location, Effect effect, int id, int data, float offsetX, float offsetY, float offsetZ, float speed, int particleCount, int radius) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } } Spigot spigot(); diff --git a/src/test/java/org/bukkit/EffectTest.java b/src/test/java/org/bukkit/EffectTest.java index 08aa71d3..5217aecb 100644 --- a/src/test/java/org/bukkit/EffectTest.java +++ b/src/test/java/org/bukkit/EffectTest.java @@ -9,7 +9,11 @@ public class EffectTest { @Test public void getById() { for (Effect effect : Effect.values()) { - assertThat(Effect.getById(effect.getId()), is(effect)); + if (effect.getType() != Effect.Type.PARTICLE) { + assertThat(Effect.getById(effect.getId()), is(effect)); + } else { + assertThat(Effect.getByName(effect.getName()), is(effect)); + } } } } From 3f5ec07d746316b3ac2f4435c46a65d0fb3a42bd Mon Sep 17 00:00:00 2001 From: Andy Shulman Date: Mon, 15 Apr 2013 20:06:01 -0500 Subject: [PATCH 07/30] Define EntitySpawnEvent and SpawnerSpawnEvent Defines EntitySpawnEvent and SpawnerSpawnEvent. Adds BUKKIT-267 and BUKKIT-1559 --- .../event/entity/CreatureSpawnEvent.java | 32 +------------ .../bukkit/event/entity/EntitySpawnEvent.java | 45 +++++++++++++++++++ .../bukkit/event/entity/ItemSpawnEvent.java | 40 +++-------------- .../event/entity/SpawnerSpawnEvent.java | 22 +++++++++ 4 files changed, 74 insertions(+), 65 deletions(-) create mode 100644 src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java create mode 100644 src/main/java/org/bukkit/event/entity/SpawnerSpawnEvent.java diff --git a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java index 288e98bd..88831574 100644 --- a/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java +++ b/src/main/java/org/bukkit/event/entity/CreatureSpawnEvent.java @@ -4,17 +4,13 @@ import org.bukkit.entity.CreatureType; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; /** * Called when a creature is spawned into a world. *

* If a Creature Spawn event is cancelled, the creature will not spawn. */ -public class CreatureSpawnEvent extends EntityEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private boolean canceled; +public class CreatureSpawnEvent extends EntitySpawnEvent { private final SpawnReason spawnReason; public CreatureSpawnEvent(final LivingEntity spawnee, final SpawnReason spawnReason) { @@ -28,28 +24,11 @@ public CreatureSpawnEvent(Entity spawnee, CreatureType type, Location loc, Spawn spawnReason = reason; } - public boolean isCancelled() { - return canceled; - } - - public void setCancelled(boolean cancel) { - canceled = cancel; - } - @Override public LivingEntity getEntity() { return (LivingEntity) entity; } - /** - * Gets the location at which the creature is spawning. - * - * @return The location at which the creature is spawning - */ - public Location getLocation() { - return getEntity().getLocation(); - } - /** * Gets the type of creature being spawned. * @@ -72,15 +51,6 @@ public SpawnReason getSpawnReason() { return spawnReason; } - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } - /** * An enum to specify the type of spawning */ diff --git a/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java b/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java new file mode 100644 index 00000000..5dcf98f3 --- /dev/null +++ b/src/main/java/org/bukkit/event/entity/EntitySpawnEvent.java @@ -0,0 +1,45 @@ +package org.bukkit.event.entity; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.event.HandlerList; + +/** + * Called when an entity is spawned into a world. + *

+ * If an Entity Spawn event is cancelled, the entity will not spawn. + */ +public class EntitySpawnEvent extends EntityEvent implements org.bukkit.event.Cancellable { + private static final HandlerList handlers = new HandlerList(); + private boolean canceled; + + public EntitySpawnEvent(final Entity spawnee) { + super(spawnee); + } + + public boolean isCancelled() { + return canceled; + } + + public void setCancelled(boolean cancel) { + canceled = cancel; + } + + /** + * Gets the location at which the entity is spawning. + * + * @return The location at which the entity is spawning + */ + public Location getLocation() { + return getEntity().getLocation(); + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java b/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java index bafd934a..776f8e72 100644 --- a/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java +++ b/src/main/java/org/bukkit/event/entity/ItemSpawnEvent.java @@ -1,51 +1,23 @@ package org.bukkit.event.entity; -import org.bukkit.entity.Item; import org.bukkit.Location; -import org.bukkit.event.Cancellable; -import org.bukkit.event.HandlerList; +import org.bukkit.entity.Item; /** * Called when an item is spawned into a world */ -public class ItemSpawnEvent extends EntityEvent implements Cancellable { - private static final HandlerList handlers = new HandlerList(); - private final Location location; - private boolean canceled; - - public ItemSpawnEvent(final Item spawnee, final Location loc) { +public class ItemSpawnEvent extends EntitySpawnEvent { + public ItemSpawnEvent(final Item spawnee) { super(spawnee); - this.location = loc; } - public boolean isCancelled() { - return canceled; - } - - public void setCancelled(boolean cancel) { - canceled = cancel; + @Deprecated + public ItemSpawnEvent(final Item spawnee, final Location loc) { + this(spawnee); } @Override public Item getEntity() { return (Item) entity; } - - /** - * Gets the location at which the item is spawning. - * - * @return The location at which the item is spawning - */ - public Location getLocation() { - return location; - } - - @Override - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } } diff --git a/src/main/java/org/bukkit/event/entity/SpawnerSpawnEvent.java b/src/main/java/org/bukkit/event/entity/SpawnerSpawnEvent.java new file mode 100644 index 00000000..1acb3c40 --- /dev/null +++ b/src/main/java/org/bukkit/event/entity/SpawnerSpawnEvent.java @@ -0,0 +1,22 @@ +package org.bukkit.event.entity; + +import org.bukkit.block.CreatureSpawner; +import org.bukkit.entity.Entity; + +/** + * Called when an entity is spawned into a world by a spawner. + *

+ * If a Spawner Spawn event is cancelled, the entity will not spawn. + */ +public class SpawnerSpawnEvent extends EntitySpawnEvent { + private final CreatureSpawner spawner; + + public SpawnerSpawnEvent(final Entity spawnee, final CreatureSpawner spawner) { + super(spawnee); + this.spawner = spawner; + } + + public CreatureSpawner getSpawner() { + return spawner; + } +} From bd06b74349a813a7a08c3e6ff8ebbc3312ba1c30 Mon Sep 17 00:00:00 2001 From: md_5 Date: Tue, 2 Jul 2013 20:32:53 +1000 Subject: [PATCH 08/30] Entity Mount and Dismount Events --- .../event/entity/EntityDismountEvent.java | 39 ++++++++++++++ .../event/entity/EntityMountEvent.java | 52 +++++++++++++++++++ 2 files changed, 91 insertions(+) create mode 100644 src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java create mode 100644 src/main/java/org/spigotmc/event/entity/EntityMountEvent.java diff --git a/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java b/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java new file mode 100644 index 00000000..24d4942a --- /dev/null +++ b/src/main/java/org/spigotmc/event/entity/EntityDismountEvent.java @@ -0,0 +1,39 @@ +package org.spigotmc.event.entity; + +import org.bukkit.entity.Entity; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityEvent; + +/** + * Called when an entity stops riding another entity. + * + */ +public class EntityDismountEvent extends EntityEvent +{ + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final Entity dismounted; + + public EntityDismountEvent(Entity what, Entity dismounted) + { + super( what ); + this.dismounted = dismounted; + } + + public Entity getDismounted() + { + return dismounted; + } + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} diff --git a/src/main/java/org/spigotmc/event/entity/EntityMountEvent.java b/src/main/java/org/spigotmc/event/entity/EntityMountEvent.java new file mode 100644 index 00000000..16aa2a7e --- /dev/null +++ b/src/main/java/org/spigotmc/event/entity/EntityMountEvent.java @@ -0,0 +1,52 @@ +package org.spigotmc.event.entity; + +import org.bukkit.entity.Entity; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.entity.EntityEvent; + +/** + * Called when an entity attempts to ride another entity. + * + */ +public class EntityMountEvent extends EntityEvent implements Cancellable +{ + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled; + private final Entity mount; + + public EntityMountEvent(Entity what, Entity mount) + { + super( what ); + this.mount = mount; + } + + public Entity getMount() + { + return mount; + } + + @Override + public boolean isCancelled() + { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) + { + this.cancelled = cancel; + } + + @Override + public HandlerList getHandlers() + { + return handlers; + } + + public static HandlerList getHandlerList() + { + return handlers; + } +} From bc1667a6da739991a4dd236e564198c8946aba05 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 4 Jul 2013 20:05:19 +1000 Subject: [PATCH 09/30] Update Depends - All of these changes have been reviewed to be binary compatible and in general contract compatible with previous versions of the libraries. --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 2e5420b4..0c9f2433 100644 --- a/pom.xml +++ b/pom.xml @@ -76,21 +76,21 @@ org.yaml snakeyaml - 1.9 + 1.12 jar compile com.googlecode.json-simple json-simple - 1.1 + 1.1.1 jar compile org.avaje ebean - 2.7.3 + 2.8.1 jar compile @@ -104,7 +104,7 @@ commons-lang commons-lang - 2.3 + 2.6 From 1e9a6be94fc7bf711d3bb47088b106a22380eb46 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 7 Jul 2013 10:32:05 -0400 Subject: [PATCH 10/30] InventoryClickEvent getClickedInventory Add InventoryClickEvent.getClickedInventory. Adds BUKKIT-4495 Plugins currently have to do the logic themselves on the raw slot ID in order to determine the inventory clicked. This provides the logic for plugins to readily identify which inventory was clicked. --- .../event/inventory/InventoryClickEvent.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java b/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java index 28198b8b..3313d915 100644 --- a/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java +++ b/src/main/java/org/bukkit/event/inventory/InventoryClickEvent.java @@ -47,6 +47,7 @@ public class InventoryClickEvent extends InventoryInteractEvent { private static final HandlerList handlers = new HandlerList(); private final ClickType click; private final InventoryAction action; + private final Inventory clickedInventory; private SlotType slot_type; private int whichSlot; private int rawSlot; @@ -62,6 +63,13 @@ public InventoryClickEvent(InventoryView view, SlotType type, int slot, ClickTyp super(view); this.slot_type = type; this.rawSlot = slot; + if (slot < 0) { + this.clickedInventory = null; + } else if (view.getTopInventory() != null && slot < view.getTopInventory().getSize()) { + this.clickedInventory = view.getTopInventory(); + } else { + this.clickedInventory = view.getBottomInventory(); + } this.whichSlot = view.convertSlot(slot); this.click = click; this.action = action; @@ -72,6 +80,14 @@ public InventoryClickEvent(InventoryView view, SlotType type, int slot, ClickTyp this.hotbarKey = key; } + /** + * Gets the inventory that was clicked, or null if outside of window + * @return The clicked inventory + */ + public Inventory getClickedInventory() { + return clickedInventory; + } + /** * Gets the type of slot that was clicked. * From 7d0f86a24ab94c7b033d65013a02bd9020cc7948 Mon Sep 17 00:00:00 2001 From: Alex Bennett Date: Thu, 11 Jul 2013 15:31:32 -0500 Subject: [PATCH 11/30] Added getAllSessionData() to the Conversation API. --- .../org/bukkit/conversations/ConversationContext.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/bukkit/conversations/ConversationContext.java b/src/main/java/org/bukkit/conversations/ConversationContext.java index 4f33ff46..7390a771 100644 --- a/src/main/java/org/bukkit/conversations/ConversationContext.java +++ b/src/main/java/org/bukkit/conversations/ConversationContext.java @@ -45,6 +45,14 @@ public Conversable getForWhom() { return forWhom; } + /** + * Gets the entire sessionData map. + * @return The full sessionData map. + */ + public Map getAllSessionData() { + return sessionData; + } + /** * Gets session data shared between all {@link Prompt} invocations. Use * this as a way to pass data through each Prompt as the conversation From dd9483b4d46ea41df021fcdbc9635c197a1e363e Mon Sep 17 00:00:00 2001 From: md_5 Date: Mon, 22 Jul 2013 19:09:43 +1000 Subject: [PATCH 12/30] Catch Conversation API Errors --- src/main/java/org/bukkit/conversations/Conversation.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/org/bukkit/conversations/Conversation.java b/src/main/java/org/bukkit/conversations/Conversation.java index d4c1f6d3..46912c8f 100644 --- a/src/main/java/org/bukkit/conversations/Conversation.java +++ b/src/main/java/org/bukkit/conversations/Conversation.java @@ -209,6 +209,7 @@ public ConversationState getState() { * @param input The user's chat text. */ public void acceptInput(String input) { + try { // Spigot if (currentPrompt != null) { // Echo the user's input @@ -228,6 +229,12 @@ public void acceptInput(String input) { currentPrompt = currentPrompt.acceptInput(context, input); outputNextPrompt(); } + // Spigot Start + } catch ( Throwable t ) + { + org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.SEVERE, "Error handling conversation prompt", t ); + } + // Spigot End } /** From 4a68dc0abf462c4575d1fb0324c39d20adfac431 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 3 Aug 2013 19:20:50 +1000 Subject: [PATCH 13/30] Player Collision API --- src/main/java/org/bukkit/entity/Player.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java index c6bb7872..b879ecb4 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1055,6 +1055,27 @@ public void playEffect(Location location, Effect effect, int id, int data, float { throw new UnsupportedOperationException( "Not supported yet." ); } + + /** + * Gets whether the player collides with entities + * + * @return the player's collision toggle state + */ + public boolean getCollidesWithEntities() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + /** + * Sets whether the player collides with entities + * + * @param collides whether the player should collide with entities or + * not. + */ + public void setCollidesWithEntities(boolean collides) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } } Spigot spigot(); From a7d7357b5ccf70bf902cff31513f4b2840331aa4 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 3 Aug 2013 19:42:16 +1000 Subject: [PATCH 14/30] Expand Boolean Prompt Values --- src/main/java/org/bukkit/conversations/BooleanPrompt.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/bukkit/conversations/BooleanPrompt.java b/src/main/java/org/bukkit/conversations/BooleanPrompt.java index 3f2c97f4..81ef78cd 100644 --- a/src/main/java/org/bukkit/conversations/BooleanPrompt.java +++ b/src/main/java/org/bukkit/conversations/BooleanPrompt.java @@ -15,12 +15,13 @@ public BooleanPrompt() { @Override protected boolean isInputValid(ConversationContext context, String input) { - String[] accepted = {"true", "false", "on", "off", "yes", "no"}; + String[] accepted = {"true", "false", "on", "off", "yes", "no" /* Spigot: */, "y", "n", "1", "0", "right", "wrong", "correct", "incorrect", "valid", "invalid"}; // Spigot return ArrayUtils.contains(accepted, input.toLowerCase()); } @Override protected Prompt acceptValidatedInput(ConversationContext context, String input) { + if (input.equalsIgnoreCase("y") || input.equals("1") || input.equalsIgnoreCase("right") || input.equalsIgnoreCase("correct") || input.equalsIgnoreCase("valid")) input = "true"; // Spigot return acceptValidatedInput(context, BooleanUtils.toBoolean(input)); } From 1a0fa23c6367c7f574174dcef58575ed41d69eec Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 3 Aug 2013 19:49:36 +1000 Subject: [PATCH 15/30] Add Getter for Entity Invulnerability --- src/main/java/org/bukkit/entity/Entity.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/main/java/org/bukkit/entity/Entity.java b/src/main/java/org/bukkit/entity/Entity.java index 396ea208..294e80b4 100644 --- a/src/main/java/org/bukkit/entity/Entity.java +++ b/src/main/java/org/bukkit/entity/Entity.java @@ -291,4 +291,22 @@ public interface Entity extends Metadatable { * @return The current vehicle. */ public Entity getVehicle(); + + // Spigot Start + public class Spigot + { + + /** + * Returns whether this entity is invulnerable. + * + * @return True if the entity is invulnerable. + */ + public boolean isInvulnerable() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + } + + Spigot spigot(); + // Spigot End } From 8b2546fba7cc3e5148a9771382f463985a2eb71b Mon Sep 17 00:00:00 2001 From: ninja- Date: Tue, 8 Oct 2013 14:35:58 +0200 Subject: [PATCH 16/30] Add respawn API. --- src/main/java/org/bukkit/entity/Player.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java index b879ecb4..65592439 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1076,6 +1076,14 @@ public void setCollidesWithEntities(boolean collides) { throw new UnsupportedOperationException( "Not supported yet." ); } + + /** + * Respawns the player if dead. + */ + public void respawn() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } } Spigot spigot(); From 0d5e70ce77f1b4faa812ae12da2d65b0421c247a Mon Sep 17 00:00:00 2001 From: md_5 Date: Sat, 19 Oct 2013 12:59:42 +1100 Subject: [PATCH 17/30] Fix Plugin Message API Disconnects --- .../org/bukkit/plugin/messaging/StandardMessenger.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java b/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java index a906f8dd..4c171e88 100644 --- a/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java +++ b/src/main/java/org/bukkit/plugin/messaging/StandardMessenger.java @@ -421,7 +421,15 @@ public void dispatchIncomingMessage(Player source, String channel, byte[] messag Set registrations = getIncomingChannelRegistrations(channel); for (PluginMessageListenerRegistration registration : registrations) { - registration.getListener().onPluginMessageReceived(channel, source, message); + // Spigot Start + try + { + registration.getListener().onPluginMessageReceived( channel, source, message ); + } catch ( Throwable t ) + { + org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.WARNING, "Could not pass incoming plugin message to " + registration.getPlugin(), t ); + } + // Spigot End } } From 7677d9e6d3af21d4cdd63e5cb97dfdb25f9d684b Mon Sep 17 00:00:00 2001 From: md_5 Date: Tue, 24 Dec 2013 10:14:25 +1100 Subject: [PATCH 18/30] Fix Tab Completion for Some Commands --- .../org/bukkit/command/defaults/PluginsCommand.java | 8 ++++++++ .../org/bukkit/command/defaults/ReloadCommand.java | 8 ++++++++ .../org/bukkit/command/defaults/TellCommand.java | 12 ++++++++++++ .../org/bukkit/command/defaults/TestForCommand.java | 12 ++++++++++++ 4 files changed, 40 insertions(+) diff --git a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java index b888da13..e21d1679 100644 --- a/src/main/java/org/bukkit/command/defaults/PluginsCommand.java +++ b/src/main/java/org/bukkit/command/defaults/PluginsCommand.java @@ -40,4 +40,12 @@ private String getPluginList() { return "(" + plugins.length + "): " + pluginList.toString(); } + + // Spigot Start + @Override + public java.util.List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException + { + return java.util.Collections.emptyList(); + } + // Spigot End } diff --git a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java index fb3c90fb..a08ae804 100644 --- a/src/main/java/org/bukkit/command/defaults/ReloadCommand.java +++ b/src/main/java/org/bukkit/command/defaults/ReloadCommand.java @@ -25,4 +25,12 @@ public boolean execute(CommandSender sender, String currentAlias, String[] args) return true; } + + // Spigot Start + @Override + public java.util.List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException + { + return java.util.Collections.emptyList(); + } + // Spigot End } diff --git a/src/main/java/org/bukkit/command/defaults/TellCommand.java b/src/main/java/org/bukkit/command/defaults/TellCommand.java index 287f49f8..fc49207a 100644 --- a/src/main/java/org/bukkit/command/defaults/TellCommand.java +++ b/src/main/java/org/bukkit/command/defaults/TellCommand.java @@ -45,4 +45,16 @@ public boolean execute(CommandSender sender, String currentAlias, String[] args) return true; } + + // Spigot Start + @Override + public java.util.List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException + { + if ( args.length == 0 ) + { + return super.tabComplete( sender, alias, args ); + } + return java.util.Collections.emptyList(); + } + // Spigot End } diff --git a/src/main/java/org/bukkit/command/defaults/TestForCommand.java b/src/main/java/org/bukkit/command/defaults/TestForCommand.java index c9ac1cea..a687fef3 100644 --- a/src/main/java/org/bukkit/command/defaults/TestForCommand.java +++ b/src/main/java/org/bukkit/command/defaults/TestForCommand.java @@ -23,4 +23,16 @@ public boolean execute(CommandSender sender, String currentAlias, String[] args) sender.sendMessage(ChatColor.RED + "/testfor is only usable by commandblocks with analog output."); return true; } + + // Spigot Start + @Override + public java.util.List tabComplete(CommandSender sender, String alias, String[] args) throws IllegalArgumentException + { + if ( args.length == 0 ) + { + return super.tabComplete( sender, alias, args ); + } + return java.util.Collections.emptyList(); + } + // Spigot End } From 15b7016db900ae472355319178b2a729eaca5ac8 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 23 Jan 2014 13:17:38 +1100 Subject: [PATCH 19/30] Add Spigot Links --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a51766e6..1905b8d5 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -Bukkit +Spigot-API ====== A Minecraft Server API. -Website: [http://bukkit.org](http://bukkit.org) -Bugs/Suggestions: [http://leaky.bukkit.org](http://leaky.bukkit.org) -Contributing Guidelines: [CONTRIBUTING.md](https://github.com/Bukkit/Bukkit/blob/master/CONTRIBUTING.md) +Website: [http://spigotmc.org](http://spigotmc.org) +Bugs/Suggestions: [http://www.spigotmc.org/forums/bugs-feature-requests.8/](http://www.spigotmc.org/forums/bugs-feature-requests.8/) +Contributing Guidelines: [CONTRIBUTING.md](https://github.com/SpigotMC/Spigot-API/blob/master/CONTRIBUTING.md) Compilation ----------- From 892f708509b8ad25fa1f81ec5a506924f5d93282 Mon Sep 17 00:00:00 2001 From: Smove Date: Sat, 1 Feb 2014 18:10:49 +1100 Subject: [PATCH 20/30] Implement Locale Getter for Players --- src/main/java/org/bukkit/entity/Player.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java index 65592439..2cc19a79 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1084,6 +1084,16 @@ public void respawn() { throw new UnsupportedOperationException( "Not supported yet." ); } + + /** + * Gets player locale language. + * + * @return the player's client language settings + */ + public String getLocale() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } } Spigot spigot(); From db2459fa15abbcd5dc1d88e5fd2dc4a5a2b0fc3c Mon Sep 17 00:00:00 2001 From: Tux Date: Sun, 9 Feb 2014 14:02:11 -0500 Subject: [PATCH 21/30] Add support for fetching hidden players --- src/main/java/org/bukkit/entity/Player.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java index 2cc19a79..37c8a589 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -1094,6 +1094,16 @@ public String getLocale() { throw new UnsupportedOperationException( "Not supported yet." ); } + + /** + * Gets all players hidden with {@link hidePlayer(org.bukkit.entity.Player)}. + * + * @return a Set with all hidden players + */ + public java.util.Set getHiddenPlayers() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } } Spigot spigot(); From 2e53a3f3a4a221e1733c52bac6e11c4adf78f54e Mon Sep 17 00:00:00 2001 From: drXor Date: Sun, 23 Feb 2014 16:16:29 -0400 Subject: [PATCH 22/30] Silenceable Lightning API --- src/main/java/org/bukkit/World.java | 24 +++++++++++++++++++ .../org/bukkit/entity/LightningStrike.java | 17 +++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java index 6cf3ff06..ab731747 100644 --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java @@ -1200,6 +1200,30 @@ public void playEffect(Location location, Effect effect, int id, int data, float { throw new UnsupportedOperationException( "Not supported yet." ); } + + /** + * Strikes lightning at the given {@link Location} and possibly without sound + * + * @param loc The location to strike lightning + * @param isSilent Whether this strike makes no sound + * @return The lightning entity. + */ + public LightningStrike strikeLightning(Location loc, boolean isSilent) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + /** + * Strikes lightning at the given {@link Location} without doing damage and possibly without sound + * + * @param loc The location to strike lightning + * @param isSilent Whether this strike makes no sound + * @return The lightning entity. + */ + public LightningStrike strikeLightningEffect(Location loc, boolean isSilent) + { + throw new UnsupportedOperationException( "Not supported yet." ); + } } Spigot spigot(); diff --git a/src/main/java/org/bukkit/entity/LightningStrike.java b/src/main/java/org/bukkit/entity/LightningStrike.java index c8b5154e..1ed4ac98 100644 --- a/src/main/java/org/bukkit/entity/LightningStrike.java +++ b/src/main/java/org/bukkit/entity/LightningStrike.java @@ -12,4 +12,21 @@ public interface LightningStrike extends Weather { */ public boolean isEffect(); + + public class Spigot extends Entity.Spigot + { + + /* + * Returns whether the strike is silent. + * + * @return whether the strike is silent. + */ + public boolean isSilent() + { + throw new UnsupportedOperationException( "Not supported yet." ); + } + + } + + Spigot spigot(); } From 892ce3addd4617e845f5532ed7da4ca6828d3119 Mon Sep 17 00:00:00 2001 From: md_5 Date: Sun, 30 Mar 2014 15:58:22 +1100 Subject: [PATCH 23/30] Remove deprecation on some player lookup methods Most of these methods still have plenty of use given that only one player with each name can exist at a time. Deprecating these methods renders even basic functionality such as /msg impossible without causing compiler warnings. We will maintain this API and it should be considered safe and appropriate for most use cases. --- src/main/java/org/bukkit/Bukkit.java | 3 --- src/main/java/org/bukkit/Server.java | 9 --------- 2 files changed, 12 deletions(-) diff --git a/src/main/java/org/bukkit/Bukkit.java b/src/main/java/org/bukkit/Bukkit.java index 7b25817e..34f44af4 100644 --- a/src/main/java/org/bukkit/Bukkit.java +++ b/src/main/java/org/bukkit/Bukkit.java @@ -197,7 +197,6 @@ public static String getUpdateFolder() { /** * @see Server#getPlayer(String name) */ - @Deprecated public static Player getPlayer(String name) { return server.getPlayer(name); } @@ -205,7 +204,6 @@ public static Player getPlayer(String name) { /** * @see Server#matchPlayer(String name) */ - @Deprecated public static List matchPlayer(String name) { return server.matchPlayer(name); } @@ -448,7 +446,6 @@ public static OfflinePlayer getOfflinePlayer(UUID id) { /** * @see Server#getPlayerExact(String name) */ - @Deprecated public static Player getPlayerExact(String name) { return server.getPlayerExact(name); } diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java index e14e9f1d..14c8a8a7 100644 --- a/src/main/java/org/bukkit/Server.java +++ b/src/main/java/org/bukkit/Server.java @@ -308,23 +308,17 @@ public interface Server extends PluginMessageRecipient { *

* This method may not return objects for offline players. * - * @deprecated Use {@link #getPlayer(UUID)} as player names are no longer - * guaranteed to be unique * @param name the name to look up * @return a player if one was found, null otherwise */ - @Deprecated public Player getPlayer(String name); /** * Gets the player with the exact given name, case insensitive. * - * @deprecated Use {@link #getPlayer(UUID)} as player names are no longer - * guaranteed to be unique * @param name Exact name of the player to retrieve * @return a player object if one was found, null otherwise */ - @Deprecated public Player getPlayerExact(String name); /** @@ -334,12 +328,9 @@ public interface Server extends PluginMessageRecipient { * This list is not sorted in any particular order. If an exact match is * found, the returned list will only contain a single result. * - * @deprecated Use {@link #getPlayer(UUID)} as player names are no longer - * guaranteed to be unique * @param name the (partial) name to match * @return list of all possible players */ - @Deprecated public List matchPlayer(String name); /** From 23f195346b8d08160d46003bf53812a3fb0c19d7 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 17 Apr 2014 19:22:26 +1000 Subject: [PATCH 24/30] Expand team API to allow arbitrary strings. --- src/main/java/org/bukkit/scoreboard/Team.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/main/java/org/bukkit/scoreboard/Team.java b/src/main/java/org/bukkit/scoreboard/Team.java index 50c6f762..b90b9c3a 100644 --- a/src/main/java/org/bukkit/scoreboard/Team.java +++ b/src/main/java/org/bukkit/scoreboard/Team.java @@ -118,6 +118,15 @@ public interface Team { */ Set getPlayers() throws IllegalStateException; + // Spigot start + /** + * Same as the player method, but with an arbitrary string. + * + * @see #getPlayers() + */ + Set getEntries() throws IllegalStateException; + // Spigot End + /** * Gets the size of the team * @@ -145,6 +154,15 @@ public interface Team { */ void addPlayer(OfflinePlayer player) throws IllegalStateException, IllegalArgumentException; + // Spigot start + /** + * Same as the player method, but with an arbitrary string. + * + * @see #addPlayer(org.bukkit.OfflinePlayer) + */ + void addEntry(String entry) throws IllegalStateException, IllegalArgumentException; + // Spigot end + /** * Removes the player from this team. * @@ -155,6 +173,15 @@ public interface Team { */ boolean removePlayer(OfflinePlayer player) throws IllegalStateException, IllegalArgumentException; + // Spigot start + /** + * Same as the player method, but with an arbitrary string. + * + * @see #removePlayer(org.bukkit.OfflinePlayer) + */ + boolean removeEntry(String entry) throws IllegalStateException, IllegalArgumentException; + // Spigot end + /** * Unregisters this team from the Scoreboard * @@ -171,4 +198,13 @@ public interface Team { * @throws IllegalStateException if this team has been unregistered */ boolean hasPlayer(OfflinePlayer player) throws IllegalArgumentException, IllegalStateException; + + // Spigot start + /** + * Same as the player method, but with an arbitrary string. + * + * @see #hasPlayer(org.bukkit.OfflinePlayer) + */ + boolean hasEntry(String entry) throws IllegalArgumentException,IllegalStateException; + // Spigot end } From b6cddde8c0877e34e802e521c88df6418fedf150 Mon Sep 17 00:00:00 2001 From: md_5 Date: Thu, 17 Apr 2014 19:35:13 +1000 Subject: [PATCH 25/30] Add Score.isScoreSet()Z API. --- src/main/java/org/bukkit/scoreboard/Score.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/org/bukkit/scoreboard/Score.java b/src/main/java/org/bukkit/scoreboard/Score.java index 4c103468..2410cbd1 100644 --- a/src/main/java/org/bukkit/scoreboard/Score.java +++ b/src/main/java/org/bukkit/scoreboard/Score.java @@ -51,6 +51,17 @@ public interface Score { */ void setScore(int score) throws IllegalStateException; + // Spigot start + /** + * Shows if this score has been set at any point in time. + * + * @return if this score has been set before + * @throws IllegalStateException if the associated objective has been + * unregistered + */ + boolean isScoreSet() throws IllegalStateException; + // Spigot end + /** * Gets the scoreboard for the associated objective. * From a9c9f2f67d26ebfdd0ddd6756cac422fdb94944f Mon Sep 17 00:00:00 2001 From: ninja Date: Tue, 8 Apr 2014 14:01:32 +0200 Subject: [PATCH 26/30] Add PlayerSpawnLocationEvent. --- .../player/PlayerSpawnLocationEvent.java | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/main/java/org/spigotmc/event/player/PlayerSpawnLocationEvent.java diff --git a/src/main/java/org/spigotmc/event/player/PlayerSpawnLocationEvent.java b/src/main/java/org/spigotmc/event/player/PlayerSpawnLocationEvent.java new file mode 100644 index 00000000..dd3f58ca --- /dev/null +++ b/src/main/java/org/spigotmc/event/player/PlayerSpawnLocationEvent.java @@ -0,0 +1,50 @@ +package org.spigotmc.event.player; + +import org.bukkit.Location; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; + +/** + * Called when player is about to spawn in a world after joining the server. + */ +public class PlayerSpawnLocationEvent extends PlayerEvent { + private static final HandlerList handlers = new HandlerList(); + private Location spawnLocation; + + public PlayerSpawnLocationEvent(final Player who, Location spawnLocation) { + super(who); + this.spawnLocation = spawnLocation; + } + + + /** + * Gets player's spawn location. + * If the player {@link Player#hasPlayedBefore()}, it's going to default to the location inside player.dat file. + * For new players, the default spawn location is spawn of the main Bukkit world. + * + * @return the spawn location + */ + public Location getSpawnLocation() { + return spawnLocation; + } + + /** + * Sets player's spawn location. + * + * @param location the spawn location + */ + public void setSpawnLocation(Location location) { + this.spawnLocation = location; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} From 57f5c65d68a8a590d29208e2b11cde2defeb9804 Mon Sep 17 00:00:00 2001 From: md_5 Date: Wed, 16 Jul 2014 17:24:21 +1000 Subject: [PATCH 27/30] Ease ClassLoader Deadlocks Where Possible When on Java 7 we can register the classloader as parallel capable to prevent deadlocks caused by certain scenarios. Due to the nature of PluginClassLoader this isn't completely safe, but we can make it safer by switching to concurrency focused collections. Either way this is far better than crashing the server. --- .../bukkit/plugin/java/JavaPluginLoader.java | 2 +- .../bukkit/plugin/java/PluginClassLoader.java | 26 ++++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java index 6611342a..a845e818 100644 --- a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java @@ -48,7 +48,7 @@ public final class JavaPluginLoader implements PluginLoader { final Server server; private final Pattern[] fileFilters = new Pattern[] { Pattern.compile("\\.jar$"), }; - private final Map> classes = new HashMap>(); + private final Map> classes = new java.util.concurrent.ConcurrentHashMap>(); // Spigot private final Map loaders = new LinkedHashMap(); public static final CustomTimingsHandler pluginParentTimer = new CustomTimingsHandler("** Plugins"); // Spigot diff --git a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java index 13f86338..4cffa137 100644 --- a/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java +++ b/src/main/java/org/bukkit/plugin/java/PluginClassLoader.java @@ -17,7 +17,7 @@ */ final class PluginClassLoader extends URLClassLoader { private final JavaPluginLoader loader; - private final Map> classes = new HashMap>(); + private final Map> classes = new java.util.concurrent.ConcurrentHashMap>(); // Spigot private final PluginDescriptionFile description; private final File dataFolder; private final File file; @@ -25,6 +25,30 @@ final class PluginClassLoader extends URLClassLoader { private JavaPlugin pluginInit; private IllegalStateException pluginState; + // Spigot Start + static + { + try + { + java.lang.reflect.Method method = ClassLoader.class.getDeclaredMethod( "registerAsParallelCapable" ); + if ( method != null ) + { + boolean oldAccessible = method.isAccessible(); + method.setAccessible( true ); + method.invoke( null ); + method.setAccessible( oldAccessible ); + org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.INFO, "Set PluginClassLoader as parallel capable" ); + } + } catch ( NoSuchMethodException ex ) + { + // Ignore + } catch ( Exception ex ) + { + org.bukkit.Bukkit.getLogger().log( java.util.logging.Level.WARNING, "Error setting PluginClassLoader as parallel capable", ex ); + } + } + // Spigot End + PluginClassLoader(final JavaPluginLoader loader, final ClassLoader parent, final PluginDescriptionFile description, final File dataFolder, final File file) throws InvalidPluginException, MalformedURLException { super(new URL[] {file.toURI().toURL()}, parent); Validate.notNull(loader, "Loader cannot be null"); From f78e555343b8566004e4bfaa8aa5e87c363943f8 Mon Sep 17 00:00:00 2001 From: md_5 Date: Tue, 22 Jul 2014 21:01:32 +1000 Subject: [PATCH 28/30] Fix slow tab complete for some commands. Use online players instead of offline players, which is very slow. --- src/main/java/org/bukkit/command/defaults/DeopCommand.java | 2 +- src/main/java/org/bukkit/command/defaults/WhitelistCommand.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/bukkit/command/defaults/DeopCommand.java b/src/main/java/org/bukkit/command/defaults/DeopCommand.java index 1b71d493..be85334a 100644 --- a/src/main/java/org/bukkit/command/defaults/DeopCommand.java +++ b/src/main/java/org/bukkit/command/defaults/DeopCommand.java @@ -49,7 +49,7 @@ public List tabComplete(CommandSender sender, String alias, String[] arg if (args.length == 1) { List completions = new ArrayList(); - for (OfflinePlayer player : Bukkit.getOfflinePlayers()) { + for (OfflinePlayer player : Bukkit.getOperators()) { // Spigot - only deop ops! String playerName = player.getName(); if (player.isOp() && StringUtil.startsWithIgnoreCase(playerName, args[0])) { completions.add(playerName); diff --git a/src/main/java/org/bukkit/command/defaults/WhitelistCommand.java b/src/main/java/org/bukkit/command/defaults/WhitelistCommand.java index b3fa4f82..6559b33b 100644 --- a/src/main/java/org/bukkit/command/defaults/WhitelistCommand.java +++ b/src/main/java/org/bukkit/command/defaults/WhitelistCommand.java @@ -104,7 +104,7 @@ public List tabComplete(CommandSender sender, String alias, String[] arg } else if (args.length == 2) { if (args[0].equalsIgnoreCase("add")) { List completions = new ArrayList(); - for (OfflinePlayer player : Bukkit.getOfflinePlayers()) { + for (OfflinePlayer player : Bukkit.getOnlinePlayers()) { // Spigot - well maybe sometimes you haven't turned the whitelist on just yet. String name = player.getName(); if (StringUtil.startsWithIgnoreCase(name, args[1]) && !player.isWhitelisted()) { completions.add(name); From 5891e6f76a7d2623e11b9104075dbd010bae4d8f Mon Sep 17 00:00:00 2001 From: drXor Date: Wed, 23 Jul 2014 15:50:36 -0400 Subject: [PATCH 29/30] Undeprecate Player#updateInventory()V --- src/main/java/org/bukkit/entity/Player.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/org/bukkit/entity/Player.java b/src/main/java/org/bukkit/entity/Player.java index 37c8a589..b2ad5b7f 100644 --- a/src/main/java/org/bukkit/entity/Player.java +++ b/src/main/java/org/bukkit/entity/Player.java @@ -333,10 +333,8 @@ public interface Player extends HumanEntity, Conversable, CommandSender, Offline /** * Forces an update of the player's entire inventory. * - * @deprecated This method should not be relied upon as it is a temporary - * work-around for a larger, more complicated issue. */ - @Deprecated + //@Deprecated // Spigot - undeprecate public void updateInventory(); /** From 168f37a1118eeeeccb6a34acf0070f887f989007 Mon Sep 17 00:00:00 2001 From: Maxim Van de Wynckel Date: Thu, 31 Jul 2014 00:08:46 +0200 Subject: [PATCH 30/30] Usefull loaded chunks in timings Adds total loading chunks to timings (in comments) --- src/main/java/org/spigotmc/CustomTimingsHandler.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/org/spigotmc/CustomTimingsHandler.java b/src/main/java/org/spigotmc/CustomTimingsHandler.java index 8d982974..ab5299fd 100644 --- a/src/main/java/org/spigotmc/CustomTimingsHandler.java +++ b/src/main/java/org/spigotmc/CustomTimingsHandler.java @@ -67,13 +67,16 @@ public static void printTimings(PrintStream printStream) printStream.println( "# Version " + Bukkit.getVersion() ); int entities = 0; int livingEntities = 0; + int loadedChunks = 0; for ( World world : Bukkit.getWorlds() ) { entities += world.getEntities().size(); livingEntities += world.getLivingEntities().size(); + loadedChunks += world.getLoadedChunks().size(); } printStream.println( "# Entities " + entities ); printStream.println( "# LivingEntities " + livingEntities ); + printStream.println( "# LoadedChunks " + loadedChunks ); } /**