BY_ID = Maps.newHashMap();
+
+ private Art(int id, int width, int height) {
+ this.id = id;
+ this.width = width;
+ this.height = height;
+ }
+
+ /**
+ * Gets the width of the painting, in blocks
+ *
+ * @return The width of the painting, in blocks
+ */
+ public int getBlockWidth() {
+ return width;
+ }
+
+ /**
+ * Gets the height of the painting, in blocks
+ *
+ * @return The height of the painting, in blocks
+ */
+ public int getBlockHeight() {
+ return height;
+ }
+
+ /**
+ * Get the ID of this painting.
+ *
+ * @return The ID of this painting
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Get a painting by its numeric ID
+ *
+ * @param id The ID
+ * @return The painting
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static Art getById(int id) {
+ return BY_ID.get(id);
+ }
+
+ /**
+ * Get a painting by its unique name
+ *
+ * This ignores underscores and capitalization
+ *
+ * @param name The name
+ * @return The painting
+ */
+ public static Art getByName(String name) {
+ Validate.notNull(name, "Name cannot be null");
+
+ return BY_NAME.get(name.toLowerCase().replaceAll("_", ""));
+ }
+
+ static {
+ for (Art art : values()) {
+ BY_ID.put(art.id, art);
+ BY_NAME.put(art.toString().toLowerCase().replaceAll("_", ""), art);
+ }
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/BanEntry.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/BanEntry.java
new file mode 100644
index 0000000..b2437c6
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/BanEntry.java
@@ -0,0 +1,128 @@
+package org.bukkit;
+
+import java.util.Date;
+
+/**
+ * A single entry from a ban list. This may represent either a player ban or
+ * an IP ban.
+ *
+ * Ban entries include the following properties:
+ *
+ * Property information
+ *
+ * Property |
+ * Description |
+ *
+ * Target Name / IP Address |
+ * The target name or IP address |
+ *
+ * Creation Date |
+ * The creation date of the ban |
+ *
+ * Source |
+ * The source of the ban, such as a player, console, plugin, etc |
+ *
+ * Expiration Date |
+ * The expiration date of the ban |
+ *
+ * Reason |
+ * The reason for the ban |
+ *
+ *
+ *
+ * Unsaved information is not automatically written to the implementation's
+ * ban list, instead, the {@link #save()} method must be called to write the
+ * changes to the ban list. If this ban entry has expired (such as from an
+ * unban) and is no longer found in the list, the {@link #save()} call will
+ * re-add it to the list, therefore banning the victim specified.
+ *
+ * Likewise, changes to the associated {@link BanList} or other entries may or
+ * may not be reflected in this entry.
+ */
+public interface BanEntry {
+
+ /**
+ * Gets the target involved. This may be in the form of an IP or a player
+ * name.
+ *
+ * @return the target name or IP address
+ */
+ public String getTarget();
+
+ /**
+ * Gets the date this ban entry was created.
+ *
+ * @return the creation date
+ */
+ public Date getCreated();
+
+ /**
+ * Sets the date this ban entry was created.
+ *
+ * @param created the new created date, cannot be null
+ * @see #save() saving changes
+ */
+ public void setCreated(Date created);
+
+ /**
+ * Gets the source of this ban.
+ *
+ * Note: A source is considered any String, although this is generally a
+ * player name.
+ *
+ * @return the source of the ban
+ */
+ public String getSource();
+
+ /**
+ * Sets the source of this ban.
+ *
+ * Note: A source is considered any String, although this is generally a
+ * player name.
+ *
+ * @param source the new source where null values become empty strings
+ * @see #save() saving changes
+ */
+ public void setSource(String source);
+
+ /**
+ * Gets the date this ban expires on, or null for no defined end date.
+ *
+ * @return the expiration date
+ */
+ public Date getExpiration();
+
+ /**
+ * Sets the date this ban expires on. Null values are considered
+ * "infinite" bans.
+ *
+ * @param expiration the new expiration date, or null to indicate an
+ * eternity
+ * @see #save() saving changes
+ */
+ public void setExpiration(Date expiration);
+
+ /**
+ * Gets the reason for this ban.
+ *
+ * @return the ban reason, or null if not set
+ */
+ public String getReason();
+
+ /**
+ * Sets the reason for this ban. Reasons must not be null.
+ *
+ * @param reason the new reason, null values assume the implementation
+ * default
+ * @see #save() saving changes
+ */
+ public void setReason(String reason);
+
+ /**
+ * Saves the ban entry, overwriting any previous data in the ban list.
+ *
+ * Saving the ban entry of an unbanned player will cause the player to be
+ * banned once again.
+ */
+ public void save();
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/BanList.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/BanList.java
new file mode 100644
index 0000000..c21b858
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/BanList.java
@@ -0,0 +1,72 @@
+package org.bukkit;
+
+import java.util.Date;
+import java.util.Set;
+
+/**
+ * A ban list, containing bans of some {@link Type}.
+ */
+public interface BanList {
+
+ /**
+ * Represents a ban-type that a {@link BanList} may track.
+ */
+ public enum Type {
+ /**
+ * Banned player names
+ */
+ NAME,
+ /**
+ * Banned player IP addresses
+ */
+ IP,
+ ;
+ }
+
+ /**
+ * Gets a {@link BanEntry} by target.
+ *
+ * @param target entry parameter to search for
+ * @return the corresponding entry, or null if none found
+ */
+ public BanEntry getBanEntry(String target);
+
+ /**
+ * Adds a ban to the this list. If a previous ban exists, this will
+ * update the previous entry.
+ *
+ * @param target the target of the ban
+ * @param reason reason for the ban, null indicates implementation default
+ * @param expires date for the ban's expiration (unban), or null to imply
+ * forever
+ * @param source source of the ban, null indicates implementation default
+ * @return the entry for the newly created ban, or the entry for the
+ * (updated) previous ban
+ */
+ public BanEntry addBan(String target, String reason, Date expires, String source);
+
+ /**
+ * Gets a set containing every {@link BanEntry} in this list.
+ *
+ * @return an immutable set containing every entry tracked by this list
+ */
+ public Set getBanEntries();
+
+ /**
+ * Gets if a {@link BanEntry} exists for the target, indicating an active
+ * ban status.
+ *
+ * @param target the target to find
+ * @return true if a {@link BanEntry} exists for the name, indicating an
+ * active ban status, false otherwise
+ */
+ public boolean isBanned(String target);
+
+ /**
+ * Removes the specified target from this list, therefore indicating a
+ * "not banned" status.
+ *
+ * @param target the target to remove from this list
+ */
+ public void pardon(String target);
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/BlockChangeDelegate.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/BlockChangeDelegate.java
new file mode 100644
index 0000000..e6b9f0e
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/BlockChangeDelegate.java
@@ -0,0 +1,104 @@
+package org.bukkit;
+
+/**
+ * A delegate for handling block changes. This serves as a direct interface
+ * between generation algorithms in the server implementation and utilizing
+ * code.
+ */
+public interface BlockChangeDelegate {
+
+ /**
+ * Set a block type at the specified coordinates without doing all world
+ * updates and notifications.
+ *
+ * It is safe to have this call World.setTypeId, but it may be slower than
+ * World.setRawTypeId.
+ *
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param z Z coordinate
+ * @param typeId New block ID
+ * @return true if the block was set successfully
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public boolean setRawTypeId(int x, int y, int z, int typeId);
+
+ /**
+ * Set a block type and data at the specified coordinates without doing
+ * all world updates and notifications.
+ *
+ * It is safe to have this call World.setTypeId, but it may be slower than
+ * World.setRawTypeId.
+ *
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param z Z coordinate
+ * @param typeId New block ID
+ * @param data Block data
+ * @return true if the block was set successfully
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public boolean setRawTypeIdAndData(int x, int y, int z, int typeId, int data);
+
+ /**
+ * Set a block type at the specified coordinates.
+ *
+ * This method cannot call World.setRawTypeId, a full update is needed.
+ *
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param z Z coordinate
+ * @param typeId New block ID
+ * @return true if the block was set successfully
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public boolean setTypeId(int x, int y, int z, int typeId);
+
+ /**
+ * Set a block type and data at the specified coordinates.
+ *
+ * This method cannot call World.setRawTypeId, a full update is needed.
+ *
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param z Z coordinate
+ * @param typeId New block ID
+ * @param data Block data
+ * @return true if the block was set successfully
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public boolean setTypeIdAndData(int x, int y, int z, int typeId, int data);
+
+ /**
+ * Get the block type at the location.
+ *
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param z Z coordinate
+ * @return The block ID
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public int getTypeId(int x, int y, int z);
+
+ /**
+ * Gets the height of the world.
+ *
+ * @return Height of the world
+ */
+ public int getHeight();
+
+ /**
+ * Checks if the specified block is empty (air) or not.
+ *
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param z Z coordinate
+ * @return True if the block is considered empty.
+ */
+ public boolean isEmpty(int x, int y, int z);
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Bukkit.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Bukkit.java
new file mode 100644
index 0000000..8fbc828
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Bukkit.java
@@ -0,0 +1,1169 @@
+package org.bukkit;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.logging.Logger;
+
+import org.bukkit.Warning.WarningState;
+import org.bukkit.command.CommandException;
+import org.bukkit.command.CommandMap;
+import org.bukkit.command.CommandSender;
+import org.bukkit.command.ConsoleCommandSender;
+import org.bukkit.command.PluginCommand;
+import org.bukkit.entity.Entity;
+import org.bukkit.entity.Player;
+import org.bukkit.event.inventory.InventoryType;
+import org.bukkit.event.server.ServerListPingEvent;
+import org.bukkit.help.HelpMap;
+import org.bukkit.inventory.Inventory;
+import org.bukkit.inventory.InventoryHolder;
+import org.bukkit.inventory.ItemStack;
+import org.bukkit.inventory.Recipe;
+import org.bukkit.map.MapView;
+import org.bukkit.permissions.Permissible;
+import org.bukkit.plugin.PluginManager;
+import org.bukkit.plugin.ServicesManager;
+import org.bukkit.plugin.messaging.Messenger;
+import org.bukkit.scheduler.BukkitScheduler;
+import org.bukkit.scoreboard.ScoreboardManager;
+import org.bukkit.util.CachedServerIcon;
+
+import com.avaje.ebean.config.ServerConfig;
+import com.google.common.collect.ImmutableList;
+import org.bukkit.generator.ChunkGenerator;
+
+import org.bukkit.inventory.ItemFactory;
+import org.bukkit.inventory.meta.ItemMeta;
+
+/**
+ * Represents the Bukkit core, for version and Server singleton handling
+ */
+public final class Bukkit {
+ private static Server server;
+
+ /**
+ * Static class cannot be initialized.
+ */
+ private Bukkit() {}
+
+ /**
+ * Gets the current {@link Server} singleton
+ *
+ * @return Server instance being ran
+ */
+ public static Server getServer() {
+ return server;
+ }
+
+ /**
+ * Attempts to set the {@link Server} singleton.
+ *
+ * This cannot be done if the Server is already set.
+ *
+ * @param server Server instance
+ */
+ public static void setServer(Server server) {
+ if (Bukkit.server != null) {
+ throw new UnsupportedOperationException("Cannot redefine singleton Server");
+ }
+
+ Bukkit.server = server;
+ server.getLogger().info("This server is running " + getName() + " version " + getVersion() + " (Implementing API version " + getBukkitVersion() + ")");
+ }
+
+ /**
+ * Gets the name of this server implementation.
+ *
+ * @return name of this server implementation
+ */
+ public static String getName() {
+ return server.getName();
+ }
+
+ /**
+ * Gets the version string of this server implementation.
+ *
+ * @return version of this server implementation
+ */
+ public static String getVersion() {
+ return server.getVersion();
+ }
+
+ /**
+ * Gets the Bukkit version that this server is running.
+ *
+ * @return version of Bukkit
+ */
+ public static String getBukkitVersion() {
+ return server.getBukkitVersion();
+ }
+
+ /**
+ * Gets an array copy of all currently logged in players.
+ *
+ * This method exists for legacy reasons to provide backwards
+ * compatibility. It will not exist at runtime and should not be used
+ * under any circumstances.
+ *
+ * @deprecated superseded by {@link #getOnlinePlayers()}
+ * @return an array of Players that are currently online
+ */
+ @Deprecated
+ public static Player[] _INVALID_getOnlinePlayers() {
+ return server._INVALID_getOnlinePlayers();
+ }
+
+ /**
+ * Gets a view of all currently logged in players. This {@linkplain
+ * Collections#unmodifiableCollection(Collection) view} is a reused
+ * object, making some operations like {@link Collection#size()}
+ * zero-allocation.
+ *
+ * The collection is a view backed by the internal representation, such
+ * that, changes to the internal state of the server will be reflected
+ * immediately. However, the reuse of the returned collection (identity)
+ * is not strictly guaranteed for future or all implementations. Casting
+ * the collection, or relying on interface implementations (like {@link
+ * Serializable} or {@link List}), is deprecated.
+ *
+ * Iteration behavior is undefined outside of self-contained main-thread
+ * uses. Normal and immediate iterator use without consequences that
+ * affect the collection are fully supported. The effects following
+ * (non-exhaustive) {@link Entity#teleport(Location) teleportation},
+ * {@link Player#setHealth(double) death}, and {@link Player#kickPlayer(
+ * String) kicking} are undefined. Any use of this collection from
+ * asynchronous threads is unsafe.
+ *
+ * For safe consequential iteration or mimicking the old array behavior,
+ * using {@link Collection#toArray(Object[])} is recommended. For making
+ * snapshots, {@link ImmutableList#copyOf(Collection)} is recommended.
+ *
+ * @return a view of currently online players.
+ */
+ public static Collection extends Player> getOnlinePlayers() {
+ return server.getOnlinePlayers();
+ }
+
+ /**
+ * Get the maximum amount of players which can login to this server.
+ *
+ * @return the amount of players this server allows
+ */
+ public static int getMaxPlayers() {
+ return server.getMaxPlayers();
+ }
+
+ /**
+ * Get the game port that the server runs on.
+ *
+ * @return the port number of this server
+ */
+ public static int getPort() {
+ return server.getPort();
+ }
+
+ /**
+ * Get the view distance from this server.
+ *
+ * @return the view distance from this server.
+ */
+ public static int getViewDistance() {
+ return server.getViewDistance();
+ }
+
+ /**
+ * Get the IP that this server is bound to, or empty string if not
+ * specified.
+ *
+ * @return the IP string that this server is bound to, otherwise empty
+ * string
+ */
+ public static String getIp() {
+ return server.getIp();
+ }
+
+ /**
+ * Get the name of this server.
+ *
+ * @return the name of this server
+ */
+ public static String getServerName() {
+ return server.getServerName();
+ }
+
+ /**
+ * Get an ID of this server. The ID is a simple generally alphanumeric ID
+ * that can be used for uniquely identifying this server.
+ *
+ * @return the ID of this server
+ */
+ public static String getServerId() {
+ return server.getServerId();
+ }
+
+ /**
+ * Get world type (level-type setting) for default world.
+ *
+ * @return the value of level-type (e.g. DEFAULT, FLAT, DEFAULT_1_1)
+ */
+ public static String getWorldType() {
+ return server.getWorldType();
+ }
+
+ /**
+ * Get generate-structures setting.
+ *
+ * @return true if structure generation is enabled, false otherwise
+ */
+ public static boolean getGenerateStructures() {
+ return server.getGenerateStructures();
+ }
+
+ /**
+ * Gets whether this server allows the End or not.
+ *
+ * @return whether this server allows the End or not
+ */
+ public static boolean getAllowEnd() {
+ return server.getAllowEnd();
+ }
+
+ /**
+ * Gets whether this server allows the Nether or not.
+ *
+ * @return whether this server allows the Nether or not
+ */
+ public static boolean getAllowNether() {
+ return server.getAllowNether();
+ }
+
+ /**
+ * Gets whether this server has a whitelist or not.
+ *
+ * @return whether this server has a whitelist or not
+ */
+ public static boolean hasWhitelist() {
+ return server.hasWhitelist();
+ }
+
+ /**
+ * Sets if the server is whitelisted.
+ *
+ * @param value true for whitelist on, false for off
+ */
+ public static void setWhitelist(boolean value) {
+ server.setWhitelist(value);
+ }
+
+ /**
+ * Gets a list of whitelisted players.
+ *
+ * @return a set containing all whitelisted players
+ */
+ public static Set getWhitelistedPlayers() {
+ return server.getWhitelistedPlayers();
+ }
+
+ /**
+ * Reloads the whitelist from disk.
+ */
+ public static void reloadWhitelist() {
+ server.reloadWhitelist();
+ }
+
+ /**
+ * Broadcast a message to all players.
+ *
+ * This is the same as calling {@link #broadcast(java.lang.String,
+ * java.lang.String)} to {@link Server#BROADCAST_CHANNEL_USERS}
+ *
+ * @param message the message
+ * @return the number of players
+ */
+ public static int broadcastMessage(String message) {
+ return server.broadcastMessage(message);
+ }
+
+ // Paper start
+ /**
+ * Sends the component to the player
+ *
+ * @param component the components to send
+ */
+ public static void broadcast(net.md_5.bungee.api.chat.BaseComponent component) {
+ server.broadcast(component);
+ }
+
+ /**
+ * Sends an array of components as a single message to the player
+ *
+ * @param components the components to send
+ */
+ public static void broadcast(net.md_5.bungee.api.chat.BaseComponent... components) {
+ server.broadcast(components);
+ }
+ // Paper end
+
+ /**
+ * Gets the name of the update folder. The update folder is used to safely
+ * update plugins at the right moment on a plugin load.
+ *
+ * The update folder name is relative to the plugins folder.
+ *
+ * @return the name of the update folder
+ */
+ public static String getUpdateFolder() {
+ return server.getUpdateFolder();
+ }
+
+ /**
+ * Gets the update folder. The update folder is used to safely update
+ * plugins at the right moment on a plugin load.
+ *
+ * @return the update folder
+ */
+ public static File getUpdateFolderFile() {
+ return server.getUpdateFolderFile();
+ }
+
+ /**
+ * Gets the value of the connection throttle setting.
+ *
+ * @return the value of the connection throttle setting
+ */
+ public static long getConnectionThrottle() {
+ return server.getConnectionThrottle();
+ }
+
+ /**
+ * Gets default ticks per animal spawns value.
+ *
+ * Example Usage:
+ *
+ * - A value of 1 will mean the server will attempt to spawn monsters
+ * every tick.
+ *
- A value of 400 will mean the server will attempt to spawn monsters
+ * every 400th tick.
+ *
- A value below 0 will be reset back to Minecraft's default.
+ *
+ *
+ * Note: If set to 0, animal spawning will be disabled. We
+ * recommend using spawn-animals to control this instead.
+ *
+ * Minecraft default: 400.
+ *
+ * @return the default ticks per animal spawns value
+ */
+ public static int getTicksPerAnimalSpawns() {
+ return server.getTicksPerAnimalSpawns();
+ }
+
+ /**
+ * Gets the default ticks per monster spawns value.
+ *
+ * Example Usage:
+ *
+ * - A value of 1 will mean the server will attempt to spawn monsters
+ * every tick.
+ *
- A value of 400 will mean the server will attempt to spawn monsters
+ * every 400th tick.
+ *
- A value below 0 will be reset back to Minecraft's default.
+ *
+ *
+ * Note: If set to 0, monsters spawning will be disabled. We
+ * recommend using spawn-monsters to control this instead.
+ *
+ * Minecraft default: 1.
+ *
+ * @return the default ticks per monsters spawn value
+ */
+ public static int getTicksPerMonsterSpawns() {
+ return server.getTicksPerMonsterSpawns();
+ }
+
+ /**
+ * Gets a player object by the given username.
+ *
+ * This method may not return objects for offline players.
+ *
+ * @param name the name to look up
+ * @return a player if one was found, null otherwise
+ */
+ public static Player getPlayer(String name) {
+ return server.getPlayer(name);
+ }
+
+ /**
+ * Gets the player with the exact given name, case insensitive.
+ *
+ * @param name Exact name of the player to retrieve
+ * @return a player object if one was found, null otherwise
+ */
+ public static Player getPlayerExact(String name) {
+ return server.getPlayerExact(name);
+ }
+
+ /**
+ * Attempts to match any players with the given name, and returns a list
+ * of all possibly matches.
+ *
+ * This list is not sorted in any particular order. If an exact match is
+ * found, the returned list will only contain a single result.
+ *
+ * @param name the (partial) name to match
+ * @return list of all possible players
+ */
+ public static List matchPlayer(String name) {
+ return server.matchPlayer(name);
+ }
+
+ /**
+ * Gets the player with the given UUID.
+ *
+ * @param id UUID of the player to retrieve
+ * @return a player object if one was found, null otherwise
+ */
+ public static Player getPlayer(UUID id) {
+ return server.getPlayer(id);
+ }
+
+ /**
+ * Gets the plugin manager for interfacing with plugins.
+ *
+ * @return a plugin manager for this Server instance
+ */
+ public static PluginManager getPluginManager() {
+ return server.getPluginManager();
+ }
+
+ /**
+ * Gets the scheduler for managing scheduled events.
+ *
+ * @return a scheduling service for this server
+ */
+ public static BukkitScheduler getScheduler() {
+ return server.getScheduler();
+ }
+
+ /**
+ * Gets a services manager.
+ *
+ * @return s services manager
+ */
+ public static ServicesManager getServicesManager() {
+ return server.getServicesManager();
+ }
+
+ /**
+ * Gets a list of all worlds on this server.
+ *
+ * @return a list of worlds
+ */
+ public static List getWorlds() {
+ return server.getWorlds();
+ }
+
+ /**
+ * Creates or loads a world with the given name using the specified
+ * options.
+ *
+ * If the world is already loaded, it will just return the equivalent of
+ * getWorld(creator.name()).
+ *
+ * @param creator the options to use when creating the world
+ * @return newly created or loaded world
+ */
+ public static World createWorld(WorldCreator creator) {
+ return server.createWorld(creator);
+ }
+
+ /**
+ * Unloads a world with the given name.
+ *
+ * @param name Name of the world to unload
+ * @param save whether to save the chunks before unloading
+ * @return true if successful, false otherwise
+ */
+ public static boolean unloadWorld(String name, boolean save) {
+ return server.unloadWorld(name, save);
+ }
+
+ /**
+ * Unloads the given world.
+ *
+ * @param world the world to unload
+ * @param save whether to save the chunks before unloading
+ * @return true if successful, false otherwise
+ */
+ public static boolean unloadWorld(World world, boolean save) {
+ return server.unloadWorld(world, save);
+ }
+
+ /**
+ * Gets the world with the given name.
+ *
+ * @param name the name of the world to retrieve
+ * @return a world with the given name, or null if none exists
+ */
+ public static World getWorld(String name) {
+ return server.getWorld(name);
+ }
+
+ /**
+ * Gets the world from the given Unique ID.
+ *
+ * @param uid a unique-id of the world to retrieve
+ * @return a world with the given Unique ID, or null if none exists
+ */
+ public static World getWorld(UUID uid) {
+ return server.getWorld(uid);
+ }
+
+ /**
+ * Gets the map from the given item ID.
+ *
+ * @param id the id of the map to get
+ * @return a map view if it exists, or null otherwise
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static MapView getMap(short id) {
+ return server.getMap(id);
+ }
+
+ /**
+ * Create a new map with an automatically assigned ID.
+ *
+ * @param world the world the map will belong to
+ * @return a newly created map view
+ */
+ public static MapView createMap(World world) {
+ return server.createMap(world);
+ }
+
+ /**
+ * Reloads the server, refreshing settings and plugin information.
+ */
+ public static void reload() {
+ server.reload();
+ }
+
+ /**
+ * Returns the primary logger associated with this server instance.
+ *
+ * @return Logger associated with this server
+ */
+ public static Logger getLogger() {
+ return server.getLogger();
+ }
+
+ /**
+ * Gets a {@link PluginCommand} with the given name or alias.
+ *
+ * @param name the name of the command to retrieve
+ * @return a plugin command if found, null otherwise
+ */
+ public static PluginCommand getPluginCommand(String name) {
+ return server.getPluginCommand(name);
+ }
+
+ /**
+ * Writes loaded players to disk.
+ */
+ public static void savePlayers() {
+ server.savePlayers();
+ }
+
+ /**
+ * Dispatches a command on this server, and executes it if found.
+ *
+ * @param sender the apparent sender of the command
+ * @param commandLine the command + arguments. Example: test abc
+ * 123
+ * @return returns false if no target is found
+ * @throws CommandException thrown when the executor for the given command
+ * fails with an unhandled exception
+ */
+ public static boolean dispatchCommand(CommandSender sender, String commandLine) throws CommandException {
+ return server.dispatchCommand(sender, commandLine);
+ }
+
+ /**
+ * Populates a given {@link ServerConfig} with values attributes to this
+ * server.
+ *
+ * @param config the server config to populate
+ */
+ public static void configureDbConfig(ServerConfig config) {
+ server.configureDbConfig(config);
+ }
+
+ /**
+ * Adds a recipe to the crafting manager.
+ *
+ * @param recipe the recipe to add
+ * @return true if the recipe was added, false if it wasn't for some
+ * reason
+ */
+ public static boolean addRecipe(Recipe recipe) {
+ return server.addRecipe(recipe);
+ }
+
+ /**
+ * Get a list of all recipes for a given item. The stack size is ignored
+ * in comparisons. If the durability is -1, it will match any data value.
+ *
+ * @param result the item to match against recipe results
+ * @return a list of recipes with the given result
+ */
+ public static List getRecipesFor(ItemStack result) {
+ return server.getRecipesFor(result);
+ }
+
+ /**
+ * Get an iterator through the list of crafting recipes.
+ *
+ * @return an iterator
+ */
+ public static Iterator recipeIterator() {
+ return server.recipeIterator();
+ }
+
+ /**
+ * Clears the list of crafting recipes.
+ */
+ public static void clearRecipes() {
+ server.clearRecipes();
+ }
+
+ /**
+ * Resets the list of crafting recipes to the default.
+ */
+ public static void resetRecipes() {
+ server.resetRecipes();
+ }
+
+ /**
+ * Gets a list of command aliases defined in the server properties.
+ *
+ * @return a map of aliases to command names
+ */
+ public static Map getCommandAliases() {
+ return server.getCommandAliases();
+ }
+
+ /**
+ * Gets the radius, in blocks, around each worlds spawn point to protect.
+ *
+ * @return spawn radius, or 0 if none
+ */
+ public static int getSpawnRadius() {
+ return server.getSpawnRadius();
+ }
+
+ /**
+ * Sets the radius, in blocks, around each worlds spawn point to protect.
+ *
+ * @param value new spawn radius, or 0 if none
+ */
+ public static void setSpawnRadius(int value) {
+ server.setSpawnRadius(value);
+ }
+
+ /**
+ * Gets whether the Server is in online mode or not.
+ *
+ * @return true if the server authenticates clients, false otherwise
+ */
+ public static boolean getOnlineMode() {
+ return server.getOnlineMode();
+ }
+
+ /**
+ * Gets whether this server allows flying or not.
+ *
+ * @return true if the server allows flight, false otherwise
+ */
+ public static boolean getAllowFlight() {
+ return server.getAllowFlight();
+ }
+
+ /**
+ * Gets whether the server is in hardcore mode or not.
+ *
+ * @return true if the server mode is hardcore, false otherwise
+ */
+ public static boolean isHardcore() {
+ return server.isHardcore();
+ }
+
+ /**
+ * Gets whether to use vanilla (false) or exact behaviour (true).
+ *
+ *
+ * - Vanilla behaviour: check for collisions and move the player if
+ * needed.
+ *
- Exact behaviour: spawn players exactly where they should be.
+ *
+ *
+ * @return true if exact location locations are used for spawning, false
+ * for vanilla collision detection or otherwise
+ *
+ * @deprecated non standard and unused feature.
+ */
+ @Deprecated
+ public static boolean useExactLoginLocation() {
+ return server.useExactLoginLocation();
+ }
+
+ /**
+ * Shutdowns the server, stopping everything.
+ */
+ public static void shutdown() {
+ server.shutdown();
+ }
+
+ /**
+ * Broadcasts the specified message to every user with the given
+ * permission name.
+ *
+ * @param message message to broadcast
+ * @param permission the required permission {@link Permissible
+ * permissibles} must have to receive the broadcast
+ * @return number of message recipients
+ */
+ public static int broadcast(String message, String permission) {
+ return server.broadcast(message, permission);
+ }
+
+ /**
+ * Gets the player by the given name, regardless if they are offline or
+ * online.
+ *
+ * This method may involve a blocking web request to get the UUID for the
+ * given name.
+ *
+ * This will return an object even if the player does not exist. To this
+ * method, all players will exist.
+ *
+ * @deprecated Persistent storage of users should be by UUID as names are no longer
+ * unique past a single session.
+ * @param name the name the player to retrieve
+ * @return an offline player
+ * @see #getOfflinePlayer(java.util.UUID)
+ */
+ @Deprecated
+ public static OfflinePlayer getOfflinePlayer(String name) {
+ return server.getOfflinePlayer(name);
+ }
+
+ /**
+ * Gets the player by the given UUID, regardless if they are offline or
+ * online.
+ *
+ * This will return an object even if the player does not exist. To this
+ * method, all players will exist.
+ *
+ * @param id the UUID of the player to retrieve
+ * @return an offline player
+ */
+ public static OfflinePlayer getOfflinePlayer(UUID id) {
+ return server.getOfflinePlayer(id);
+ }
+
+ /**
+ * Gets a set containing all current IPs that are banned.
+ *
+ * @return a set containing banned IP addresses
+ */
+ public static Set getIPBans() {
+ return server.getIPBans();
+ }
+
+ /**
+ * Bans the specified address from the server.
+ *
+ * @param address the IP address to ban
+ */
+ public static void banIP(String address) {
+ server.banIP(address);
+ }
+
+ /**
+ * Unbans the specified address from the server.
+ *
+ * @param address the IP address to unban
+ */
+ public static void unbanIP(String address) {
+ server.unbanIP(address);
+ }
+
+ /**
+ * Gets a set containing all banned players.
+ *
+ * @return a set containing banned players
+ */
+ public static Set getBannedPlayers() {
+ return server.getBannedPlayers();
+ }
+
+ /**
+ * Gets a ban list for the supplied type.
+ *
+ * Bans by name are no longer supported and this method will return
+ * null when trying to request them. The replacement is bans by UUID.
+ *
+ * @param type the type of list to fetch, cannot be null
+ * @return a ban list of the specified type
+ */
+ public static BanList getBanList(BanList.Type type){
+ return server.getBanList(type);
+ }
+
+ /**
+ * Gets a set containing all player operators.
+ *
+ * @return a set containing player operators
+ */
+ public static Set getOperators() {
+ return server.getOperators();
+ }
+
+ /**
+ * Gets the default {@link GameMode} for new players.
+ *
+ * @return the default game mode
+ */
+ public static GameMode getDefaultGameMode() {
+ return server.getDefaultGameMode();
+ }
+
+ /**
+ * Sets the default {@link GameMode} for new players.
+ *
+ * @param mode the new game mode
+ */
+ public static void setDefaultGameMode(GameMode mode) {
+ server.setDefaultGameMode(mode);
+ }
+
+ /**
+ * Gets a {@link ConsoleCommandSender} that may be used as an input source
+ * for this server.
+ *
+ * @return a console command sender
+ */
+ public static ConsoleCommandSender getConsoleSender() {
+ return server.getConsoleSender();
+ }
+
+ /**
+ * Gets the folder that contains all of the various {@link World}s.
+ *
+ * @return folder that contains all worlds
+ */
+ public static File getWorldContainer() {
+ return server.getWorldContainer();
+ }
+
+ /**
+ * Gets every player that has ever played on this server.
+ *
+ * @return an array containing all previous players
+ */
+ public static OfflinePlayer[] getOfflinePlayers() {
+ return server.getOfflinePlayers();
+ }
+
+ /**
+ * Gets the {@link Messenger} responsible for this server.
+ *
+ * @return messenger responsible for this server
+ */
+ public static Messenger getMessenger() {
+ return server.getMessenger();
+ }
+
+ /**
+ * Gets the {@link HelpMap} providing help topics for this server.
+ *
+ * @return a help map for this server
+ */
+ public static HelpMap getHelpMap() {
+ return server.getHelpMap();
+ }
+
+ /**
+ * Creates an empty inventory of the specified type. If the type is {@link
+ * InventoryType#CHEST}, the new inventory has a size of 27; otherwise the
+ * new inventory has the normal size for its type.
+ *
+ * @param owner the holder of the inventory, or null to indicate no holder
+ * @param type the type of inventory to create
+ * @return a new inventory
+ */
+ public static Inventory createInventory(InventoryHolder owner, InventoryType type) {
+ return server.createInventory(owner, type);
+ }
+
+ /**
+ * Creates an empty inventory with the specified type and title. If the type
+ * is {@link InventoryType#CHEST}, the new inventory has a size of 27;
+ * otherwise the new inventory has the normal size for its type.
+ * It should be noted that some inventory types do not support titles and
+ * may not render with said titles on the Minecraft client.
+ *
+ * @param owner The holder of the inventory; can be null if there's no holder.
+ * @param type The type of inventory to create.
+ * @param title The title of the inventory, to be displayed when it is viewed.
+ * @return The new inventory.
+ */
+ public static Inventory createInventory(InventoryHolder owner, InventoryType type, String title) {
+ return server.createInventory(owner, type, title);
+ }
+
+ /**
+ * Creates an empty inventory of type {@link InventoryType#CHEST} with the
+ * specified size.
+ *
+ * @param owner the holder of the inventory, or null to indicate no holder
+ * @param size a multiple of 9 as the size of inventory to create
+ * @return a new inventory
+ * @throws IllegalArgumentException if the size is not a multiple of 9
+ */
+ public static Inventory createInventory(InventoryHolder owner, int size) throws IllegalArgumentException {
+ return server.createInventory(owner, size);
+ }
+
+ /**
+ * Creates an empty inventory of type {@link InventoryType#CHEST} with the
+ * specified size and title.
+ *
+ * @param owner the holder of the inventory, or null to indicate no holder
+ * @param size a multiple of 9 as the size of inventory to create
+ * @param title the title of the inventory, displayed when inventory is
+ * viewed
+ * @return a new inventory
+ * @throws IllegalArgumentException if the size is not a multiple of 9
+ */
+ public static Inventory createInventory(InventoryHolder owner, int size, String title) throws IllegalArgumentException {
+ return server.createInventory(owner, size, title);
+ }
+
+ /**
+ * Gets user-specified limit for number of monsters that can spawn in a
+ * chunk.
+ *
+ * @return the monster spawn limit
+ */
+ public static int getMonsterSpawnLimit() {
+ return server.getMonsterSpawnLimit();
+ }
+
+ /**
+ * Gets user-specified limit for number of animals that can spawn in a
+ * chunk.
+ *
+ * @return the animal spawn limit
+ */
+ public static int getAnimalSpawnLimit() {
+ return server.getAnimalSpawnLimit();
+ }
+
+ /**
+ * Gets user-specified limit for number of water animals that can spawn in
+ * a chunk.
+ *
+ * @return the water animal spawn limit
+ */
+ public static int getWaterAnimalSpawnLimit() {
+ return server.getWaterAnimalSpawnLimit();
+ }
+
+ /**
+ * Gets user-specified limit for number of ambient mobs that can spawn in
+ * a chunk.
+ *
+ * @return the ambient spawn limit
+ */
+ public static int getAmbientSpawnLimit() {
+ return server.getAmbientSpawnLimit();
+ }
+
+ /**
+ * Checks the current thread against the expected primary thread for the
+ * server.
+ *
+ * Note: this method should not be used to indicate the current
+ * synchronized state of the runtime. A current thread matching the main
+ * thread indicates that it is synchronized, but a mismatch does not
+ * preclude the same assumption.
+ *
+ * @return true if the current thread matches the expected primary thread,
+ * false otherwise
+ */
+ public static boolean isPrimaryThread() {
+ return server.isPrimaryThread();
+ }
+
+ /**
+ * Gets the message that is displayed on the server list.
+ *
+ * @return the servers MOTD
+ */
+ public static String getMotd() {
+ return server.getMotd();
+ }
+
+ /**
+ * Gets the default message that is displayed when the server is stopped.
+ *
+ * @return the shutdown message
+ */
+ public static String getShutdownMessage() {
+ return server.getShutdownMessage();
+ }
+
+ /**
+ * Gets the current warning state for the server.
+ *
+ * @return the configured warning state
+ */
+ public static WarningState getWarningState() {
+ return server.getWarningState();
+ }
+
+ /**
+ * Gets the instance of the item factory (for {@link ItemMeta}).
+ *
+ * @return the item factory
+ * @see ItemFactory
+ */
+ public static ItemFactory getItemFactory() {
+ return server.getItemFactory();
+ }
+
+ /**
+ * Gets the instance of the scoreboard manager.
+ *
+ * This will only exist after the first world has loaded.
+ *
+ * @return the scoreboard manager or null if no worlds are loaded.
+ */
+ public static ScoreboardManager getScoreboardManager() {
+ return server.getScoreboardManager();
+ }
+
+ /**
+ * Gets an instance of the server's default server-icon.
+ *
+ * @return the default server-icon; null values may be used by the
+ * implementation to indicate no defined icon, but this behavior is
+ * not guaranteed
+ */
+ public static CachedServerIcon getServerIcon() {
+ return server.getServerIcon();
+ }
+
+ /**
+ * Loads an image from a file, and returns a cached image for the specific
+ * server-icon.
+ *
+ * Size and type are implementation defined. An incompatible file is
+ * guaranteed to throw an implementation-defined {@link Exception}.
+ *
+ * @param file the file to load the from
+ * @throws IllegalArgumentException if image is null
+ * @throws Exception if the image does not meet current server server-icon
+ * specifications
+ * @return a cached server-icon that can be used for a {@link
+ * ServerListPingEvent#setServerIcon(CachedServerIcon)}
+ */
+ public static CachedServerIcon loadServerIcon(File file) throws IllegalArgumentException, Exception {
+ return server.loadServerIcon(file);
+ }
+
+ /**
+ * Creates a cached server-icon for the specific image.
+ *
+ * Size and type are implementation defined. An incompatible file is
+ * guaranteed to throw an implementation-defined {@link Exception}.
+ *
+ * @param image the image to use
+ * @throws IllegalArgumentException if image is null
+ * @throws Exception if the image does not meet current server
+ * server-icon specifications
+ * @return a cached server-icon that can be used for a {@link
+ * ServerListPingEvent#setServerIcon(CachedServerIcon)}
+ */
+ public static CachedServerIcon loadServerIcon(BufferedImage image) throws IllegalArgumentException, Exception {
+ return server.loadServerIcon(image);
+ }
+
+ /**
+ * Set the idle kick timeout. Any players idle for the specified amount of
+ * time will be automatically kicked.
+ *
+ * A value of 0 will disable the idle kick timeout.
+ *
+ * @param threshold the idle timeout in minutes
+ */
+ public static void setIdleTimeout(int threshold) {
+ server.setIdleTimeout(threshold);
+ }
+
+ /**
+ * Gets the idle kick timeout.
+ *
+ * @return the idle timeout in minutes
+ */
+ public static int getIdleTimeout() {
+ return server.getIdleTimeout();
+ }
+
+ /**
+ * Create a ChunkData for use in a generator.
+ *
+ * See {@link ChunkGenerator#generateChunkData(org.bukkit.World, java.util.Random, int, int, org.bukkit.generator.ChunkGenerator.BiomeGrid)}
+ *
+ * @param world the world to create the ChunkData for
+ * @return a new ChunkData for the world
+ *
+ */
+ public static ChunkGenerator.ChunkData createChunkData(World world) {
+ return server.createChunkData(world);
+ }
+
+ /**
+ * @see UnsafeValues
+ * @return the unsafe values instance
+ */
+ @Deprecated
+ public static UnsafeValues getUnsafe() {
+ return server.getUnsafe();
+ }
+
+ // Paper start
+ /**
+ * Gets the active {@link CommandMap}.
+ *
+ * @return the active command map
+ */
+ public static CommandMap getCommandMap() {
+ return server.getCommandMap();
+ }
+ // Paper end
+
+ public static Server.Spigot spigot()
+ {
+ return server.spigot();
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/ChatColor.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/ChatColor.java
new file mode 100644
index 0000000..adbae51
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/ChatColor.java
@@ -0,0 +1,371 @@
+package org.bukkit;
+
+import java.util.Map;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.Validate;
+
+import com.google.common.collect.Maps;
+
+/**
+ * All supported color values for chat
+ */
+public enum ChatColor{
+ /**
+ * Represents black
+ */
+ BLACK('0', 0x00) {
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.BLACK;
+ }
+ },
+ /**
+ * Represents dark blue
+ */
+ DARK_BLUE('1', 0x1){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.DARK_BLUE;
+ }
+ },
+ /**
+ * Represents dark green
+ */
+ DARK_GREEN('2', 0x2){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.DARK_GREEN;
+ }
+ },
+ /**
+ * Represents dark blue (aqua)
+ */
+ DARK_AQUA('3', 0x3){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.DARK_AQUA;
+ }
+ },
+ /**
+ * Represents dark red
+ */
+ DARK_RED('4', 0x4){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.DARK_RED;
+ }
+ },
+ /**
+ * Represents dark purple
+ */
+ DARK_PURPLE('5', 0x5){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.DARK_PURPLE;
+ }
+ },
+ /**
+ * Represents gold
+ */
+ GOLD('6', 0x6){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.GOLD;
+ }
+ },
+ /**
+ * Represents gray
+ */
+ GRAY('7', 0x7){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.GRAY;
+ }
+ },
+ /**
+ * Represents dark gray
+ */
+ DARK_GRAY('8', 0x8){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.DARK_GRAY;
+ }
+ },
+ /**
+ * Represents blue
+ */
+ BLUE('9', 0x9){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.BLUE;
+ }
+ },
+ /**
+ * Represents green
+ */
+ GREEN('a', 0xA){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.GREEN;
+ }
+ },
+ /**
+ * Represents aqua
+ */
+ AQUA('b', 0xB){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.AQUA;
+ }
+ },
+ /**
+ * Represents red
+ */
+ RED('c', 0xC){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.RED;
+ }
+ },
+ /**
+ * Represents light purple
+ */
+ LIGHT_PURPLE('d', 0xD){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.LIGHT_PURPLE;
+ }
+ },
+ /**
+ * Represents yellow
+ */
+ YELLOW('e', 0xE){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.YELLOW;
+ }
+ },
+ /**
+ * Represents white
+ */
+ WHITE('f', 0xF){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.WHITE;
+ }
+ },
+ /**
+ * Represents magical characters that change around randomly
+ */
+ MAGIC('k', 0x10, true){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.MAGIC;
+ }
+ },
+ /**
+ * Makes the text bold.
+ */
+ BOLD('l', 0x11, true){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.BOLD;
+ }
+ },
+ /**
+ * Makes a line appear through the text.
+ */
+ STRIKETHROUGH('m', 0x12, true){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.STRIKETHROUGH;
+ }
+ },
+ /**
+ * Makes the text appear underlined.
+ */
+ UNDERLINE('n', 0x13, true){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.UNDERLINE;
+ }
+ },
+ /**
+ * Makes the text italic.
+ */
+ ITALIC('o', 0x14, true){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.ITALIC;
+ }
+ },
+ /**
+ * Resets all previous chat colors or formats.
+ */
+ RESET('r', 0x15){
+ @Override
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.RESET;
+ }
+ };
+
+ /**
+ * The special character which prefixes all chat colour codes. Use this if
+ * you need to dynamically convert colour codes from your custom format.
+ */
+ public static final char COLOR_CHAR = '\u00A7';
+ private static final Pattern STRIP_COLOR_PATTERN = Pattern.compile("(?i)" + String.valueOf(COLOR_CHAR) + "[0-9A-FK-OR]");
+
+ private final int intCode;
+ private final char code;
+ private final boolean isFormat;
+ private final String toString;
+ private final static Map BY_ID = Maps.newHashMap();
+ private final static Map BY_CHAR = Maps.newHashMap();
+
+ private ChatColor(char code, int intCode) {
+ this(code, intCode, false);
+ }
+
+ private ChatColor(char code, int intCode, boolean isFormat) {
+ this.code = code;
+ this.intCode = intCode;
+ this.isFormat = isFormat;
+ this.toString = new String(new char[] {COLOR_CHAR, code});
+ }
+
+ public net.md_5.bungee.api.ChatColor asBungee() {
+ return net.md_5.bungee.api.ChatColor.RESET;
+ };
+
+ /**
+ * Gets the char value associated with this color
+ *
+ * @return A char value of this color code
+ */
+ public char getChar() {
+ return code;
+ }
+
+ @Override
+ public String toString() {
+ return toString;
+ }
+
+ /**
+ * Checks if this code is a format code as opposed to a color code.
+ *
+ * @return whether this ChatColor is a format code
+ */
+ public boolean isFormat() {
+ return isFormat;
+ }
+
+ /**
+ * Checks if this code is a color code as opposed to a format code.
+ *
+ * @return whether this ChatColor is a color code
+ */
+ public boolean isColor() {
+ return !isFormat && this != RESET;
+ }
+
+ /**
+ * Gets the color represented by the specified color code
+ *
+ * @param code Code to check
+ * @return Associative {@link org.bukkit.ChatColor} with the given code,
+ * or null if it doesn't exist
+ */
+ public static ChatColor getByChar(char code) {
+ return BY_CHAR.get(code);
+ }
+
+ /**
+ * Gets the color represented by the specified color code
+ *
+ * @param code Code to check
+ * @return Associative {@link org.bukkit.ChatColor} with the given code,
+ * or null if it doesn't exist
+ */
+ public static ChatColor getByChar(String code) {
+ Validate.notNull(code, "Code cannot be null");
+ Validate.isTrue(code.length() > 0, "Code must have at least one char");
+
+ return BY_CHAR.get(code.charAt(0));
+ }
+
+ /**
+ * Strips the given message of all color codes
+ *
+ * @param input String to strip of color
+ * @return A copy of the input string, without any coloring
+ */
+ public static String stripColor(final String input) {
+ if (input == null) {
+ return null;
+ }
+
+ return STRIP_COLOR_PATTERN.matcher(input).replaceAll("");
+ }
+
+ /**
+ * Translates a string using an alternate color code character into a
+ * string that uses the internal ChatColor.COLOR_CODE color code
+ * character. The alternate color code character will only be replaced if
+ * it is immediately followed by 0-9, A-F, a-f, K-O, k-o, R or r.
+ *
+ * @param altColorChar The alternate color code character to replace. Ex: {@literal &}
+ * @param textToTranslate Text containing the alternate color code character.
+ * @return Text containing the ChatColor.COLOR_CODE color code character.
+ */
+ public static String translateAlternateColorCodes(char altColorChar, String textToTranslate) {
+ char[] b = textToTranslate.toCharArray();
+ for (int i = 0; i < b.length - 1; i++) {
+ if (b[i] == altColorChar && "0123456789AaBbCcDdEeFfKkLlMmNnOoRr".indexOf(b[i+1]) > -1) {
+ b[i] = ChatColor.COLOR_CHAR;
+ b[i+1] = Character.toLowerCase(b[i+1]);
+ }
+ }
+ return new String(b);
+ }
+
+ /**
+ * Gets the ChatColors used at the end of the given input string.
+ *
+ * @param input Input string to retrieve the colors from.
+ * @return Any remaining ChatColors to pass onto the next line.
+ */
+ public static String getLastColors(String input) {
+ String result = "";
+ int length = input.length();
+
+ // Search backwards from the end as it is faster
+ for (int index = length - 1; index > -1; index--) {
+ char section = input.charAt(index);
+ if (section == COLOR_CHAR && index < length - 1) {
+ char c = input.charAt(index + 1);
+ ChatColor color = getByChar(c);
+
+ if (color != null) {
+ result = color.toString() + result;
+
+ // Once we find a color or reset we can stop searching
+ if (color.isColor() || color.equals(RESET)) {
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ static {
+ for (ChatColor color : values()) {
+ BY_ID.put(color.intCode, color);
+ BY_CHAR.put(color.code, color);
+ }
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Chunk.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Chunk.java
new file mode 100644
index 0000000..9017e6c
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Chunk.java
@@ -0,0 +1,129 @@
+package org.bukkit;
+
+import gg.ragemc.spigot.chunk.FakeMultiBlockChange;
+import org.bukkit.block.Block;
+import org.bukkit.block.BlockState;
+import org.bukkit.entity.Entity;
+
+/**
+ * Represents a chunk of blocks
+ */
+public interface Chunk {
+
+ /**
+ * Gets the X-coordinate of this chunk
+ *
+ * @return X-coordinate
+ */
+ int getX();
+
+ /**
+ * Gets the Z-coordinate of this chunk
+ *
+ * @return Z-coordinate
+ */
+ int getZ();
+
+ /**
+ * Gets the world containing this chunk
+ *
+ * @return Parent World
+ */
+ World getWorld();
+
+ /**
+ * Gets a block from this chunk
+ *
+ * @param x 0-15
+ * @param y 0-127
+ * @param z 0-15
+ * @return the Block
+ */
+ Block getBlock(int x, int y, int z);
+
+ /**
+ * Capture thread-safe read-only snapshot of chunk data
+ *
+ * @return ChunkSnapshot
+ */
+ ChunkSnapshot getChunkSnapshot();
+
+ /**
+ * Capture thread-safe read-only snapshot of chunk data
+ *
+ * @param includeMaxblocky - if true, snapshot includes per-coordinate
+ * maximum Y values
+ * @param includeBiome - if true, snapshot includes per-coordinate biome
+ * type
+ * @param includeBiomeTempRain - if true, snapshot includes per-coordinate
+ * raw biome temperature and rainfall
+ * @return ChunkSnapshot
+ */
+ ChunkSnapshot getChunkSnapshot(boolean includeMaxblocky, boolean includeBiome, boolean includeBiomeTempRain);
+
+ /**
+ * Get a list of all entities in the chunk.
+ *
+ * @return The entities.
+ */
+ Entity[] getEntities();
+
+ /**
+ * Get a list of all tile entities in the chunk.
+ *
+ * @return The tile entities.
+ */
+ BlockState[] getTileEntities();
+
+ /**
+ * Checks if the chunk is loaded.
+ *
+ * @return True if it is loaded.
+ */
+ boolean isLoaded();
+
+ /**
+ * Loads the chunk.
+ *
+ * @param generate Whether or not to generate a chunk if it doesn't
+ * already exist
+ * @return true if the chunk has loaded successfully, otherwise false
+ */
+ boolean load(boolean generate);
+
+ /**
+ * Loads the chunk.
+ *
+ * @return true if the chunk has loaded successfully, otherwise false
+ */
+ boolean load();
+
+ /**
+ * Unloads and optionally saves the Chunk
+ *
+ * @param save Controls whether the chunk is saved
+ * @param safe Controls whether to unload the chunk when players are
+ * nearby
+ * @return true if the chunk has unloaded successfully, otherwise false
+ */
+ boolean unload(boolean save, boolean safe);
+
+ /**
+ * Unloads and optionally saves the Chunk
+ *
+ * @param save Controls whether the chunk is saved
+ * @return true if the chunk has unloaded successfully, otherwise false
+ */
+ boolean unload(boolean save);
+
+ /**
+ * Unloads and optionally saves the Chunk
+ *
+ * @return true if the chunk has unloaded successfully, otherwise false
+ */
+ boolean unload();
+
+ // RageSpigot start
+ FakeMultiBlockChange createFakeBlockUpdate(final Location[] locations, final int[] ids, final int[] datas);
+ // RageSpigot end
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/ChunkSnapshot.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/ChunkSnapshot.java
new file mode 100644
index 0000000..83fccc8
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/ChunkSnapshot.java
@@ -0,0 +1,129 @@
+package org.bukkit;
+
+import org.bukkit.block.Biome;
+
+/**
+ * Represents a static, thread-safe snapshot of chunk of blocks.
+ *
+ * Purpose is to allow clean, efficient copy of a chunk data to be made, and
+ * then handed off for processing in another thread (e.g. map rendering)
+ */
+public interface ChunkSnapshot {
+
+ /**
+ * Gets the X-coordinate of this chunk
+ *
+ * @return X-coordinate
+ */
+ int getX();
+
+ /**
+ * Gets the Z-coordinate of this chunk
+ *
+ * @return Z-coordinate
+ */
+ int getZ();
+
+ /**
+ * Gets name of the world containing this chunk
+ *
+ * @return Parent World Name
+ */
+ String getWorldName();
+
+ /**
+ * Get block type for block at corresponding coordinate in the chunk
+ *
+ * @param x 0-15
+ * @param y 0-127
+ * @param z 0-15
+ * @return 0-255
+ * @deprecated Magic value
+ */
+ @Deprecated
+ int getBlockTypeId(int x, int y, int z);
+
+ /**
+ * Get block data for block at corresponding coordinate in the chunk
+ *
+ * @param x 0-15
+ * @param y 0-127
+ * @param z 0-15
+ * @return 0-15
+ * @deprecated Magic value
+ */
+ @Deprecated
+ int getBlockData(int x, int y, int z);
+
+ /**
+ * Get sky light level for block at corresponding coordinate in the chunk
+ *
+ * @param x 0-15
+ * @param y 0-127
+ * @param z 0-15
+ * @return 0-15
+ */
+ int getBlockSkyLight(int x, int y, int z);
+
+ /**
+ * Get light level emitted by block at corresponding coordinate in the
+ * chunk
+ *
+ * @param x 0-15
+ * @param y 0-127
+ * @param z 0-15
+ * @return 0-15
+ */
+ int getBlockEmittedLight(int x, int y, int z);
+
+ /**
+ * Gets the highest non-air coordinate at the given coordinates
+ *
+ * @param x X-coordinate of the blocks
+ * @param z Z-coordinate of the blocks
+ * @return Y-coordinate of the highest non-air block
+ */
+ int getHighestBlockYAt(int x, int z);
+
+ /**
+ * Get biome at given coordinates
+ *
+ * @param x X-coordinate
+ * @param z Z-coordinate
+ * @return Biome at given coordinate
+ */
+ Biome getBiome(int x, int z);
+
+ /**
+ * Get raw biome temperature (0.0-1.0) at given coordinate
+ *
+ * @param x X-coordinate
+ * @param z Z-coordinate
+ * @return temperature at given coordinate
+ */
+ double getRawBiomeTemperature(int x, int z);
+
+ /**
+ * Get raw biome rainfall (0.0-1.0) at given coordinate
+ *
+ * @param x X-coordinate
+ * @param z Z-coordinate
+ * @return rainfall at given coordinate
+ */
+ double getRawBiomeRainfall(int x, int z);
+
+ /**
+ * Get world full time when chunk snapshot was captured
+ *
+ * @return time in ticks
+ */
+ long getCaptureFullTime();
+
+ /**
+ * Test if section is empty
+ *
+ * @param sy - section Y coordinate (block Y / 16)
+ * @return true if empty, false if not
+ */
+ boolean isSectionEmpty(int sy);
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/CoalType.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/CoalType.java
new file mode 100644
index 0000000..4fcccd2
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/CoalType.java
@@ -0,0 +1,50 @@
+package org.bukkit;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+/**
+ * Represents the two types of coal
+ */
+public enum CoalType {
+ COAL(0x0),
+ CHARCOAL(0x1);
+
+ private final byte data;
+ private final static Map BY_DATA = Maps.newHashMap();
+
+ private CoalType(final int data) {
+ this.data = (byte) data;
+ }
+
+ /**
+ * Gets the associated data value representing this type of coal
+ *
+ * @return A byte containing the data value of this coal type
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public byte getData() {
+ return data;
+ }
+
+ /**
+ * Gets the type of coal with the given data value
+ *
+ * @param data Data value to fetch
+ * @return The {@link CoalType} representing the given value, or null if
+ * it doesn't exist
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static CoalType getByData(final byte data) {
+ return BY_DATA.get(data);
+ }
+
+ static {
+ for (CoalType type : values()) {
+ BY_DATA.put(type.data, type);
+ }
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Color.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Color.java
new file mode 100644
index 0000000..83927dd
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Color.java
@@ -0,0 +1,344 @@
+package org.bukkit;
+
+import java.util.Map;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.bukkit.configuration.serialization.SerializableAs;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * A container for a color palette. This class is immutable; the set methods
+ * return a new color. The color names listed as fields are HTML4 standards,
+ * but subject to change.
+ */
+@SerializableAs("Color")
+public final class Color implements ConfigurationSerializable {
+ private static final int BIT_MASK = 0xff;
+
+ /**
+ * White, or (0xFF,0xFF,0xFF) in (R,G,B)
+ */
+ public static final Color WHITE = fromRGB(0xFFFFFF);
+
+ /**
+ * Silver, or (0xC0,0xC0,0xC0) in (R,G,B)
+ */
+ public static final Color SILVER = fromRGB(0xC0C0C0);
+
+ /**
+ * Gray, or (0x80,0x80,0x80) in (R,G,B)
+ */
+ public static final Color GRAY = fromRGB(0x808080);
+
+ /**
+ * Black, or (0x00,0x00,0x00) in (R,G,B)
+ */
+ public static final Color BLACK = fromRGB(0x000000);
+
+ /**
+ * Red, or (0xFF,0x00,0x00) in (R,G,B)
+ */
+ public static final Color RED = fromRGB(0xFF0000);
+
+ /**
+ * Maroon, or (0x80,0x00,0x00) in (R,G,B)
+ */
+ public static final Color MAROON = fromRGB(0x800000);
+
+ /**
+ * Yellow, or (0xFF,0xFF,0x00) in (R,G,B)
+ */
+ public static final Color YELLOW = fromRGB(0xFFFF00);
+
+ /**
+ * Olive, or (0x80,0x80,0x00) in (R,G,B)
+ */
+ public static final Color OLIVE = fromRGB(0x808000);
+
+ /**
+ * Lime, or (0x00,0xFF,0x00) in (R,G,B)
+ */
+ public static final Color LIME = fromRGB(0x00FF00);
+
+ /**
+ * Green, or (0x00,0x80,0x00) in (R,G,B)
+ */
+ public static final Color GREEN = fromRGB(0x008000);
+
+ /**
+ * Aqua, or (0x00,0xFF,0xFF) in (R,G,B)
+ */
+ public static final Color AQUA = fromRGB(0x00FFFF);
+
+ /**
+ * Teal, or (0x00,0x80,0x80) in (R,G,B)
+ */
+ public static final Color TEAL = fromRGB(0x008080);
+
+ /**
+ * Blue, or (0x00,0x00,0xFF) in (R,G,B)
+ */
+ public static final Color BLUE = fromRGB(0x0000FF);
+
+ /**
+ * Navy, or (0x00,0x00,0x80) in (R,G,B)
+ */
+ public static final Color NAVY = fromRGB(0x000080);
+
+ /**
+ * Fuchsia, or (0xFF,0x00,0xFF) in (R,G,B)
+ */
+ public static final Color FUCHSIA = fromRGB(0xFF00FF);
+
+ /**
+ * Purple, or (0x80,0x00,0x80) in (R,G,B)
+ */
+ public static final Color PURPLE = fromRGB(0x800080);
+
+ /**
+ * Orange, or (0xFF,0xA5,0x00) in (R,G,B)
+ */
+ public static final Color ORANGE = fromRGB(0xFFA500);
+
+ private final byte red;
+ private final byte green;
+ private final byte blue;
+
+ /**
+ * Creates a new Color object from a red, green, and blue
+ *
+ * @param red integer from 0-255
+ * @param green integer from 0-255
+ * @param blue integer from 0-255
+ * @return a new Color object for the red, green, blue
+ * @throws IllegalArgumentException if any value is strictly {@literal >255 or <0}
+ */
+ public static Color fromRGB(int red, int green, int blue) throws IllegalArgumentException {
+ return new Color(red, green, blue);
+ }
+
+ /**
+ * Creates a new Color object from a blue, green, and red
+ *
+ * @param blue integer from 0-255
+ * @param green integer from 0-255
+ * @param red integer from 0-255
+ * @return a new Color object for the red, green, blue
+ * @throws IllegalArgumentException if any value is strictly {@literal >255 or <0}
+ */
+ public static Color fromBGR(int blue, int green, int red) throws IllegalArgumentException {
+ return new Color(red, green, blue);
+ }
+
+ /**
+ * Creates a new color object from an integer that contains the red,
+ * green, and blue bytes in the lowest order 24 bits.
+ *
+ * @param rgb the integer storing the red, green, and blue values
+ * @return a new color object for specified values
+ * @throws IllegalArgumentException if any data is in the highest order 8
+ * bits
+ */
+ public static Color fromRGB(int rgb) throws IllegalArgumentException {
+ Validate.isTrue((rgb >> 24) == 0, "Extrenuous data in: ", rgb);
+ return fromRGB(rgb >> 16 & BIT_MASK, rgb >> 8 & BIT_MASK, rgb >> 0 & BIT_MASK);
+ }
+
+ /**
+ * Creates a new color object from an integer that contains the blue,
+ * green, and red bytes in the lowest order 24 bits.
+ *
+ * @param bgr the integer storing the blue, green, and red values
+ * @return a new color object for specified values
+ * @throws IllegalArgumentException if any data is in the highest order 8
+ * bits
+ */
+ public static Color fromBGR(int bgr) throws IllegalArgumentException {
+ Validate.isTrue((bgr >> 24) == 0, "Extrenuous data in: ", bgr);
+ return fromBGR(bgr >> 16 & BIT_MASK, bgr >> 8 & BIT_MASK, bgr >> 0 & BIT_MASK);
+ }
+
+ private Color(int red, int green, int blue) {
+ Validate.isTrue(red >= 0 && red <= BIT_MASK, "Red is not between 0-255: ", red);
+ Validate.isTrue(green >= 0 && green <= BIT_MASK, "Green is not between 0-255: ", green);
+ Validate.isTrue(blue >= 0 && blue <= BIT_MASK, "Blue is not between 0-255: ", blue);
+
+ this.red = (byte) red;
+ this.green = (byte) green;
+ this.blue = (byte) blue;
+ }
+
+ /**
+ * Gets the red component
+ *
+ * @return red component, from 0 to 255
+ */
+ public int getRed() {
+ return BIT_MASK & red;
+ }
+
+ /**
+ * Creates a new Color object with specified component
+ *
+ * @param red the red component, from 0 to 255
+ * @return a new color object with the red component
+ */
+ public Color setRed(int red) {
+ return fromRGB(red, getGreen(), getBlue());
+ }
+
+ /**
+ * Gets the green component
+ *
+ * @return green component, from 0 to 255
+ */
+ public int getGreen() {
+ return BIT_MASK & green;
+ }
+
+ /**
+ * Creates a new Color object with specified component
+ *
+ * @param green the red component, from 0 to 255
+ * @return a new color object with the red component
+ */
+ public Color setGreen(int green) {
+ return fromRGB(getRed(), green, getBlue());
+ }
+
+ /**
+ * Gets the blue component
+ *
+ * @return blue component, from 0 to 255
+ */
+ public int getBlue() {
+ return BIT_MASK & blue;
+ }
+
+ /**
+ * Creates a new Color object with specified component
+ *
+ * @param blue the red component, from 0 to 255
+ * @return a new color object with the red component
+ */
+ public Color setBlue(int blue) {
+ return fromRGB(getRed(), getGreen(), blue);
+ }
+
+ /**
+ *
+ * @return An integer representation of this color, as 0xRRGGBB
+ */
+ public int asRGB() {
+ return getRed() << 16 | getGreen() << 8 | getBlue() << 0;
+ }
+
+ /**
+ *
+ * @return An integer representation of this color, as 0xBBGGRR
+ */
+ public int asBGR() {
+ return getBlue() << 16 | getGreen() << 8 | getRed() << 0;
+ }
+
+ /**
+ * Creates a new color with its RGB components changed as if it was dyed
+ * with the colors passed in, replicating vanilla workbench dyeing
+ *
+ * @param colors The DyeColors to dye with
+ * @return A new color with the changed rgb components
+ */
+ // TODO: Javadoc what this method does, not what it mimics. API != Implementation
+ public Color mixDyes(DyeColor... colors) {
+ Validate.noNullElements(colors, "Colors cannot be null");
+
+ Color[] toPass = new Color[colors.length];
+ for (int i = 0; i < colors.length; i++) {
+ toPass[i] = colors[i].getColor();
+ }
+
+ return mixColors(toPass);
+ }
+
+ /**
+ * Creates a new color with its RGB components changed as if it was dyed
+ * with the colors passed in, replicating vanilla workbench dyeing
+ *
+ * @param colors The colors to dye with
+ * @return A new color with the changed rgb components
+ */
+ // TODO: Javadoc what this method does, not what it mimics. API != Implementation
+ public Color mixColors(Color... colors) {
+ Validate.noNullElements(colors, "Colors cannot be null");
+
+ int totalRed = this.getRed();
+ int totalGreen = this.getGreen();
+ int totalBlue = this.getBlue();
+ int totalMax = Math.max(Math.max(totalRed, totalGreen), totalBlue);
+ for (Color color : colors) {
+ totalRed += color.getRed();
+ totalGreen += color.getGreen();
+ totalBlue += color.getBlue();
+ totalMax += Math.max(Math.max(color.getRed(), color.getGreen()), color.getBlue());
+ }
+
+ float averageRed = totalRed / (colors.length + 1);
+ float averageGreen = totalGreen / (colors.length + 1);
+ float averageBlue = totalBlue / (colors.length + 1);
+ float averageMax = totalMax / (colors.length + 1);
+
+ float maximumOfAverages = Math.max(Math.max(averageRed, averageGreen), averageBlue);
+ float gainFactor = averageMax / maximumOfAverages;
+
+ return Color.fromRGB((int) (averageRed * gainFactor), (int) (averageGreen * gainFactor), (int) (averageBlue * gainFactor));
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof Color)) {
+ return false;
+ }
+ final Color that = (Color) o;
+ return this.blue == that.blue && this.green == that.green && this.red == that.red;
+ }
+
+ @Override
+ public int hashCode() {
+ return asRGB() ^ Color.class.hashCode();
+ }
+
+ public Map serialize() {
+ return ImmutableMap.of(
+ "RED", getRed(),
+ "BLUE", getBlue(),
+ "GREEN", getGreen()
+ );
+ }
+
+ @SuppressWarnings("javadoc")
+ public static Color deserialize(Map map) {
+ return fromRGB(
+ asInt("RED", map),
+ asInt("GREEN", map),
+ asInt("BLUE", map)
+ );
+ }
+
+ private static int asInt(String string, Map map) {
+ Object value = map.get(string);
+ if (value == null) {
+ throw new IllegalArgumentException(string + " not in map " + map);
+ }
+ if (!(value instanceof Number)) {
+ throw new IllegalArgumentException(string + '(' + value + ") is not a number");
+ }
+ return ((Number) value).intValue();
+ }
+
+ @Override
+ public String toString() {
+ return "Color:[rgb0x" + Integer.toHexString(getRed()).toUpperCase() + Integer.toHexString(getGreen()).toUpperCase() + Integer.toHexString(getBlue()).toUpperCase() + "]";
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/CropState.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/CropState.java
new file mode 100644
index 0000000..ef0faf9
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/CropState.java
@@ -0,0 +1,81 @@
+package org.bukkit;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+/**
+ * Represents the different growth states of crops
+ */
+public enum CropState {
+
+ /**
+ * State when first seeded
+ */
+ SEEDED(0x0),
+ /**
+ * First growth stage
+ */
+ GERMINATED(0x1),
+ /**
+ * Second growth stage
+ */
+ VERY_SMALL(0x2),
+ /**
+ * Third growth stage
+ */
+ SMALL(0x3),
+ /**
+ * Fourth growth stage
+ */
+ MEDIUM(0x4),
+ /**
+ * Fifth growth stage
+ */
+ TALL(0x5),
+ /**
+ * Almost ripe stage
+ */
+ VERY_TALL(0x6),
+ /**
+ * Ripe stage
+ */
+ RIPE(0x7);
+
+ private final byte data;
+ private final static Map BY_DATA = Maps.newHashMap();
+
+ private CropState(final int data) {
+ this.data = (byte) data;
+ }
+
+ /**
+ * Gets the associated data value representing this growth state
+ *
+ * @return A byte containing the data value of this growth state
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public byte getData() {
+ return data;
+ }
+
+ /**
+ * Gets the CropState with the given data value
+ *
+ * @param data Data value to fetch
+ * @return The {@link CropState} representing the given value, or null if
+ * it doesn't exist
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static CropState getByData(final byte data) {
+ return BY_DATA.get(data);
+ }
+
+ static {
+ for (CropState cropState : values()) {
+ BY_DATA.put(cropState.getData(), cropState);
+ }
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Difficulty.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Difficulty.java
new file mode 100644
index 0000000..a8a5a78
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Difficulty.java
@@ -0,0 +1,72 @@
+package org.bukkit;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+/**
+ * Represents the various difficulty levels that are available.
+ */
+public enum Difficulty {
+ /**
+ * Players regain health over time, hostile mobs don't spawn, the hunger
+ * bar does not deplete.
+ */
+ PEACEFUL(0),
+
+ /**
+ * Hostile mobs spawn, enemies deal less damage than on normal difficulty,
+ * the hunger bar does deplete and starving deals up to 5 hearts of
+ * damage. (Default value)
+ */
+ EASY(1),
+
+ /**
+ * Hostile mobs spawn, enemies deal normal amounts of damage, the hunger
+ * bar does deplete and starving deals up to 9.5 hearts of damage.
+ */
+ NORMAL(2),
+
+ /**
+ * Hostile mobs spawn, enemies deal greater damage than on normal
+ * difficulty, the hunger bar does deplete and starving can kill players.
+ */
+ HARD(3);
+
+ private final int value;
+ private final static Map BY_ID = Maps.newHashMap();
+
+ private Difficulty(final int value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the difficulty value associated with this Difficulty.
+ *
+ * @return An integer value of this difficulty
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Gets the Difficulty represented by the specified value
+ *
+ * @param value Value to check
+ * @return Associative {@link Difficulty} with the given value, or null if
+ * it doesn't exist
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static Difficulty getByValue(final int value) {
+ return BY_ID.get(value);
+ }
+
+ static {
+ for (Difficulty diff : values()) {
+ BY_ID.put(diff.value, diff);
+ }
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/DyeColor.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/DyeColor.java
new file mode 100644
index 0000000..214806e
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/DyeColor.java
@@ -0,0 +1,239 @@
+package org.bukkit;
+
+import java.util.Map;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * All supported color values for dyes and cloth
+ */
+public enum DyeColor {
+
+ /**
+ * Represents white dye.
+ */
+ WHITE(0x0, 0xF, Color.WHITE, Color.fromRGB(0xF0F0F0)),
+ /**
+ * Represents orange dye.
+ */
+ ORANGE(0x1, 0xE, Color.fromRGB(0xD87F33), Color.fromRGB(0xEB8844)),
+ /**
+ * Represents magenta dye.
+ */
+ MAGENTA(0x2, 0xD, Color.fromRGB(0xB24CD8), Color.fromRGB(0xC354CD)),
+ /**
+ * Represents light blue dye.
+ */
+ LIGHT_BLUE(0x3, 0xC, Color.fromRGB(0x6699D8), Color.fromRGB(0x6689D3)),
+ /**
+ * Represents yellow dye.
+ */
+ YELLOW(0x4, 0xB, Color.fromRGB(0xE5E533), Color.fromRGB(0xDECF2A)),
+ /**
+ * Represents lime dye.
+ */
+ LIME(0x5, 0xA, Color.fromRGB(0x7FCC19), Color.fromRGB(0x41CD34)),
+ /**
+ * Represents pink dye.
+ */
+ PINK(0x6, 0x9, Color.fromRGB(0xF27FA5), Color.fromRGB(0xD88198)),
+ /**
+ * Represents gray dye.
+ */
+ GRAY(0x7, 0x8, Color.fromRGB(0x4C4C4C), Color.fromRGB(0x434343)),
+ /**
+ * Represents silver dye.
+ */
+ SILVER(0x8, 0x7, Color.fromRGB(0x999999), Color.fromRGB(0xABABAB)),
+ /**
+ * Represents cyan dye.
+ */
+ CYAN(0x9, 0x6, Color.fromRGB(0x4C7F99), Color.fromRGB(0x287697)),
+ /**
+ * Represents purple dye.
+ */
+ PURPLE(0xA, 0x5, Color.fromRGB(0x7F3FB2), Color.fromRGB(0x7B2FBE)),
+ /**
+ * Represents blue dye.
+ */
+ BLUE(0xB, 0x4, Color.fromRGB(0x334CB2), Color.fromRGB(0x253192)),
+ /**
+ * Represents brown dye.
+ */
+ BROWN(0xC, 0x3, Color.fromRGB(0x664C33), Color.fromRGB(0x51301A)),
+ /**
+ * Represents green dye.
+ */
+ GREEN(0xD, 0x2, Color.fromRGB(0x667F33), Color.fromRGB(0x3B511A)),
+ /**
+ * Represents red dye.
+ */
+ RED(0xE, 0x1, Color.fromRGB(0x993333), Color.fromRGB(0xB3312C)),
+ /**
+ * Represents black dye.
+ */
+ BLACK(0xF, 0x0, Color.fromRGB(0x191919), Color.fromRGB(0x1E1B1B));
+
+ private final byte woolData;
+ private final byte dyeData;
+ private final Color color;
+ private final Color firework;
+ private final static DyeColor[] BY_WOOL_DATA;
+ private final static DyeColor[] BY_DYE_DATA;
+ private final static Map BY_COLOR;
+ private final static Map BY_FIREWORK;
+
+ private DyeColor(final int woolData, final int dyeData, Color color, Color firework) {
+ this.woolData = (byte) woolData;
+ this.dyeData = (byte) dyeData;
+ this.color = color;
+ this.firework = firework;
+ }
+
+ /**
+ * Gets the associated (wool) data value representing this color.
+ *
+ * @return A byte containing the (wool) data value of this color
+ * @deprecated The name is misleading. It would imply {@link
+ * Material#INK_SACK} but uses {@link Material#WOOL}
+ * @see #getWoolData()
+ * @see #getDyeData()
+ */
+ @Deprecated
+ public byte getData() {
+ return getWoolData();
+ }
+
+ /**
+ * Gets the associated wool data value representing this color.
+ *
+ * @return A byte containing the wool data value of this color
+ * @see #getDyeData()
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public byte getWoolData() {
+ return woolData;
+ }
+
+ /**
+ * Gets the associated dye data value representing this color.
+ *
+ * @return A byte containing the dye data value of this color
+ * @see #getWoolData()
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public byte getDyeData() {
+ return dyeData;
+ }
+
+ /**
+ * Gets the color that this dye represents.
+ *
+ * @return The {@link Color} that this dye represents
+ */
+ public Color getColor() {
+ return color;
+ }
+
+ /**
+ * Gets the firework color that this dye represents.
+ *
+ * @return The {@link Color} that this dye represents
+ */
+ public Color getFireworkColor() {
+ return firework;
+ }
+
+ /**
+ * Gets the DyeColor with the given (wool) data value.
+ *
+ * @param data (wool) data value to fetch
+ * @return The {@link DyeColor} representing the given value, or null if
+ * it doesn't exist
+ * @deprecated The name is misleading. It would imply {@link
+ * Material#INK_SACK} but uses {@link Material#WOOL}
+ * @see #getByDyeData(byte)
+ * @see #getByWoolData(byte)
+ */
+ @Deprecated
+ public static DyeColor getByData(final byte data) {
+ return getByWoolData(data);
+ }
+
+ /**
+ * Gets the DyeColor with the given wool data value.
+ *
+ * @param data Wool data value to fetch
+ * @return The {@link DyeColor} representing the given value, or null if
+ * it doesn't exist
+ * @see #getByDyeData(byte)
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static DyeColor getByWoolData(final byte data) {
+ int i = 0xff & data;
+ if (i >= BY_WOOL_DATA.length) {
+ return null;
+ }
+ return BY_WOOL_DATA[i];
+ }
+
+ /**
+ * Gets the DyeColor with the given dye data value.
+ *
+ * @param data Dye data value to fetch
+ * @return The {@link DyeColor} representing the given value, or null if
+ * it doesn't exist
+ * @see #getByWoolData(byte)
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static DyeColor getByDyeData(final byte data) {
+ int i = 0xff & data;
+ if (i >= BY_DYE_DATA.length) {
+ return null;
+ }
+ return BY_DYE_DATA[i];
+ }
+
+ /**
+ * Gets the DyeColor with the given color value.
+ *
+ * @param color Color value to get the dye by
+ * @return The {@link DyeColor} representing the given value, or null if
+ * it doesn't exist
+ */
+ public static DyeColor getByColor(final Color color) {
+ return BY_COLOR.get(color);
+ }
+
+ /**
+ * Gets the DyeColor with the given firework color value.
+ *
+ * @param color Color value to get dye by
+ * @return The {@link DyeColor} representing the given value, or null if
+ * it doesn't exist
+ */
+ public static DyeColor getByFireworkColor(final Color color) {
+ return BY_FIREWORK.get(color);
+ }
+
+ static {
+ BY_WOOL_DATA = values();
+ BY_DYE_DATA = values();
+ ImmutableMap.Builder byColor = ImmutableMap.builder();
+ ImmutableMap.Builder byFirework = ImmutableMap.builder();
+
+ for (DyeColor color : values()) {
+ BY_WOOL_DATA[color.woolData & 0xff] = color;
+ BY_DYE_DATA[color.dyeData & 0xff] = color;
+ byColor.put(color.getColor(), color);
+ byFirework.put(color.getFireworkColor(), color);
+ }
+
+ BY_COLOR = byColor.build();
+ BY_FIREWORK = byFirework.build();
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Effect.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Effect.java
new file mode 100644
index 0000000..37f29e2
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Effect.java
@@ -0,0 +1,337 @@
+package org.bukkit;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+import org.bukkit.block.BlockFace;
+import org.bukkit.material.MaterialData;
+import org.bukkit.potion.Potion;
+
+/**
+ * A list of effects that the server is able to send to players.
+ */
+public enum Effect {
+ /**
+ * An alternate click sound.
+ */
+ CLICK2(1000, Type.SOUND),
+ /**
+ * A click sound.
+ */
+ CLICK1(1001, Type.SOUND),
+ /**
+ * Sound of a bow firing.
+ */
+ BOW_FIRE(1002, Type.SOUND),
+ /**
+ * Sound of a door opening/closing.
+ */
+ DOOR_TOGGLE(1003, Type.SOUND),
+ /**
+ * Sound of fire being extinguished.
+ */
+ EXTINGUISH(1004, Type.SOUND),
+ /**
+ * A song from a record. Needs the record item ID as additional info
+ */
+ RECORD_PLAY(1005, Type.SOUND, Material.class),
+ /**
+ * Sound of ghast shrieking.
+ */
+ GHAST_SHRIEK(1007, Type.SOUND),
+ /**
+ * Sound of ghast firing.
+ */
+ GHAST_SHOOT(1008, Type.SOUND),
+ /**
+ * Sound of blaze firing.
+ */
+ BLAZE_SHOOT(1009, Type.SOUND),
+ /**
+ * Sound of zombies chewing on wooden doors.
+ */
+ ZOMBIE_CHEW_WOODEN_DOOR(1010, Type.SOUND),
+ /**
+ * Sound of zombies chewing on iron doors.
+ */
+ ZOMBIE_CHEW_IRON_DOOR(1011, Type.SOUND),
+ /**
+ * Sound of zombies destroying a door.
+ */
+ ZOMBIE_DESTROY_DOOR(1012, Type.SOUND),
+ /**
+ * A visual smoke effect. Needs direction as additional info.
+ */
+ SMOKE(2000, Type.VISUAL, BlockFace.class),
+ /**
+ * Sound of a block breaking. Needs block ID as additional info.
+ */
+ STEP_SOUND(2001, Type.SOUND, Material.class),
+ /**
+ * Visual effect of a splash potion breaking. Needs potion data value as
+ * additional info.
+ */
+ POTION_BREAK(2002, Type.VISUAL, Potion.class),
+ /**
+ * An ender eye signal; a visual effect.
+ */
+ ENDER_SIGNAL(2003, Type.VISUAL),
+ /**
+ * The flames seen on a mobspawner; a visual effect.
+ */
+ 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;
+
+ private Effect(int id, Type type) {
+ this(id,type,null);
+ }
+
+ 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 if this Effect isn't of type PARTICLE it returns ID of this effect
+ * @deprecated Magic value
+ */
+ @Deprecated
+ 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.
+ */
+ public Type getType() {
+ return this.type;
+ }
+
+ /**
+ * @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;
+ }
+
+ /**
+ * Gets the Effect associated with the given ID.
+ *
+ * @param id ID of the Effect to return
+ * @return Effect with the given ID
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static Effect getById(int id) {
+ return BY_ID.get(id);
+ }
+
+ static {
+ for (Effect effect : values()) {
+ 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, PARTICLE}
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/EntityEffect.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/EntityEffect.java
new file mode 100644
index 0000000..c816edf
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/EntityEffect.java
@@ -0,0 +1,136 @@
+package org.bukkit;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+/**
+ * A list of all Effects that can happen to entities.
+ */
+public enum EntityEffect {
+
+ /**
+ * When mobs get hurt.
+ */
+ HURT(2),
+
+ /**
+ * When a mob dies.
+ *
+ * This will cause client-glitches!
+ */
+ DEATH(3),
+
+ /**
+ * The smoke when taming a wolf fails.
+ *
+ * Without client-mods this will be ignored if the entity is not a wolf.
+ */
+ WOLF_SMOKE(6),
+
+ /**
+ * The hearts when taming a wolf succeeds.
+ *
+ * Without client-mods this will be ignored if the entity is not a wolf.
+ */
+ WOLF_HEARTS(7),
+
+ /**
+ * When a wolf shakes (after being wet).
+ *
+ * Without client-mods this will be ignored if the entity is not a wolf.
+ */
+ WOLF_SHAKE(8),
+
+ /**
+ * When a sheep eats a LONG_GRASS block.
+ */
+ SHEEP_EAT(10),
+
+ /**
+ * When an Iron Golem gives a rose.
+ *
+ * This will not play an effect if the entity is not an iron golem.
+ */
+ IRON_GOLEM_ROSE(11),
+
+ /**
+ * Hearts from a villager.
+ *
+ * This will not play an effect if the entity is not a villager.
+ */
+ VILLAGER_HEART(12),
+
+ /**
+ * When a villager is angry.
+ *
+ * This will not play an effect if the entity is not a villager.
+ */
+ VILLAGER_ANGRY(13),
+
+ /**
+ * Happy particles from a villager.
+ *
+ * This will not play an effect if the entity is not a villager.
+ */
+ VILLAGER_HAPPY(14),
+
+ /**
+ * Magic particles from a witch.
+ *
+ * This will not play an effect if the entity is not a witch.
+ */
+ WITCH_MAGIC(15),
+
+ /**
+ * When a zombie transforms into a villager by shaking violently.
+ *
+ * This will not play an effect if the entity is not a zombie.
+ */
+ ZOMBIE_TRANSFORM(16),
+
+ /**
+ * When a firework explodes.
+ *
+ * This will not play an effect if the entity is not a firework.
+ */
+ FIREWORK_EXPLODE(17);
+
+ private final byte data;
+ private final static Map BY_DATA = Maps.newHashMap();
+
+ EntityEffect(final int data) {
+ this.data = (byte) data;
+ }
+
+ /**
+ * Gets the data value of this EntityEffect
+ *
+ * @return The data value
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public byte getData() {
+ return data;
+ }
+
+ /**
+ * Gets the EntityEffect with the given data value
+ *
+ * @param data Data value to fetch
+ * @return The {@link EntityEffect} representing the given value, or null
+ * if it doesn't exist
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static EntityEffect getByData(final byte data) {
+ return BY_DATA.get(data);
+ }
+
+
+ static {
+ for (EntityEffect entityEffect : values()) {
+ BY_DATA.put(entityEffect.data, entityEffect);
+ }
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/FireworkEffect.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/FireworkEffect.java
new file mode 100644
index 0000000..4b0687f
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/FireworkEffect.java
@@ -0,0 +1,424 @@
+package org.bukkit;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.Validate;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.bukkit.configuration.serialization.SerializableAs;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Represents a single firework effect.
+ */
+@SerializableAs("Firework")
+public final class FireworkEffect implements ConfigurationSerializable {
+
+ /**
+ * The type or shape of the effect.
+ */
+ public enum Type {
+ /**
+ * A small ball effect.
+ */
+ BALL,
+ /**
+ * A large ball effect.
+ */
+ BALL_LARGE,
+ /**
+ * A star-shaped effect.
+ */
+ STAR,
+ /**
+ * A burst effect.
+ */
+ BURST,
+ /**
+ * A creeper-face effect.
+ */
+ CREEPER,
+ ;
+ }
+
+ /**
+ * Construct a firework effect.
+ *
+ * @return A utility object for building a firework effect
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * This is a builder for FireworkEffects.
+ *
+ * @see FireworkEffect#builder()
+ */
+ public static final class Builder {
+ boolean flicker = false;
+ boolean trail = false;
+ final ImmutableList.Builder colors = ImmutableList.builder();
+ ImmutableList.Builder fadeColors = null;
+ Type type = Type.BALL;
+
+ Builder() {}
+
+ /**
+ * Specify the type of the firework effect.
+ *
+ * @param type The effect type
+ * @return This object, for chaining
+ * @throws IllegalArgumentException If type is null
+ */
+ public Builder with(Type type) throws IllegalArgumentException {
+ Validate.notNull(type, "Cannot have null type");
+ this.type = type;
+ return this;
+ }
+
+ /**
+ * Add a flicker to the firework effect.
+ *
+ * @return This object, for chaining
+ */
+ public Builder withFlicker() {
+ flicker = true;
+ return this;
+ }
+
+ /**
+ * Set whether the firework effect should flicker.
+ *
+ * @param flicker true if it should flicker, false if not
+ * @return This object, for chaining
+ */
+ public Builder flicker(boolean flicker) {
+ this.flicker = flicker;
+ return this;
+ }
+
+ /**
+ * Add a trail to the firework effect.
+ *
+ * @return This object, for chaining
+ */
+ public Builder withTrail() {
+ trail = true;
+ return this;
+ }
+
+ /**
+ * Set whether the firework effect should have a trail.
+ *
+ * @param trail true if it should have a trail, false for no trail
+ * @return This object, for chaining
+ */
+ public Builder trail(boolean trail) {
+ this.trail = trail;
+ return this;
+ }
+
+ /**
+ * Add a primary color to the firework effect.
+ *
+ * @param color The color to add
+ * @return This object, for chaining
+ * @throws IllegalArgumentException If color is null
+ */
+ public Builder withColor(Color color) throws IllegalArgumentException {
+ Validate.notNull(color, "Cannot have null color");
+
+ colors.add(color);
+
+ return this;
+ }
+
+ /**
+ * Add several primary colors to the firework effect.
+ *
+ * @param colors The colors to add
+ * @return This object, for chaining
+ * @throws IllegalArgumentException If colors is null
+ * @throws IllegalArgumentException If any color is null (may be
+ * thrown after changes have occurred)
+ */
+ public Builder withColor(Color...colors) throws IllegalArgumentException {
+ Validate.notNull(colors, "Cannot have null colors");
+ if (colors.length == 0) {
+ return this;
+ }
+
+ ImmutableList.Builder list = this.colors;
+ for (Color color : colors) {
+ Validate.notNull(color, "Color cannot be null");
+ list.add(color);
+ }
+
+ return this;
+ }
+
+ /**
+ * Add several primary colors to the firework effect.
+ *
+ * @param colors An iterable object whose iterator yields the desired
+ * colors
+ * @return This object, for chaining
+ * @throws IllegalArgumentException If colors is null
+ * @throws IllegalArgumentException If any color is null (may be
+ * thrown after changes have occurred)
+ */
+ public Builder withColor(Iterable> colors) throws IllegalArgumentException {
+ Validate.notNull(colors, "Cannot have null colors");
+
+ ImmutableList.Builder list = this.colors;
+ for (Object color : colors) {
+ if (!(color instanceof Color)) {
+ throw new IllegalArgumentException(color + " is not a Color in " + colors);
+ }
+ list.add((Color) color);
+ }
+
+ return this;
+ }
+
+ /**
+ * Add a fade color to the firework effect.
+ *
+ * @param color The color to add
+ * @return This object, for chaining
+ * @throws IllegalArgumentException If colors is null
+ * @throws IllegalArgumentException If any color is null (may be
+ * thrown after changes have occurred)
+ */
+ public Builder withFade(Color color) throws IllegalArgumentException {
+ Validate.notNull(color, "Cannot have null color");
+
+ if (fadeColors == null) {
+ fadeColors = ImmutableList.builder();
+ }
+
+ fadeColors.add(color);
+
+ return this;
+ }
+
+ /**
+ * Add several fade colors to the firework effect.
+ *
+ * @param colors The colors to add
+ * @return This object, for chaining
+ * @throws IllegalArgumentException If colors is null
+ * @throws IllegalArgumentException If any color is null (may be
+ * thrown after changes have occurred)
+ */
+ public Builder withFade(Color...colors) throws IllegalArgumentException {
+ Validate.notNull(colors, "Cannot have null colors");
+ if (colors.length == 0) {
+ return this;
+ }
+
+ ImmutableList.Builder list = this.fadeColors;
+ if (list == null) {
+ list = this.fadeColors = ImmutableList.builder();
+ }
+
+ for (Color color : colors) {
+ Validate.notNull(color, "Color cannot be null");
+ list.add(color);
+ }
+
+ return this;
+ }
+
+ /**
+ * Add several fade colors to the firework effect.
+ *
+ * @param colors An iterable object whose iterator yields the desired
+ * colors
+ * @return This object, for chaining
+ * @throws IllegalArgumentException If colors is null
+ * @throws IllegalArgumentException If any color is null (may be
+ * thrown after changes have occurred)
+ */
+ public Builder withFade(Iterable> colors) throws IllegalArgumentException {
+ Validate.notNull(colors, "Cannot have null colors");
+
+ ImmutableList.Builder list = this.fadeColors;
+ if (list == null) {
+ list = this.fadeColors = ImmutableList.builder();
+ }
+
+ for (Object color : colors) {
+ if (!(color instanceof Color)) {
+ throw new IllegalArgumentException(color + " is not a Color in " + colors);
+ }
+ list.add((Color) color);
+ }
+
+ return this;
+ }
+
+ /**
+ * Create a {@link FireworkEffect} from the current contents of this
+ * builder.
+ *
+ * To successfully build, you must have specified at least one color.
+ *
+ * @return The representative firework effect
+ */
+ public FireworkEffect build() {
+ return new FireworkEffect(
+ flicker,
+ trail,
+ colors.build(),
+ fadeColors == null ? ImmutableList.of() : fadeColors.build(),
+ type
+ );
+ }
+ }
+
+ private static final String FLICKER = "flicker";
+ private static final String TRAIL = "trail";
+ private static final String COLORS = "colors";
+ private static final String FADE_COLORS = "fade-colors";
+ private static final String TYPE = "type";
+
+ private final boolean flicker;
+ private final boolean trail;
+ private final ImmutableList colors;
+ private final ImmutableList fadeColors;
+ private final Type type;
+ private String string = null;
+
+ FireworkEffect(boolean flicker, boolean trail, ImmutableList colors, ImmutableList fadeColors, Type type) {
+ if (colors.isEmpty()) {
+ throw new IllegalStateException("Cannot make FireworkEffect without any color");
+ }
+ this.flicker = flicker;
+ this.trail = trail;
+ this.colors = colors;
+ this.fadeColors = fadeColors;
+ this.type = type;
+ }
+
+ /**
+ * Get whether the firework effect flickers.
+ *
+ * @return true if it flickers, false if not
+ */
+ public boolean hasFlicker() {
+ return flicker;
+ }
+
+ /**
+ * Get whether the firework effect has a trail.
+ *
+ * @return true if it has a trail, false if not
+ */
+ public boolean hasTrail() {
+ return trail;
+ }
+
+ /**
+ * Get the primary colors of the firework effect.
+ *
+ * @return An immutable list of the primary colors
+ */
+ public List getColors() {
+ return colors;
+ }
+
+ /**
+ * Get the fade colors of the firework effect.
+ *
+ * @return An immutable list of the fade colors
+ */
+ public List getFadeColors() {
+ return fadeColors;
+ }
+
+ /**
+ * Get the type of the firework effect.
+ *
+ * @return The effect type
+ */
+ public Type getType() {
+ return type;
+ }
+
+ /**
+ * @see ConfigurationSerializable
+ * @param map the map to deserialize
+ * @return the resulting serializable
+ */
+ public static ConfigurationSerializable deserialize(Map map) {
+ Type type = Type.valueOf((String) map.get(TYPE));
+ if (type == null) {
+ throw new IllegalArgumentException(map.get(TYPE) + " is not a valid Type");
+ }
+
+ return builder()
+ .flicker((Boolean) map.get(FLICKER))
+ .trail((Boolean) map.get(TRAIL))
+ .withColor((Iterable>) map.get(COLORS))
+ .withFade((Iterable>) map.get(FADE_COLORS))
+ .with(type)
+ .build();
+ }
+
+ @Override
+ public Map serialize() {
+ return ImmutableMap.of(
+ FLICKER, flicker,
+ TRAIL, trail,
+ COLORS, colors,
+ FADE_COLORS, fadeColors,
+ TYPE, type.name()
+ );
+ }
+
+ @Override
+ public String toString() {
+ final String string = this.string;
+ if (string == null) {
+ return this.string = "FireworkEffect:" + serialize();
+ }
+ return string;
+ }
+
+ @Override
+ public int hashCode() {
+ /**
+ * TRUE and FALSE as per boolean.hashCode()
+ */
+ final int PRIME = 31, TRUE = 1231, FALSE = 1237;
+ int hash = 1;
+ hash = hash * PRIME + (flicker ? TRUE : FALSE);
+ hash = hash * PRIME + (trail ? TRUE : FALSE);
+ hash = hash * PRIME + type.hashCode();
+ hash = hash * PRIME + colors.hashCode();
+ hash = hash * PRIME + fadeColors.hashCode();
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (!(obj instanceof FireworkEffect)) {
+ return false;
+ }
+
+ FireworkEffect that = (FireworkEffect) obj;
+ return this.flicker == that.flicker
+ && this.trail == that.trail
+ && this.type == that.type
+ && this.colors.equals(that.colors)
+ && this.fadeColors.equals(that.fadeColors);
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/GameMode.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/GameMode.java
new file mode 100644
index 0000000..803944e
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/GameMode.java
@@ -0,0 +1,73 @@
+package org.bukkit;
+
+import java.util.Map;
+
+import org.bukkit.entity.HumanEntity;
+
+import com.google.common.collect.Maps;
+
+/**
+ * Represents the various type of game modes that {@link HumanEntity}s may
+ * have
+ */
+public enum GameMode {
+ /**
+ * Creative mode may fly, build instantly, become invulnerable and create
+ * free items.
+ */
+ CREATIVE(1),
+
+ /**
+ * Survival mode is the "normal" gameplay type, with no special features.
+ */
+ SURVIVAL(0),
+
+ /**
+ * Adventure mode cannot break blocks without the correct tools.
+ */
+ ADVENTURE(2),
+
+ /**
+ * Spectator mode cannot interact with the world in anyway and is
+ * invisible to normal players. This grants the player the
+ * ability to no-clip through the world.
+ */
+ SPECTATOR(3);
+
+ private final int value;
+ private final static Map BY_ID = Maps.newHashMap();
+
+ private GameMode(final int value) {
+ this.value = value;
+ }
+
+ /**
+ * Gets the mode value associated with this GameMode
+ *
+ * @return An integer value of this gamemode
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public int getValue() {
+ return value;
+ }
+
+ /**
+ * Gets the GameMode represented by the specified value
+ *
+ * @param value Value to check
+ * @return Associative {@link GameMode} with the given value, or null if
+ * it doesn't exist
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static GameMode getByValue(final int value) {
+ return BY_ID.get(value);
+ }
+
+ static {
+ for (GameMode mode : values()) {
+ BY_ID.put(mode.getValue(), mode);
+ }
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/GrassSpecies.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/GrassSpecies.java
new file mode 100644
index 0000000..1111515
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/GrassSpecies.java
@@ -0,0 +1,61 @@
+package org.bukkit;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+/**
+ * Represents the different types of grass.
+ */
+public enum GrassSpecies {
+
+ /**
+ * Represents the dead looking grass.
+ */
+ DEAD(0x0),
+ /**
+ * Represents the normal grass species.
+ */
+ NORMAL(0x1),
+ /**
+ * Represents the fern-looking grass species.
+ */
+ FERN_LIKE(0x2);
+
+ private final byte data;
+ private final static Map BY_DATA = Maps.newHashMap();
+
+ private GrassSpecies(final int data) {
+ this.data = (byte) data;
+ }
+
+ /**
+ * Gets the associated data value representing this species
+ *
+ * @return A byte containing the data value of this grass species
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public byte getData() {
+ return data;
+ }
+
+ /**
+ * Gets the GrassSpecies with the given data value
+ *
+ * @param data Data value to fetch
+ * @return The {@link GrassSpecies} representing the given value, or null
+ * if it doesn't exist
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static GrassSpecies getByData(final byte data) {
+ return BY_DATA.get(data);
+ }
+
+ static {
+ for (GrassSpecies grassSpecies : values()) {
+ BY_DATA.put(grassSpecies.getData(), grassSpecies);
+ }
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Instrument.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Instrument.java
new file mode 100644
index 0000000..891a2b1
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Instrument.java
@@ -0,0 +1,67 @@
+package org.bukkit;
+
+import java.util.Map;
+
+import com.google.common.collect.Maps;
+
+public enum Instrument {
+
+ /**
+ * Piano is the standard instrument for a note block.
+ */
+ PIANO(0x0),
+ /**
+ * Bass drum is normally played when a note block is on top of a
+ * stone-like block
+ */
+ BASS_DRUM(0x1),
+ /**
+ * Snare drum is normally played when a note block is on top of a sandy
+ * block.
+ */
+ SNARE_DRUM(0x2),
+ /**
+ * Sticks are normally played when a note block is on top of a glass
+ * block.
+ */
+ STICKS(0x3),
+ /**
+ * Bass guitar is normally played when a note block is on top of a wooden
+ * block.
+ */
+ BASS_GUITAR(0x4);
+
+ private final byte type;
+ private final static Map BY_DATA = Maps.newHashMap();
+
+ private Instrument(final int type) {
+ this.type = (byte) type;
+ }
+
+ /**
+ * @return The type ID of this instrument.
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public byte getType() {
+ return this.type;
+ }
+
+ /**
+ * Get an instrument by its type ID.
+ *
+ * @param type The type ID
+ * @return The instrument
+ * @deprecated Magic value
+ */
+ @Deprecated
+ public static Instrument getByType(final byte type) {
+ return BY_DATA.get(type);
+ }
+
+ static {
+ for (Instrument instrument : Instrument.values()) {
+ BY_DATA.put(instrument.getType(), instrument);
+ }
+ }
+}
diff --git a/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Location.java b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Location.java
new file mode 100644
index 0000000..e7af316
--- /dev/null
+++ b/RageSpigot/RageSpigot-API/src/main/java/org/bukkit/Location.java
@@ -0,0 +1,600 @@
+package org.bukkit;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.bukkit.block.Block;
+import org.bukkit.configuration.serialization.ConfigurationSerializable;
+import org.bukkit.util.NumberConversions;
+import static org.bukkit.util.NumberConversions.checkFinite;
+import org.bukkit.util.Vector;
+
+/**
+ * Represents a 3-dimensional position in a world
+ */
+public class Location implements Cloneable, ConfigurationSerializable {
+ private World world;
+ private double x;
+ private double y;
+ private double z;
+ private float pitch;
+ private float yaw;
+
+ /**
+ * Constructs a new Location with the given coordinates
+ *
+ * @param world The world in which this location resides
+ * @param x The x-coordinate of this new location
+ * @param y The y-coordinate of this new location
+ * @param z The z-coordinate of this new location
+ */
+ public Location(final World world, final double x, final double y, final double z) {
+ this(world, x, y, z, 0, 0);
+ }
+
+ /**
+ * Constructs a new Location with the given coordinates and direction
+ *
+ * @param world The world in which this location resides
+ * @param x The x-coordinate of this new location
+ * @param y The y-coordinate of this new location
+ * @param z The z-coordinate of this new location
+ * @param yaw The absolute rotation on the x-plane, in degrees
+ * @param pitch The absolute rotation on the y-plane, in degrees
+ */
+ public Location(final World world, final double x, final double y, final double z, final float yaw, final float pitch) {
+ this.world = world;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ this.pitch = pitch;
+ this.yaw = yaw;
+ }
+
+ /**
+ * Sets the world that this location resides in
+ *
+ * @param world New world that this location resides in
+ */
+ public void setWorld(World world) {
+ this.world = world;
+ }
+
+ /**
+ * Gets the world that this location resides in
+ *
+ * @return World that contains this location
+ */
+ public World getWorld() {
+ return world;
+ }
+
+ /**
+ * Gets the chunk at the represented location
+ *
+ * @return Chunk at the represented location
+ */
+ public Chunk getChunk() {
+ return world.getChunkAt(this);
+ }
+
+ /**
+ * Gets the block at the represented location
+ *
+ * @return Block at the represented location
+ */
+ public Block getBlock() {
+ return world.getBlockAt(this);
+ }
+
+ /**
+ * Sets the x-coordinate of this location
+ *
+ * @param x X-coordinate
+ */
+ public void setX(double x) {
+ this.x = x;
+ }
+
+ /**
+ * Gets the x-coordinate of this location
+ *
+ * @return x-coordinate
+ */
+ public double getX() {
+ return x;
+ }
+
+ /**
+ * Gets the floored value of the X component, indicating the block that
+ * this location is contained with.
+ *
+ * @return block X
+ */
+ public int getBlockX() {
+ return locToBlock(x);
+ }
+
+ /**
+ * Sets the y-coordinate of this location
+ *
+ * @param y y-coordinate
+ */
+ public void setY(double y) {
+ this.y = y;
+ }
+
+ /**
+ * Gets the y-coordinate of this location
+ *
+ * @return y-coordinate
+ */
+ public double getY() {
+ return y;
+ }
+
+ /**
+ * Gets the floored value of the Y component, indicating the block that
+ * this location is contained with.
+ *
+ * @return block y
+ */
+ public int getBlockY() {
+ return locToBlock(y);
+ }
+
+ /**
+ * Sets the z-coordinate of this location
+ *
+ * @param z z-coordinate
+ */
+ public void setZ(double z) {
+ this.z = z;
+ }
+
+ /**
+ * Gets the z-coordinate of this location
+ *
+ * @return z-coordinate
+ */
+ public double getZ() {
+ return z;
+ }
+
+ /**
+ * Gets the floored value of the Z component, indicating the block that
+ * this location is contained with.
+ *
+ * @return block z
+ */
+ public int getBlockZ() {
+ return locToBlock(z);
+ }
+
+ /**
+ * Sets the yaw of this location, measured in degrees.
+ *
+ * - A yaw of 0 or 360 represents the positive z direction.
+ *
- A yaw of 180 represents the negative z direction.
+ *
- A yaw of 90 represents the negative x direction.
+ *
- A yaw of 270 represents the positive x direction.
+ *
+ * Increasing yaw values are the equivalent of turning to your
+ * right-facing, increasing the scale of the next respective axis, and
+ * decreasing the scale of the previous axis.
+ *
+ * @param yaw new rotation's yaw
+ */
+ public void setYaw(float yaw) {
+ this.yaw = yaw;
+ }
+
+ /**
+ * Gets the yaw of this location, measured in degrees.
+ *
+ * - A yaw of 0 or 360 represents the positive z direction.
+ *
- A yaw of 180 represents the negative z direction.
+ *
- A yaw of 90 represents the negative x direction.
+ *
- A yaw of 270 represents the positive x direction.
+ *
+ * Increasing yaw values are the equivalent of turning to your
+ * right-facing, increasing the scale of the next respective axis, and
+ * decreasing the scale of the previous axis.
+ *
+ * @return the rotation's yaw
+ */
+ public float getYaw() {
+ return yaw;
+ }
+
+ /**
+ * Sets the pitch of this location, measured in degrees.
+ *
+ * - A pitch of 0 represents level forward facing.
+ *
- A pitch of 90 represents downward facing, or negative y
+ * direction.
+ *
- A pitch of -90 represents upward facing, or positive y direction.
+ *
+ * Increasing pitch values the equivalent of looking down.
+ *
+ * @param pitch new incline's pitch
+ */
+ public void setPitch(float pitch) {
+ this.pitch = pitch;
+ }
+
+ /**
+ * Gets the pitch of this location, measured in degrees.
+ *
+ * - A pitch of 0 represents level forward facing.
+ *
- A pitch of 90 represents downward facing, or negative y
+ * direction.
+ *
- A pitch of -90 represents upward facing, or positive y direction.
+ *
+ * Increasing pitch values the equivalent of looking down.
+ *
+ * @return the incline's pitch
+ */
+ public float getPitch() {
+ return pitch;
+ }
+
+ /**
+ * Gets a unit-vector pointing in the direction that this Location is
+ * facing.
+ *
+ * @return a vector pointing the direction of this location's {@link
+ * #getPitch() pitch} and {@link #getYaw() yaw}
+ */
+ public Vector getDirection() {
+ Vector vector = new Vector();
+
+ double rotX = this.getYaw();
+ double rotY = this.getPitch();
+
+ vector.setY(-Math.sin(Math.toRadians(rotY)));
+
+ double xz = Math.cos(Math.toRadians(rotY));
+
+ vector.setX(-xz * Math.sin(Math.toRadians(rotX)));
+ vector.setZ(xz * Math.cos(Math.toRadians(rotX)));
+
+ return vector;
+ }
+
+ /**
+ * Sets the {@link #getYaw() yaw} and {@link #getPitch() pitch} to point
+ * in the direction of the vector.
+ *
+ * @param vector the direction vector
+ * @return the same location
+ */
+ public Location setDirection(Vector vector) {
+ /*
+ * Sin = Opp / Hyp
+ * Cos = Adj / Hyp
+ * Tan = Opp / Adj
+ *
+ * x = -Opp
+ * z = Adj
+ */
+ final double _2PI = 2 * Math.PI;
+ final double x = vector.getX();
+ final double z = vector.getZ();
+
+ if (x == 0 && z == 0) {
+ pitch = vector.getY() > 0 ? -90 : 90;
+ return this;
+ }
+
+ double theta = Math.atan2(-x, z);
+ yaw = (float) Math.toDegrees((theta + _2PI) % _2PI);
+
+ double x2 = NumberConversions.square(x);
+ double z2 = NumberConversions.square(z);
+ double xz = Math.sqrt(x2 + z2);
+ pitch = (float) Math.toDegrees(Math.atan(-vector.getY() / xz));
+
+ return this;
+ }
+
+ /**
+ * Adds the location by another.
+ *
+ * @see Vector
+ * @param vec The other location
+ * @return the same location
+ * @throws IllegalArgumentException for differing worlds
+ */
+ public Location add(Location vec) {
+ if (vec == null || vec.getWorld() != getWorld()) {
+ throw new IllegalArgumentException("Cannot add Locations of differing worlds");
+ }
+
+ x += vec.x;
+ y += vec.y;
+ z += vec.z;
+ return this;
+ }
+
+ /**
+ * Adds the location by a vector.
+ *
+ * @see Vector
+ * @param vec Vector to use
+ * @return the same location
+ */
+ public Location add(Vector vec) {
+ this.x += vec.getX();
+ this.y += vec.getY();
+ this.z += vec.getZ();
+ return this;
+ }
+
+ /**
+ * Adds the location by another. Not world-aware.
+ *
+ * @see Vector
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param z Z coordinate
+ * @return the same location
+ */
+ public Location add(double x, double y, double z) {
+ this.x += x;
+ this.y += y;
+ this.z += z;
+ return this;
+ }
+
+ /**
+ * Subtracts the location by another.
+ *
+ * @see Vector
+ * @param vec The other location
+ * @return the same location
+ * @throws IllegalArgumentException for differing worlds
+ */
+ public Location subtract(Location vec) {
+ if (vec == null || vec.getWorld() != getWorld()) {
+ throw new IllegalArgumentException("Cannot add Locations of differing worlds");
+ }
+
+ x -= vec.x;
+ y -= vec.y;
+ z -= vec.z;
+ return this;
+ }
+
+ /**
+ * Subtracts the location by a vector.
+ *
+ * @see Vector
+ * @param vec The vector to use
+ * @return the same location
+ */
+ public Location subtract(Vector vec) {
+ this.x -= vec.getX();
+ this.y -= vec.getY();
+ this.z -= vec.getZ();
+ return this;
+ }
+
+ /**
+ * Subtracts the location by another. Not world-aware and
+ * orientation independent.
+ *
+ * @see Vector
+ * @param x X coordinate
+ * @param y Y coordinate
+ * @param z Z coordinate
+ * @return the same location
+ */
+ public Location subtract(double x, double y, double z) {
+ this.x -= x;
+ this.y -= y;
+ this.z -= z;
+ return this;
+ }
+
+ /**
+ * Gets the magnitude of the location, defined as sqrt(x^2+y^2+z^2). The
+ * value of this method is not cached and uses a costly square-root
+ * function, so do not repeatedly call this method to get the location's
+ * magnitude. NaN will be returned if the inner result of the sqrt()
+ * function overflows, which will be caused if the length is too long. Not
+ * world-aware and orientation independent.
+ *
+ * @see Vector
+ * @return the magnitude
+ */
+ public double length() {
+ return Math.sqrt(NumberConversions.square(x) + NumberConversions.square(y) + NumberConversions.square(z));
+ }
+
+ /**
+ * Gets the magnitude of the location squared. Not world-aware and
+ * orientation independent.
+ *
+ * @see Vector
+ * @return the magnitude
+ */
+ public double lengthSquared() {
+ return NumberConversions.square(x) + NumberConversions.square(y) + NumberConversions.square(z);
+ }
+
+ /**
+ * Get the distance between this location and another. The value of this
+ * method is not cached and uses a costly square-root function, so do not
+ * repeatedly call this method to get the location's magnitude. NaN will
+ * be returned if the inner result of the sqrt() function overflows, which
+ * will be caused if the distance is too long.
+ *
+ * @see Vector
+ * @param o The other location
+ * @return the distance
+ * @throws IllegalArgumentException for differing worlds
+ */
+ public double distance(Location o) {
+ return Math.sqrt(distanceSquared(o));
+ }
+
+ /**
+ * Get the squared distance between this location and another.
+ *
+ * @see Vector
+ * @param o The other location
+ * @return the distance
+ * @throws IllegalArgumentException for differing worlds
+ */
+ public double distanceSquared(Location o) {
+ if (o == null) {
+ throw new IllegalArgumentException("Cannot measure distance to a null location");
+ } else if (o.getWorld() == null || getWorld() == null) {
+ throw new IllegalArgumentException("Cannot measure distance to a null world");
+ } else if (o.getWorld() != getWorld()) {
+ throw new IllegalArgumentException("Cannot measure distance between " + getWorld().getName() + " and " + o.getWorld().getName());
+ }
+
+ return NumberConversions.square(x - o.x) + NumberConversions.square(y - o.y) + NumberConversions.square(z - o.z);
+ }
+
+ /**
+ * Performs scalar multiplication, multiplying all components with a
+ * scalar. Not world-aware.
+ *
+ * @param m The factor
+ * @see Vector
+ * @return the same location
+ */
+ public Location multiply(double m) {
+ x *= m;
+ y *= m;
+ z *= m;
+ return this;
+ }
+
+ /**
+ * Zero this location's components. Not world-aware.
+ *
+ * @see Vector
+ * @return the same location
+ */
+ public Location zero() {
+ x = 0;
+ y = 0;
+ z = 0;
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Location other = (Location) obj;
+
+ if (this.world != other.world && (this.world == null || !this.world.equals(other.world))) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.x) != Double.doubleToLongBits(other.x)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.y) != Double.doubleToLongBits(other.y)) {
+ return false;
+ }
+ if (Double.doubleToLongBits(this.z) != Double.doubleToLongBits(other.z)) {
+ return false;
+ }
+ if (Float.floatToIntBits(this.pitch) != Float.floatToIntBits(other.pitch)) {
+ return false;
+ }
+ if (Float.floatToIntBits(this.yaw) != Float.floatToIntBits(other.yaw)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+
+ hash = 19 * hash + (this.world != null ? this.world.hashCode() : 0);
+ hash = 19 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32));
+ hash = 19 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32));
+ hash = 19 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32));
+ hash = 19 * hash + Float.floatToIntBits(this.pitch);
+ hash = 19 * hash + Float.floatToIntBits(this.yaw);
+ return hash;
+ }
+
+ @Override
+ public String toString() {
+ return "Location{" + "world=" + world + ",x=" + x + ",y=" + y + ",z=" + z + ",pitch=" + pitch + ",yaw=" + yaw + '}';
+ }
+
+ /**
+ * Constructs a new {@link Vector} based on this Location
+ *
+ * @return New Vector containing the coordinates represented by this
+ * Location
+ */
+ public Vector toVector() {
+ return new Vector(x, y, z);
+ }
+
+ @Override
+ public Location clone() {
+ try {
+ return (Location) super.clone();
+ } catch (CloneNotSupportedException e) {
+ throw new Error(e);
+ }
+ }
+
+ /**
+ * Safely converts a double (location coordinate) to an int (block
+ * coordinate)
+ *
+ * @param loc Precise coordinate
+ * @return Block coordinate
+ */
+ public static int locToBlock(double loc) {
+ return NumberConversions.floor(loc);
+ }
+
+ @Utility
+ public Map serialize() {
+ Map data = new HashMap();
+ data.put("world", this.world.getName());
+
+ data.put("x", this.x);
+ data.put("y", this.y);
+ data.put("z", this.z);
+
+ data.put("yaw", this.yaw);
+ data.put("pitch", this.pitch);
+
+ return data;
+ }
+
+ /**
+ * Required method for deserialization
+ *
+ * @param args map to deserialize
+ * @return deserialized location
+ * @throws IllegalArgumentException if the world don't exists
+ * @see ConfigurationSerializable
+ */
+ public static Location deserialize(Map