diff options
Diffstat (limited to 'src/main')
40 files changed, 2542 insertions, 0 deletions
diff --git a/src/main/java/org/bukkit/Block.java b/src/main/java/org/bukkit/Block.java new file mode 100644 index 00000000..0c32c321 --- /dev/null +++ b/src/main/java/org/bukkit/Block.java @@ -0,0 +1,102 @@ + +package org.bukkit; + +/** + * Represents a block + */ +public interface Block { + /** + * Gets the metadata for this block + * + * @return block specific metadata + */ + byte getData(); + + /** + * Gets the block at the given face + * + * @param face Face of this block to return + * @return Block at the given face + */ + Block getFace(BlockFace face); + + /** + * Gets the block at the given offsets + * + * @param modX X-coordinate offset + * @param modY Y-coordinate offset + * @param modZ Z-coordinate offset + * @return Block at the given offsets + */ + Block getRelative(int modX, int modY, int modZ); + + /** + * Gets the type of this block + * + * @return block type + */ + Material getType(); + + /** + * Gets the type-ID of this block + * + * @return block type-ID + */ + int getTypeID(); + + /** + * Gets the world which contains this Block + * + * @return World containing this block + */ + World getWorld(); + + /** + * Gets the x-coordinate of this block + * + * @return x-coordinate + */ + int getX(); + + /** + * Gets the y-coordinate of this block + * + * @return y-coordinate + */ + int getY(); + + /** + * Gets the z-coordinate of this block + * + * @return z-coordinate + */ + int getZ(); + + /** + * Gets the chunk which contains this block + * + * @return Containing Chunk + */ + Chunk getChunk(); + + /** + * Sets the metadata for this block + * + * @param data New block specific metadata + */ + void setData(byte data); + + /** + * Sets the type of this block + * + * @param type Material to change this block to + */ + void setType(Material type); + + /** + * Sets the type-ID of this block + * + * @param type Type-ID to change this block to + */ + void setTypeID(int type); +} diff --git a/src/main/java/org/bukkit/BlockFace.java b/src/main/java/org/bukkit/BlockFace.java new file mode 100644 index 00000000..aba16cbf --- /dev/null +++ b/src/main/java/org/bukkit/BlockFace.java @@ -0,0 +1,48 @@ +package org.bukkit; + +/** + * Represents the face of a block + */ +public enum BlockFace { + North(-1, 0, 0), + East(0, 0, -1), + South(1, 0, 0), + West(0, 0, 1), + Up(0, 1, 0), + Down(0, -1, 0), + Self(0, 0, 0); + + private final int modX; + private final int modY; + private final int modZ; + + private BlockFace(final int modX, final int modY, final int modZ) { + this.modX = modX; + this.modY = modY; + this.modZ = modZ; + } + + /** + * Get the amount of X-coordinates to modify to get the represented block + * @return Amount of X-coordinates to modify + */ + public int getModX() { + return modX; + } + + /** + * Get the amount of Y-coordinates to modify to get the represented block + * @return Amount of Y-coordinates to modify + */ + public int getModY() { + return modY; + } + + /** + * Get the amount of Z-coordinates to modify to get the represented block + * @return Amount of Z-coordinates to modify + */ + public int getModZ() { + return modZ; + } +} diff --git a/src/main/java/org/bukkit/Chunk.java b/src/main/java/org/bukkit/Chunk.java new file mode 100644 index 00000000..4bb9431f --- /dev/null +++ b/src/main/java/org/bukkit/Chunk.java @@ -0,0 +1,23 @@ + +package org.bukkit; + +/** + * 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(); + +} diff --git a/src/main/java/org/bukkit/Entity.java b/src/main/java/org/bukkit/Entity.java new file mode 100644 index 00000000..849bdd2d --- /dev/null +++ b/src/main/java/org/bukkit/Entity.java @@ -0,0 +1,35 @@ + +package org.bukkit; + +/** + * Represents a base entity in the world + */ +public interface Entity { + /** + * Gets the entitys current position + * + * @return Location containing the position of this entity + */ + public Location getLocation(); + + /** + * Gets the current world this entity resides in + * + * @return World + */ + public World getWorld(); + + /** + * Teleports this entity to the given location + * + * @param location New location to teleport this entity to + */ + public void teleportTo(Location location); + + /** + * Returns a unique ID for this entity + * + * @return Entity ID + */ + public int getEntityID(); +} diff --git a/src/main/java/org/bukkit/HumanEntity.java b/src/main/java/org/bukkit/HumanEntity.java new file mode 100644 index 00000000..349251d7 --- /dev/null +++ b/src/main/java/org/bukkit/HumanEntity.java @@ -0,0 +1,22 @@ + +package org.bukkit; + +/** + * Represents a human entity, such as an NPC or a player + */ +public interface HumanEntity extends LivingEntity { + /** + * Returns the name of this player + * + * @return Player name + */ + public String getName(); + + /** + * Gets the item this entity has currently selected, which will be shown in + * their hand + * + * @return ItemStack containing details on the item this entity has selected + */ + public ItemStack getSelectedItem(); +} diff --git a/src/main/java/org/bukkit/ItemStack.java b/src/main/java/org/bukkit/ItemStack.java new file mode 100644 index 00000000..2ca42274 --- /dev/null +++ b/src/main/java/org/bukkit/ItemStack.java @@ -0,0 +1,81 @@ + +package org.bukkit; + +/** + * Represents a stack of items + */ +public class ItemStack { + private int type; + private int amount = 0; + + public ItemStack(final int type) { + this.type = type; + } + + public ItemStack(final Material type) { + this(type.getID()); + } + + public ItemStack(final int type, final int amount) { + this.type = type; + this.amount = amount; + } + + public ItemStack(final Material type, final int amount) { + this(type.getID(), amount); + } + + /** + * Gets the type of this item + * + * @return Type of the items in this stack + */ + public Material getType() { + return Material.getMaterial(type); + } + + /** + * Sets the type of this item + * + * @param type New type to set the items in this stack to + */ + public void setType(Material type) { + this.type = type.getID(); + } + + /** + * Gets the type ID of this item + * + * @return Type ID of the items in this stack + */ + public int getTypeID() { + return type; + } + + /** + * Sets the type ID of this item + * + * @param type New type ID to set the items in this stack to + */ + public void setTypeID(int type) { + this.type = type; + } + + /** + * Gets the amount of items in this stack + * + * @return Amount of items in this stick + */ + public int getAmount() { + return amount; + } + + /** + * Sets the amount of items in this stack + * + * @param amount New amount of items in this stack + */ + public void setAmount(int amount) { + this.amount = amount; + } +} diff --git a/src/main/java/org/bukkit/LivingEntity.java b/src/main/java/org/bukkit/LivingEntity.java new file mode 100644 index 00000000..1fd153c9 --- /dev/null +++ b/src/main/java/org/bukkit/LivingEntity.java @@ -0,0 +1,21 @@ + +package org.bukkit; + +/** + * Represents a living entity, such as a monster or player + */ +public interface LivingEntity extends Entity { + /** + * Gets the entitys health from 0-20, where 0 is dead and 20 is full + * + * @return Health represented from 0-20 + */ + public int getHealth(); + + /** + * Sets the entitys health from 0-20, where 0 is dead and 20 is full + * + * @param health New health represented from 0-20 + */ + public void setHealth(int health); +} diff --git a/src/main/java/org/bukkit/Location.java b/src/main/java/org/bukkit/Location.java new file mode 100644 index 00000000..69329cd3 --- /dev/null +++ b/src/main/java/org/bukkit/Location.java @@ -0,0 +1,187 @@ + +package org.bukkit; + +/** + * Represents a 3-dimensional position in a world + */ +public class Location implements Cloneable { + private World world; + private double x; + private double y; + private double z; + private float pitch; + private float yaw; + + public Location(final World world, final double x, final double y, final double z) { + this(world, x, y, z, 0, 0); + } + + 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; + } + + /** + * 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; + } + + /** + * 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; + } + + /** + * 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; + } + + /** + * Sets the yaw of this location + * + * @param yaw New yaw + */ + public void setYaw(float yaw) { + this.yaw = yaw; + } + + /** + * Gets the yaw of this location + * + * @return Yaw + */ + public float getYaw() { + return yaw; + } + + /** + * Sets the pitch of this location + * + * @param pitch New pitch + */ + public void setPitch(float pitch) { + this.pitch = pitch; + } + + /** + * Gets the pitch of this location + * + * @return Pitch + */ + public float getPitch() { + return pitch; + } + + @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 + '}'; + } + + @Override + protected Location clone() { + return new Location(world, x, y, z, yaw, pitch); + } +} diff --git a/src/main/java/org/bukkit/Material.java b/src/main/java/org/bukkit/Material.java new file mode 100644 index 00000000..1b6323d7 --- /dev/null +++ b/src/main/java/org/bukkit/Material.java @@ -0,0 +1,205 @@ +package org.bukkit; + +import java.util.HashMap; +import java.util.Map; + +/** + * An enum of all material IDs accepted by the official server + client + */ +public enum Material { + Air(0), + Stone(1), + Grass(2), + Dirt(3), + Cobblestone(4), + Wood(5), + Sapling(6), + Bedrock(7), + Water(8), + StationaryWater(9), + Lava(10), + StationaryLava(11), + Sand(12), + Gravel(13), + GoldOre(14), + IronOre(15), + CoalOre(16), + Log(17), + Leaves(18), + Sponge(19), + Glass(20), + Cloth(35), + YellowFlower(37), + RedRose(38), + BrownMushroom(39), + RedMushroom(40), + GoldBlock(41), + IronBlock(42), + DoubleStep(43), + Step(44), + Brick(45), + TNT(46), + BookShelf(47), + MossyCobblestone(48), + Obsidian(49), + Torch(50), + Fire(51), + MobSpawner(52), + WoodStairs(53), + Chest(54), + RedstoneWire(55), + DiamondOre(56), + DiamondBlock(57), + Workbench(58), + Crops(59), + Soil(60), + Furnace(61), + BurningFurnace(62), + SignPost(63), + WoodenDoor(64), + Ladder(65), + Rails(66), + CobblestoneStairs(67), + WallSign(68), + Lever(69), + StonePlate(70), + IronDoorBlock(71), + WoodPlate(72), + RedstoneOre(73), + GlowingRedstoneOre(74), + RedstoneTorchOff(75), + RedstoneTorchOn(76), + StoneButton(77), + Snow(78), + Ice(79), + SnowBlock(80), + Cactus(81), + Clay(82), + ReedBlock(83), + Jukebox(84), + Fence(85), + Pumpkin(86), + Netherstone(87), + SlowSand(88), + LightStone(89), + Portal(90), + JackOLantern(91), + IronSpade(256), + IronPickaxe(257), + IronAxe(258), + FlintAndSteel(259), + Apple(260), + Bow(261), + Arrow(262), + Coal(263), + Diamond(264), + IronIngot(265), + GoldIngot(266), + IronSword(267), + WoodSword(268), + WoodSpade(269), + WoodPickaxe(270), + WoodAxe(271), + StoneSword(272), + StoneSpade(273), + StonePickaxe(274), + StoneAxe(275), + DiamondSword(276), + DiamondSpade(277), + DiamondPickaxe(278), + DiamondAxe(279), + Stick(280), + Bowl(281), + MushroomSoup(282), + GoldSword(283), + GoldSpade(284), + GoldPickaxe(285), + GoldAxe(286), + String(287), + Feather(288), + Gunpowder(289), + WoodHoe(290), + StoneHoe(291), + IronHoe(292), + DiamondHoe(293), + GoldHoe(294), + Seeds(295), + Wheat(296), + Bread(297), + LeatherHelmet(298), + LeatherChestplate(299), + LeatherLeggings(300), + LeatherBoots(301), + ChainmailHelmet(302), + ChainmailChestplate(303), + ChainmailLeggings(304), + ChainmailBoots(305), + IronHelmet(306), + IronChestplate(307), + IronLeggings(308), + IronBoots(309), + DiamondHelmet(310), + DiamondChestplate(311), + DiamondLeggings(312), + DiamondBoots(313), + GoldHelmet(314), + GoldChestplate(315), + GoldLeggings(316), + GoldBoots(317), + Flint(318), + Pork(319), + GrilledPork(320), + Painting(321), + GoldenApple(322), + Sign(323), + WoodDoor(324), + Bucket(325), + WaterBucket(326), + LavaBucket(327), + Minecart(328), + Saddle(329), + IronDoor(330), + RedStone(331), + SnowBall(332), + Boat(333), + Leather(334), + MilkBucket(335), + ClayBrick(336), + ClayBall(337), + Reed(338), + Paper(339), + Book(340), + SlimeBall(341), + StorageMinecart(342), + PoweredMinecart(343), + Egg(344), + Compass(345), + FishingRod(346), + Watch(347), + LightstoneDust(348), + RawFish(349), + CookedFish(350), + GoldRecord(2256), + GreenRecord(2257); + + private final int id; + private static final Map<Integer, Material> lookup = new HashMap<Integer, Material>(); + + private Material(final int id) { + this.id = id; + } + + public int getID() { + return id; + } + + public static Material getMaterial(final int id) { + return lookup.get(id); + } + + static { + for (Material material : values()) { + lookup.put(material.getID(), material); + } + } +} diff --git a/src/main/java/org/bukkit/Player.java b/src/main/java/org/bukkit/Player.java new file mode 100644 index 00000000..7d4c5ed7 --- /dev/null +++ b/src/main/java/org/bukkit/Player.java @@ -0,0 +1,22 @@ + +package org.bukkit; + +/** + * Represents a player, connected or not + * + */ +public interface Player extends HumanEntity { + /** + * Checks if this player is currently online + * + * @return true if they are online + */ + public boolean isOnline(); + + /** + * Sends this player a message, which will be displayed in their chat + * + * @param message Message to be displayed + */ + public void sendMessage(String message); +} diff --git a/src/main/java/org/bukkit/Server.java b/src/main/java/org/bukkit/Server.java new file mode 100644 index 00000000..1019423f --- /dev/null +++ b/src/main/java/org/bukkit/Server.java @@ -0,0 +1,44 @@ + +package org.bukkit; + +import org.bukkit.plugin.PluginManager; + +/** + * Represents a server implementation + */ +public interface Server { + /** + * Gets the name of this server implementation + * + * @return name of this server implementation + */ + public String getName(); + + /** + * Gets the version string of this server implementation. + * + * @return version of this server implementation + */ + public String getVersion(); + + /** + * Gets a list of all currently logged in players + * + * @return An array of Players that are currently online + */ + public Player[] getOnlinePlayers(); + + /** + * Gets the PluginManager for interfacing with plugins + * + * @return PluginManager for this Server instance + */ + public PluginManager getPluginManager(); + + /** + * Gets a list of all worlds on this server + * + * @return An array of worlds + */ + public World[] getWorlds(); +} diff --git a/src/main/java/org/bukkit/World.java b/src/main/java/org/bukkit/World.java new file mode 100644 index 00000000..1ff0d7b3 --- /dev/null +++ b/src/main/java/org/bukkit/World.java @@ -0,0 +1,18 @@ + +package org.bukkit; + +/** + * Represents a world. + * + * Currently there is only one world in the default Minecraft spec, but this + * may change with the addition of a functional Nether world + */ +public interface World { + public Block getBlockAt(int x, int y, int z); + + public Chunk getChunkAt(int x, int z); + + public Chunk getChunkAt(Block block); + + public boolean isChunkLoaded(); +} diff --git a/src/main/java/org/bukkit/event/Cancellable.java b/src/main/java/org/bukkit/event/Cancellable.java new file mode 100644 index 00000000..985dc1de --- /dev/null +++ b/src/main/java/org/bukkit/event/Cancellable.java @@ -0,0 +1,6 @@ +package org.bukkit.event; + +public interface Cancellable { + public boolean isCancelled(); + public void setCancelled(boolean cancel); +} diff --git a/src/main/java/org/bukkit/event/Event.java b/src/main/java/org/bukkit/event/Event.java new file mode 100644 index 00000000..2362a31d --- /dev/null +++ b/src/main/java/org/bukkit/event/Event.java @@ -0,0 +1,140 @@ + +package org.bukkit.event; + +/** + * Represents an event + */ +public abstract class Event { + private final Type type; + + protected Event(final Type type) { + this.type = type; + } + + /** + * Gets the Type of this event + * @return Server which this event was triggered on + */ + public Type getType() { + return type; + } + + /** + * Represents an events priority + */ + public enum Priority { + /** + * Event is critical and must be called near-first + */ + Highest, + + /** + * Event is of high importance + */ + High, + + /** + * Event is neither important or unimportant, and may be ran normally + */ + Normal, + + /** + * Event is of low importance + */ + Low, + + /** + * Event is of extremely low importance, most likely just to monitor events, and must be run near-last + */ + Lowest + } + + public enum Category { + PLAYER, + BLOCK, + ITEM, + ENVIRONMENT, + ENTITY, + VEHICLE, + INVENTORY, + SIGN, + CUSTOM; + } + + public enum Type { + /** + * Player Events + */ + PLAYER_JOIN (Category.PLAYER), + PLAYER_LOGIN (Category.PLAYER), + PLAYER_CHAT (Category.PLAYER), + PLAYER_COMMAND (Category.PLAYER), + PLAYER_QUIT (Category.PLAYER), + PLAYER_MOVE (Category.PLAYER), + //PLAYER_ANIMATION (Category.PLAYER), + PLAYER_TELEPORT (Category.PLAYER), + /** + * Block Events + */ + BLOCK_BROKEN (Category.BLOCK), + BLOCK_CANBUILD (Category.BLOCK), + BLOCK_FLOW (Category.BLOCK), + BLOCK_IGNITE (Category.BLOCK), + BLOCK_PHYSICS (Category.BLOCK), + BLOCK_PLACED (Category.BLOCK), + BLOCK_RIGHTCLICKED (Category.BLOCK), + REDSTONE_CHANGE (Category.BLOCK); + + + /** + * Item Events + + ITEM_DROP (Category.ITEM), + ITEM_PICK_UP (Category.ITEM), + ITEM_USE (Category.ITEM), + /** + * Environment Events + + IGNITE (Category.ENVIRONMENT), + FLOW (Category.ENVIRONMENT), + EXPLODE (Category.ENVIRONMENT), + LIQUID_DESTROY (Category.ENVIRONMENT), + /** + * Non-player Entity Events + + MOB_SPAWN (Category.ENTITY), + DAMAGE (Category.ENTITY), + HEALTH_CHANGE (Category.ENTITY), + ATTACK (Category.ENTITY), // Need to look into this category more + /** + * Vehicle Events + + VEHICLE_CREATE (Category.VEHICLE), + VEHICLE_UPDATE (Category.VEHICLE), + VEHICLE_DAMAGE (Category.VEHICLE), + VEHICLE_COLLISION (Category.VEHICLE), + VEHICLE_DESTROYED (Category.VEHICLE), + VEHICLE_ENTERED (Category.VEHICLE), + VEHICLE_POSITIONCHANGE (Category.VEHICLE), + /** + * Inventory Events + + OPEN_INVENTORY (Category.INVENTORY), + /** + * Sign Events (Item events??) + + SIGN_SHOW (Category.SIGN), + SIGN_CHANGE (Category.SIGN); + */ + + private Category category; + + private Type(Category category) { + this.category = category; + } + + public Category getCategory() { + return category; + } + } +} diff --git a/src/main/java/org/bukkit/event/EventException.java b/src/main/java/org/bukkit/event/EventException.java new file mode 100644 index 00000000..2abd7d94 --- /dev/null +++ b/src/main/java/org/bukkit/event/EventException.java @@ -0,0 +1,48 @@ +package org.bukkit.event; + +public class EventException extends Exception { + private static final long serialVersionUID = 3532808232324183999L; + private final Throwable cause; + + /** + * Constructs a new EventException based on the given Exception + * + * @param throwable Exception that triggered this Exception + */ + public EventException(Throwable throwable) { + cause = throwable; + } + + /** + * Constructs a new EventException + */ + public EventException() { + cause = null; + } + + /** + * Constructs a new EventException with the given message + */ + public EventException(Throwable cause, String message) { + super(message); + this.cause = cause; + } + + /** + * Constructs a new EventException with the given message + */ + public EventException(String message) { + super(message); + cause = null; + } + + /** + * If applicable, returns the Exception that triggered this Exception + * + * @return Inner exception, or null if one does not exist + */ + @Override + public Throwable getCause() { + return cause; + } +} diff --git a/src/main/java/org/bukkit/event/Listener.java b/src/main/java/org/bukkit/event/Listener.java new file mode 100644 index 00000000..004d18ed --- /dev/null +++ b/src/main/java/org/bukkit/event/Listener.java @@ -0,0 +1,9 @@ + +package org.bukkit.event; + +/** + * Simple interface for tagging all EventListeners + */ +public interface Listener { + +} diff --git a/src/main/java/org/bukkit/event/block/BlockBrokenEvent.java b/src/main/java/org/bukkit/event/block/BlockBrokenEvent.java new file mode 100644 index 00000000..800b84d8 --- /dev/null +++ b/src/main/java/org/bukkit/event/block/BlockBrokenEvent.java @@ -0,0 +1,13 @@ +package org.bukkit.event.block;
+
+import org.bukkit.Block;
+
+/**
+ * Not implemented yet
+ */
+public class BlockBrokenEvent extends BlockEvent {
+
+ public BlockBrokenEvent(Type type, Block block ) {
+ super(type, block);
+ }
+}
diff --git a/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java b/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java new file mode 100644 index 00000000..9853164f --- /dev/null +++ b/src/main/java/org/bukkit/event/block/BlockCanBuildEvent.java @@ -0,0 +1,47 @@ +/** + * + */ +package org.bukkit.event.block; + +import org.bukkit.Block; +import org.bukkit.Material; +import org.bukkit.event.Cancellable; + +/** + * @author durron597 + */ +public class BlockCanBuildEvent extends BlockEvent { + protected boolean buildable; + protected int material; + + public BlockCanBuildEvent(Type type, Block block, int id, boolean canBuild) { + super(type, block); + buildable = canBuild; + material = id; + } + + /** + * Returns whether or not the block can be built here. By default, returns + * Minecraft's answer on whether the block can be built + * + * @return boolean whether or not the block can be built + */ + public boolean isBuildable() { + return buildable; + } + + /** + * Set whether the block can be built here. + */ + public void setBuildable(boolean cancel) { + this.buildable = cancel; + } + + public Material getMaterial() { + return Material.getMaterial(material); + } + + public int getMaterialID() { + return material; + } +} diff --git a/src/main/java/org/bukkit/event/block/BlockEvent.java b/src/main/java/org/bukkit/event/block/BlockEvent.java new file mode 100644 index 00000000..6e50caed --- /dev/null +++ b/src/main/java/org/bukkit/event/block/BlockEvent.java @@ -0,0 +1,24 @@ +package org.bukkit.event.block; + +import org.bukkit.Block; +import org.bukkit.event.Event; + +/** + * Represents a block related event + */ +public class BlockEvent extends Event { + protected Block block; + + public BlockEvent(final Event.Type type, final Block theBlock) { + super(type); + block = theBlock; + } + + /** + * Returns the block involved in this event + * @return Block which block is involved in this event + */ + public final Block getBlock() { + return block; + } +} diff --git a/src/main/java/org/bukkit/event/block/BlockFromToEvent.java b/src/main/java/org/bukkit/event/block/BlockFromToEvent.java new file mode 100644 index 00000000..eb2846f9 --- /dev/null +++ b/src/main/java/org/bukkit/event/block/BlockFromToEvent.java @@ -0,0 +1,50 @@ +package org.bukkit.event.block; + +import org.bukkit.Block; +import org.bukkit.BlockFace; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; + +/** + * Holds information for events with a source block and a destination block + */ +public class BlockFromToEvent extends BlockEvent implements Cancellable { + protected Block from; + protected BlockFace face; + protected boolean cancel; + + public BlockFromToEvent(final Event.Type type, final Block block, final BlockFace face) { + super(type, block); + this.face = face; + this.from = block.getRelative(face.getModX(), face.getModY(), face.getModZ()); + this.cancel = false; + } + + /** + * Gets the location this player moved to + * + * @return Block the block is event originated from + */ + public BlockFace getFace() { + return face; + } + + /** + * Convenience method for getting the faced block + * + * @return Block the faced block + */ + public Block getFromBlock() { + return from; + } + + @Override + public boolean isCancelled() { + return cancel; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancel = cancel; + } +} diff --git a/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java b/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java new file mode 100644 index 00000000..90347096 --- /dev/null +++ b/src/main/java/org/bukkit/event/block/BlockIgniteEvent.java @@ -0,0 +1,19 @@ +package org.bukkit.event.block;
+
+import org.bukkit.event.Event;
+
+/**
+ * @author durron597
+ *
+ */
+public class BlockIgniteEvent extends Event {
+
+ /**
+ * @param type
+ */
+ public BlockIgniteEvent(Type type) {
+ super(type);
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/src/main/java/org/bukkit/event/block/BlockListener.java b/src/main/java/org/bukkit/event/block/BlockListener.java new file mode 100644 index 00000000..cef040c3 --- /dev/null +++ b/src/main/java/org/bukkit/event/block/BlockListener.java @@ -0,0 +1,81 @@ +package org.bukkit.event.block; + +import org.bukkit.event.Listener; + +/** + * Handles all events thrown in relation to Blocks + * + * @author durron597 + */ +public class BlockListener implements Listener { + /** + * Default Constructor + */ + public BlockListener() { + } + + /** + * Called when a block is broken (or destroyed) + * + * @param event Relevant event details + */ + public void onBlockBroken(BlockBrokenEvent event) { + } + + /** + * Called when we try to place a block, to see if we can build it + */ + public void onBlockCanBuild(BlockCanBuildEvent event) { + } + + /** + * Called when a block flows (water/lava) + * + * @param event Relevant event details + */ + public void onBlockFlow(BlockFromToEvent event) { + } + + /** + * Called when a block gets ignited + * + * @param event Relevant event details + */ + public void onBlockIgnite(BlockIgniteEvent event) { + } + + /** + * Called when block physics occurs + * + * @param event Relevant event details + */ + public void onBlockPhysics(BlockPhysicsEvent event) { + } + + /** + * Called when a player places a block + * + * @param event Relevant event details + */ + public void onBlockPlaced(BlockPlacedEvent event) { + } + + /** + * Called when redstone changes + * From: the source of the redstone change + * To: The redstone dust that changed + * + * @param event Relevant event details + */ + public void onBlockRedstoneChange(BlockFromToEvent event) { + } + + /** + * Called when a player right clicks a block + * + * @param event Relevant event details + */ + public void onBlockRightClicked(BlockRightClickedEvent event) { + } + +} diff --git a/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java b/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java new file mode 100644 index 00000000..addb6b18 --- /dev/null +++ b/src/main/java/org/bukkit/event/block/BlockPhysicsEvent.java @@ -0,0 +1,59 @@ +package org.bukkit.event.block; + +import org.bukkit.Block; +import org.bukkit.ItemStack; +import org.bukkit.Material; +import org.bukkit.event.Event; + +/** + * Thrown when a block physics check is called + * + * @author Dinnerbone + */ +public class BlockPhysicsEvent extends BlockEvent { + private final int changed; + private boolean cancel = false; + + public BlockPhysicsEvent(final Event.Type type, final Block block, final int changed) { + super(type, block); + this.changed = changed; + } + + /** + * Gets the type of block that changed, causing this event + * + * @return Changed block's type ID + */ + public int getChangedTypeID() { + return changed; + } + + /** + * Gets the type of block that changed, causing this event + * + * @return Changed block's type + */ + public Material getChangedType() { + return Material.getMaterial(changed); + } + + /** + * Gets the cancellation state of this event. A cancelled event will not + * be executed in the server, but will still pass to other plugins + * + * @return true if this event is cancelled + */ + public boolean isCancelled() { + return cancel; + } + + /** + * Sets the cancellation state of this event. A cancelled event will not + * be executed in the server, but will still pass to other plugins + * + * @param cancel true if you wish to cancel this event + */ + public void setCancelled(boolean cancel) { + this.cancel = cancel; + } +} diff --git a/src/main/java/org/bukkit/event/block/BlockPlacedEvent.java b/src/main/java/org/bukkit/event/block/BlockPlacedEvent.java new file mode 100644 index 00000000..de5d9427 --- /dev/null +++ b/src/main/java/org/bukkit/event/block/BlockPlacedEvent.java @@ -0,0 +1,32 @@ +package org.bukkit.event.block; + +import org.bukkit.Block; +import org.bukkit.event.Cancellable; + +/** + * Not implemented yet + */ +public class BlockPlacedEvent extends BlockEvent implements Cancellable { + private boolean cancel; + + /** + * @param type + * @param theBlock + */ + public BlockPlacedEvent(Type type, Block theBlock) { + super(type, theBlock); + cancel = false; + } + + @Override + public boolean isCancelled() { + // TODO Auto-generated method stub + return cancel; + } + + @Override + public void setCancelled(boolean cancel) { + this.cancel = cancel; + } + +} diff --git a/src/main/java/org/bukkit/event/block/BlockRightClickedEvent.java b/src/main/java/org/bukkit/event/block/BlockRightClickedEvent.java new file mode 100644 index 00000000..4f43492c --- /dev/null +++ b/src/main/java/org/bukkit/event/block/BlockRightClickedEvent.java @@ -0,0 +1,53 @@ +/**
+ *
+ */
+package org.bukkit.event.block;
+
+import org.bukkit.Block;
+import org.bukkit.BlockFace;
+import org.bukkit.ItemStack;
+import org.bukkit.Player;
+
+/**
+ * @author durron597
+ */
+public class BlockRightClickedEvent extends BlockEvent {
+ protected Player clicker;
+ protected BlockFace direction;
+ protected ItemStack clickedWith;
+
+ /**
+ * @param type The type of event this is
+ * @param theBlock The clicked block
+ * @param direction The face we clicked from
+ * @param clicker The player who clicked a block
+ * @param clickedWith Item in player's hand
+ */
+ public BlockRightClickedEvent(Type type, Block theBlock, BlockFace direction, Player clicker, ItemStack clickedWith) {
+ super(type, theBlock);
+ this.direction = direction;
+ this.clicker = clicker;
+ this.clickedWith = clickedWith;
+ }
+
+ /**
+ * @return the clicker
+ */
+ public Player getClicker() {
+ return clicker;
+ }
+
+ /**
+ * @return the direction
+ */
+ public BlockFace getDirection() {
+ return direction;
+ }
+
+ /**
+ * @return the clickedWith
+ */
+ public ItemStack getClickedWith() {
+ return clickedWith;
+ }
+}
diff --git a/src/main/java/org/bukkit/event/player/PlayerChatEvent.java b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java new file mode 100644 index 00000000..f67ebd86 --- /dev/null +++ b/src/main/java/org/bukkit/event/player/PlayerChatEvent.java @@ -0,0 +1,66 @@ + +package org.bukkit.event.player; + +import org.bukkit.Player; +import org.bukkit.event.Cancellable; + +/** + * Holds information for player chat and commands + */ +public class PlayerChatEvent extends PlayerEvent implements Cancellable { + private boolean cancel = false; + private String message; + + public PlayerChatEvent(final Type type, final Player player, final String message) { + super(type, player); + this.message = message; + } + + /** + * Gets the cancellation state of this event. A cancelled event will not + * be executed in the server, but will still pass to other plugins + * + * @return true if this event is cancelled + */ + public boolean isCancelled() { + return cancel; + } + + /** + * Sets the cancellation state of this event. A cancelled event will not + * be executed in the server, but will still pass to other plugins + * + * @param cancel true if you wish to cancel this event + */ + public void setCancelled(boolean cancel) { + this.cancel = cancel; + } + + /** + * Gets the message that the player is attempting to send + * + * @return Message the player is attempting to send + */ + public String getMessage() { + return message; + } + + /** + * Sets the message that the player will send + * + * @param message New message that the player will send + */ + public void setMessage(String message) { + this.message = message; + } + + /** + * Sets the player that this message will display as, or command will be + * executed as + * + * @param player New player which this event will execute as + */ + public void setPlayer(final Player player) { + this.player = player; + } +} diff --git a/src/main/java/org/bukkit/event/player/PlayerEvent.java b/src/main/java/org/bukkit/event/player/PlayerEvent.java new file mode 100644 index 00000000..2e4ea068 --- /dev/null +++ b/src/main/java/org/bukkit/event/player/PlayerEvent.java @@ -0,0 +1,25 @@ + +package org.bukkit.event.player; + +import org.bukkit.Player; +import org.bukkit.event.Event; + +/** + * Represents a player related event + */ +public class PlayerEvent extends Event { + protected Player player; + + public PlayerEvent(final Event.Type type, final Player who) { + super(type); + player = who; + } + + /** + * Returns the player involved in this event + * @return Player who is involved in this event + */ + public final Player getPlayer() { + return player; + } +} diff --git a/src/main/java/org/bukkit/event/player/PlayerListener.java b/src/main/java/org/bukkit/event/player/PlayerListener.java new file mode 100644 index 00000000..0c6817e2 --- /dev/null +++ b/src/main/java/org/bukkit/event/player/PlayerListener.java @@ -0,0 +1,68 @@ + +package org.bukkit.event.player; + +import org.bukkit.event.Listener; + +/** + * Handles all events thrown in relation to a Player + */ +public class PlayerListener implements Listener { + public PlayerListener() { + } + + /** + * Called when a player joins a server + * + * @param event Relevant event details + */ + public void onPlayerJoin(PlayerEvent event) { + } + + /** + * Called when a player leaves a server + * + * @param event Relevant event details + */ + public void onPlayerQuit(PlayerEvent event) { + } + + /** + * Called when a player sends a chat message + * + * @param event Relevant event details + */ + public void onPlayerChat(PlayerChatEvent event) { + } + + /** + * Called when a player attempts to use a command + * + * @param event Relevant event details + */ + public void onPlayerCommand(PlayerChatEvent event) { + } + + /** + * Called when a player attempts to move location in a world + * + * @param event Relevant event details + */ + public void onPlayerMove(PlayerMoveEvent event) { + } + + /** + * Called when a player attempts to teleport to a new location in a world + * + * @param event Relevant event details + */ + public void onPlayerTeleport(PlayerMoveEvent event) { + } + + /** + * Called when a player attempts to log in to the server + * + * @param event Relevant event details + */ + public void onPlayerLogin(PlayerLoginEvent event) { + } +} diff --git a/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java new file mode 100644 index 00000000..e19475a9 --- /dev/null +++ b/src/main/java/org/bukkit/event/player/PlayerLoginEvent.java @@ -0,0 +1,104 @@ + +package org.bukkit.event.player; + +import org.bukkit.Player; + +/** + * Stores details for players attempting to log in + */ +public class PlayerLoginEvent extends PlayerEvent { + private Result result; + private String message; + + public PlayerLoginEvent(final Type type, final Player player) { + super(type, player); + this.result = Result.ALLOWED; + this.message = ""; + } + + public PlayerLoginEvent(final Type type, final Player player, final Result result, final String message) { + super(type, player); + this.result = result; + this.message = message; + } + + /** + * Gets the current result of the login, as an enum + * + * @return Current Result of the login + */ + public Result getResult() { + return result; + } + + /** + * Sets the new result of the login, as an enum + * + * @param result New result to set + */ + public void setResult(final Result result) { + this.result = result; + } + + /** + * Gets the current kick message that will be used if getResult() != Result.ALLOWED + * + * @return Current kick message + */ + public String getKickMessage() { + return message; + } + + /** + * Sets the kick message to display if getResult() != Result.ALLOWED + * + * @param message New kick message + */ + public void setKickMessage(final String message) { + this.message = message; + } + + /** + * Allows the player to log in + */ + public void allow() { + result = Result.ALLOWED; + message = ""; + } + + /** + * Disallows the player from logging in, with the given reason + * + * @param result New result for disallowing the player + * @param message Kick message to display to the user + */ + public void disallow(final Result result, final String message) { + this.result = result; + this.message = message; + } + + /** + * Basic kick reasons for communicating to plugins + */ + public enum Result { + /** + * The player is allowed to log in + */ + ALLOWED, + + /** + * The player is not allowed to log in, due to the server being full + */ + KICK_FULL, + + /** + * The player is not allowed to log in, due to them being banned + */ + KICK_BANNED, + + /** + * The player is not allowed to log in, for reasons undefined + */ + KICK_OTHER + } +} diff --git a/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java new file mode 100644 index 00000000..24b31b59 --- /dev/null +++ b/src/main/java/org/bukkit/event/player/PlayerMoveEvent.java @@ -0,0 +1,86 @@ + +package org.bukkit.event.player; + +import org.bukkit.Location; +import org.bukkit.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.Event; + +/** + * Holds information for player movement and teleportation events + */ +public class PlayerMoveEvent extends PlayerEvent implements Cancellable { + private boolean cancel = false; + private Location from; + private Location to; + + public PlayerMoveEvent(final Event.Type type, final Player player, final Location from, final Location to) { + super(type, player); + this.from = from; + this.to = to; + } + + /** + * Gets the cancellation state of this event. A cancelled event will not + * be executed in the server, but will still pass to other plugins + * + * If a move or teleport event is cancelled, the player will be moved or + * teleported back to the Location as defined by getFrom(). This will not + * fire an event + * + * @return true if this event is cancelled + */ + public boolean isCancelled() { + return cancel; + } + + /** + * Sets the cancellation state of this event. A cancelled event will not + * be executed in the server, but will still pass to other plugins + * + * If a move or teleport event is cancelled, the player will be moved or + * teleported back to the Location as defined by getFrom(). This will not + * fire an event + * + * @param cancel true if you wish to cancel this event + */ + public void setCancelled(boolean cancel) { + this.cancel = cancel; + } + + /** + * Gets the location this player moved from + * + * @return Location the player moved from + */ + public Location getFrom() { + return from; + } + + /** + * Sets the location to mark as where the player moved from + * + * @param from New location to mark as the players previous location + */ + public void setFrom(Location from) { + this.from = from; + } + + /** + * Gets the location this player moved to + * + * @return Location the player moved to + */ + public Location getTo() { + return to; + } + + /** + * Sets the location that this player will move to + * + * @param to New Location this player will move to + */ + public void setTo(Location to) { + this.to = to; + } +} diff --git a/src/main/java/org/bukkit/plugin/InvalidDescriptionException.java b/src/main/java/org/bukkit/plugin/InvalidDescriptionException.java new file mode 100644 index 00000000..e6f03892 --- /dev/null +++ b/src/main/java/org/bukkit/plugin/InvalidDescriptionException.java @@ -0,0 +1,36 @@ + +package org.bukkit.plugin; + +/** + * Thrown when attempting to load an invalid PluginDescriptionFile + */ +public class InvalidDescriptionException extends Exception { + private static final long serialVersionUID = 5721389122281775894L; + private final Throwable cause; + + /** + * Constructs a new InvalidDescriptionException based on the given Exception + * + * @param throwable Exception that triggered this Exception + */ + public InvalidDescriptionException(Throwable throwable) { + cause = throwable; + } + + /** + * Constructs a new InvalidDescriptionException + */ + public InvalidDescriptionException() { + cause = null; + } + + /** + * If applicable, returns the Exception that triggered this Exception + * + * @return Inner exception, or null if one does not exist + */ + @Override + public Throwable getCause() { + return cause; + } +} diff --git a/src/main/java/org/bukkit/plugin/InvalidPluginException.java b/src/main/java/org/bukkit/plugin/InvalidPluginException.java new file mode 100644 index 00000000..4155723a --- /dev/null +++ b/src/main/java/org/bukkit/plugin/InvalidPluginException.java @@ -0,0 +1,36 @@ + +package org.bukkit.plugin; + +/** + * Thrown when attempting to load an invalid Plugin file + */ +public class InvalidPluginException extends Exception { + private static final long serialVersionUID = -8242141640709409542L; + private final Throwable cause; + + /** + * Constructs a new InvalidPluginException based on the given Exception + * + * @param throwable Exception that triggered this Exception + */ + public InvalidPluginException(Throwable throwable) { + cause = throwable; + } + + /** + * Constructs a new InvalidPluginException + */ + public InvalidPluginException() { + cause = null; + } + + /** + * If applicable, returns the Exception that triggered this Exception + * + * @return Inner exception, or null if one does not exist + */ + @Override + public Throwable getCause() { + return cause; + } +} diff --git a/src/main/java/org/bukkit/plugin/Plugin.java b/src/main/java/org/bukkit/plugin/Plugin.java new file mode 100644 index 00000000..e9097cdb --- /dev/null +++ b/src/main/java/org/bukkit/plugin/Plugin.java @@ -0,0 +1,47 @@ + +package org.bukkit.plugin; + +import org.bukkit.Server; + +/** + * Represents a Plugin + */ +public interface Plugin { + /** + * Returns the plugin.yaml file containing the details for this plugin + * + * @return Contents of the plugin.yaml file + */ + public PluginDescriptionFile getDescription(); + + /** + * Gets the associated PluginLoader responsible for this plugin + * + * @return PluginLoader that controls this plugin + */ + public PluginLoader getPluginLoader(); + + /** + * Returns the Server instance currently running this plugin + * + * @return Server running this plugin + */ + public Server getServer(); + + /** + * Returns a value indicating whether or not this plugin is currently enabled + * + * @return true if this plugin is enabled, otherwise false + */ + public boolean isEnabled(); + + /** + * Called when this plugin is disabled + */ + public void onDisable(); + + /** + * Called when this plugin is enabled + */ + public void onEnable(); +} diff --git a/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java new file mode 100644 index 00000000..9387d253 --- /dev/null +++ b/src/main/java/org/bukkit/plugin/PluginDescriptionFile.java @@ -0,0 +1,87 @@ + +package org.bukkit.plugin; + +import java.io.InputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.HashMap; +import java.util.Map; +import org.yaml.snakeyaml.Yaml; +import org.yaml.snakeyaml.constructor.SafeConstructor; + +/** + * Provides access to a Plugins description file, plugin.yaml + */ +public final class PluginDescriptionFile { + private static final Yaml yaml = new Yaml(new SafeConstructor()); + private String name = null; + private String main = null; + + public PluginDescriptionFile(final InputStream stream) throws InvalidDescriptionException { + try { + loadMap((Map<String, Object>)yaml.load(stream)); + } catch (ClassCastException ex) { + throw new InvalidDescriptionException(ex); + } + } + + /** + * Loads a PluginDescriptionFile from the specified reader + * @param reader + */ + public PluginDescriptionFile(final Reader reader) { + loadMap((Map<String, Object>)yaml.load(reader)); + } + + /** + * Creates a new PluginDescriptionFile with the given detailed + * + * @param pluginName Name of this plugin + * @param mainClass Full location of the main class of this plugin + */ + public PluginDescriptionFile(final String pluginName, final String mainClass) { + name = pluginName; + main = mainClass; + } + + /** + * Saves this PluginDescriptionFile to the given writer + * + * @param writer Writer to output this file to + */ + public void save(Writer writer) { + yaml.dump(saveMap(), writer); + } + + /** + * Returns the name of a plugin + * + * @return String name + */ + public String getName() { + return name; + } + + /** + * Returns the main class for a plugin + * + * @return Java classpath + */ + public String getMain() { + return main; + } + + private void loadMap(Map<String, Object> map) throws ClassCastException { + name = (String)map.get("name"); + main = (String)map.get("main"); + } + + private Map<String, Object> saveMap() { + Map<String, Object> map = new HashMap<String, Object>(); + + map.put("name", name); + map.put("main", main); + + return map; + } +} diff --git a/src/main/java/org/bukkit/plugin/PluginLoader.java b/src/main/java/org/bukkit/plugin/PluginLoader.java new file mode 100644 index 00000000..7d75f577 --- /dev/null +++ b/src/main/java/org/bukkit/plugin/PluginLoader.java @@ -0,0 +1,37 @@ + +package org.bukkit.plugin; + +import java.io.File; +import java.util.regex.Pattern; + +import org.bukkit.event.Event; + +/** + * Represents a plugin loader, which handles direct access to specific types + * of plugins + */ +public interface PluginLoader { + /** + * Loads the plugin contained in the specified file + * + * @param file File to attempt to load + * @return Plugin that was contained in the specified file, or null if + * unsuccessful + * @throws InvalidPluginException Thrown when the specified file is not a plugin + */ + public Plugin loadPlugin(File file) throws InvalidPluginException; + + /** + * Returns a list of all filename filters expected by this PluginLoader + */ + public Pattern[] getPluginFileFilters(); + + /** + * Calls a player related event with the given details + * + * @param registration Registered information on the plugin to call about this event + * @param type Type of player related event to call + * @param event Event details + */ + public void callEvent(RegisteredListener registration, Event event); +} diff --git a/src/main/java/org/bukkit/plugin/PluginManager.java b/src/main/java/org/bukkit/plugin/PluginManager.java new file mode 100644 index 00000000..a2f88cb1 --- /dev/null +++ b/src/main/java/org/bukkit/plugin/PluginManager.java @@ -0,0 +1,87 @@ + +package org.bukkit.plugin; + +import java.io.File; + +import org.bukkit.event.Event; +import org.bukkit.event.Event.Priority; +import org.bukkit.event.Listener; + +/** + * Handles all plugin management from the Server + */ +public interface PluginManager { + + /** + * Registers the specified plugin loader + * + * @param loader Class name of the PluginLoader to register + * @throws IllegalArgumentException Thrown when the given Class is not a valid PluginLoader + */ + public void RegisterInterface(Class loader) throws IllegalArgumentException; + + /** + * Checks if the given plugin is loaded and returns it when applicable + * + * Please note that the name of the plugin is case-sensitive + * + * @param name Name of the plugin to check + * @return Plugin if it exists, otherwise null + */ + public Plugin getPlugin(String name); + + /** + * Checks if the given plugin is enabled or not + * + * Please note that the name of the plugin is case-sensitive. + * + * @param name Name of the plugin to check + * @return true if the plugin is enabled, otherwise false + */ + public boolean isPluginEnabled(String name); + + /** + * Checks if the given plugin is enabled or not + * + * @param plugin Plugin to check + * @return true if the plugin is enabled, otherwise false + */ + public boolean isPluginEnabled(Plugin plugin); + + /** + * Loads the plugin in the specified file + * + * File must be valid according to the current enabled Plugin interfaces + * + * @param file File containing the plugin to load + * @return The Plugin loaded, or null if it was invalid + * @throws InvalidPluginException Thrown when the specified file is not a valid plugin + */ + public Plugin loadPlugin(File file) throws InvalidPluginException; + + /** + * Loads the plugins contained within the specified directory + * + * @param directory Directory to check for plugins + * @return A list of all plugins loaded + */ + public Plugin[] loadPlugins(File directory); + + /** + * Calls a player related event with the given details + * + * @param type Type of player related event to call + * @param event Event details + */ + public void callEvent(Event event); + + /** + * Registers the given event to the specified listener + * + * @param type EventType to register + * @param listener Listener to register + * @param priority Priority of this event + * @param plugin Plugin to register + */ + public void registerEvent(Event.Type type, Listener listener, Priority priority, Plugin plugin); +} diff --git a/src/main/java/org/bukkit/plugin/RegisteredListener.java b/src/main/java/org/bukkit/plugin/RegisteredListener.java new file mode 100644 index 00000000..1ee5a1c7 --- /dev/null +++ b/src/main/java/org/bukkit/plugin/RegisteredListener.java @@ -0,0 +1,44 @@ + +package org.bukkit.plugin; + +import org.bukkit.event.Event; +import org.bukkit.event.Listener; + +/** + * Stores relevant information for plugin listeners + */ +public class RegisteredListener { + private final Listener listener; + private final Event.Priority priority; + private final Plugin plugin; + + public RegisteredListener(final Listener pluginListener, final Event.Priority eventPriority, final Plugin registeredPlugin) { + listener = pluginListener; + priority = eventPriority; + plugin = registeredPlugin; + } + + /** + * Gets the listener for this registration + * @return Registered Listener + */ + public Listener getListener() { + return listener; + } + + /** + * Gets the plugin for this registration + * @return Registered Plugin + */ + public Plugin getPlugin() { + return plugin; + } + + /** + * Gets the priority for this registration + * @return Registered Priority + */ + public Event.Priority getPriority() { + return priority; + } +} diff --git a/src/main/java/org/bukkit/plugin/SimplePluginManager.java b/src/main/java/org/bukkit/plugin/SimplePluginManager.java new file mode 100644 index 00000000..d2c4b770 --- /dev/null +++ b/src/main/java/org/bukkit/plugin/SimplePluginManager.java @@ -0,0 +1,216 @@ + +package org.bukkit.plugin; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.regex.Matcher; +import org.bukkit.Server; +import java.util.regex.Pattern; + +import org.bukkit.event.Event; +import org.bukkit.event.Event.Priority; +import org.bukkit.event.Listener; + +/** + * Handles all plugin management from the Server + */ +public final class SimplePluginManager implements PluginManager { + private final Server server; + private final Map<Pattern, PluginLoader> fileAssociations = new HashMap<Pattern, PluginLoader>(); + private final List<Plugin> plugins = new ArrayList<Plugin>(); + private final Map<String, Plugin> lookupNames = new HashMap<String, Plugin>(); + private final Map<Event.Type, List<RegisteredListener>> listeners = new EnumMap<Event.Type, List<RegisteredListener>>(Event.Type.class); + + public SimplePluginManager(Server instance) { + server = instance; + } + + /** + * Registers the specified plugin loader + * + * @param loader Class name of the PluginLoader to register + * @throws IllegalArgumentException Thrown when the given Class is not a valid PluginLoader + */ + public void RegisterInterface(Class loader) throws IllegalArgumentException { + PluginLoader instance; + + if (PluginLoader.class.isAssignableFrom(loader)) { + Constructor constructor; + try { + constructor = loader.getConstructor(Server.class); + instance = (PluginLoader) constructor.newInstance(server); + } catch (NoSuchMethodException ex) { + throw new IllegalArgumentException(String.format("Class %s does not have a public %s(Server) constructor", loader.getName()), ex); + } catch (Exception ex) { + throw new IllegalArgumentException(String.format("Unexpected exception %s while attempting to construct a new instance of %s", ex.getClass().getName(), loader.getName()), ex); + } + } else { + throw new IllegalArgumentException(String.format("Class %s does not implement interface PluginLoader", loader.getName())); + } + + Pattern[] patterns = instance.getPluginFileFilters(); + + for (Pattern pattern : patterns) { + fileAssociations.put(pattern, instance); + } + } + + /** + * Loads the plugins contained within the specified directory + * + * @param directory Directory to check for plugins + * @return A list of all plugins loaded + */ + public Plugin[] loadPlugins(File directory) { + List<Plugin> result = new ArrayList<Plugin>(); + File[] files = directory.listFiles(); + + for (File file : files) { + Plugin plugin = null; + + try { + plugin = loadPlugin(file); + } catch (InvalidPluginException ex) { + Logger.getLogger(SimplePluginManager.class.getName()).log(Level.SEVERE, "Could not load " + file.getPath() + " in " + directory.getPath(), ex); + } + + if (plugin != null) { + result.add(plugin); + } + } + + return result.toArray(new Plugin[result.size()]); + } + + /** + * Loads the plugin in the specified file + * + * File must be valid according to the current enabled Plugin interfaces + * + * @param file File containing the plugin to load + * @return The Plugin loaded, or null if it was invalid + * @throws InvalidPluginException Thrown when the specified file is not a valid plugin + */ + public Plugin loadPlugin(File file) throws InvalidPluginException { + Set<Pattern> filters = fileAssociations.keySet(); + Plugin result = null; + + for (Pattern filter : filters) { + String name = file.getName(); + Matcher match = filter.matcher(name); + + if (match.find()) { + PluginLoader loader = fileAssociations.get(filter); + result = loader.loadPlugin(file); + } + } + + if (result != null) { + plugins.add(result); + lookupNames.put(result.getDescription().getName(), result); + } + + return result; + } + + /** + * Checks if the given plugin is loaded and returns it when applicable + * + * Please note that the name of the plugin is case-sensitive + * + * @param name Name of the plugin to check + * @return Plugin if it exists, otherwise null + */ + public Plugin getPlugin(String name) { + return lookupNames.get(name); + } + + /** + * Checks if the given plugin is enabled or not + * + * Please note that the name of the plugin is case-sensitive. + * + * @param name Name of the plugin to check + * @return true if the plugin is enabled, otherwise false + */ + public boolean isPluginEnabled(String name) { + Plugin plugin = getPlugin(name); + + return isPluginEnabled(plugin); + } + + /** + * Checks if the given plugin is enabled or not + * + * @param plugin Plugin to check + * @return true if the plugin is enabled, otherwise false + */ + public boolean isPluginEnabled(Plugin plugin) { + if ((plugin != null) && (plugins.contains(plugin))) { + return plugin.isEnabled(); + } else { + return false; + } + } + + /** + * Calls a player related event with the given details + * + * @param type Type of player related event to call + * @param event Event details + */ + public void callEvent(Event event) { + List<RegisteredListener> eventListeners = listeners.get(event.getType()); + + if (eventListeners != null) { + for (RegisteredListener registration : eventListeners) { + Plugin plugin = registration.getPlugin(); + PluginLoader loader = plugin.getPluginLoader(); + + if (plugin.isEnabled()) { + try { + loader.callEvent(registration, event); + } catch (Throwable ex) { + Logger.getLogger(SimplePluginManager.class.getName()).log(Level.SEVERE, "Could not pass event " + event.getType() + " to " + plugin.getDescription().getName(), ex); + } + } + } + } + } + + /** + * Registers the given event to the specified listener + * + * @param type EventType to register + * @param listener PlayerListener to register + * @param priority Priority of this event + * @param plugin Plugin to register + */ + public void registerEvent(Event.Type type, Listener listener, Priority priority, Plugin plugin) { + List<RegisteredListener> eventListeners = listeners.get(type); + int position = 0; + + if (eventListeners != null) { + for (RegisteredListener registration : eventListeners) { + if (registration.getPriority().compareTo(priority) < 0) { + break; + } + + position++; + } + } else { + eventListeners = new ArrayList<RegisteredListener>(); + listeners.put(type, eventListeners); + } + + eventListeners.add(position, new RegisteredListener(listener, priority, plugin)); + } +} diff --git a/src/main/java/org/bukkit/plugin/java/JavaPlugin.java b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java new file mode 100644 index 00000000..7692e3d5 --- /dev/null +++ b/src/main/java/org/bukkit/plugin/java/JavaPlugin.java @@ -0,0 +1,91 @@ + +package org.bukkit.plugin.java; + +import java.io.File; +import org.bukkit.Server; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; +import org.bukkit.plugin.PluginLoader; + +/** + * Represents a Java plugin + */ +public abstract class JavaPlugin implements Plugin { + private boolean isEnabled = true; + private final PluginLoader loader; + private final Server server; + private final File file; + private final PluginDescriptionFile description; + private final ClassLoader classLoader; + + /** + * Constructs a new Java plugin instance + * + * @param pluginLoader PluginLoader that is responsible for this plugin + * @param instance Server instance that is running this plugin + * @param desc PluginDescriptionFile containing metadata on this plugin + * @param plugin File containing this plugin + * @param cLoader ClassLoader which holds this plugin + */ + public JavaPlugin(PluginLoader pluginLoader, Server instance, PluginDescriptionFile desc, File plugin, ClassLoader cLoader) { + loader = pluginLoader; + server = instance; + file = plugin; + description = desc; + classLoader = cLoader; + } + + /** + * Gets the associated PluginLoader responsible for this plugin + * + * @return PluginLoader that controls this plugin + */ + public final PluginLoader getPluginLoader() { + return loader; + } + + /** + * Returns the Server instance currently running this plugin + * + * @return Server running this plugin + */ + public final Server getServer() { + return server; + } + + /** + * Returns a value indicating whether or not this plugin is currently enabled + * + * @return true if this plugin is enabled, otherwise false + */ + public final boolean isEnabled() { + return isEnabled; + } + + /** + * Returns the file which contains this plugin + * + * @return File containing this plugin + */ + protected File getFile() { + return file; + } + + /** + * Returns the plugin.yaml file containing the details for this plugin + * + * @return Contents of the plugin.yaml file + */ + public PluginDescriptionFile getDescription() { + return description; + } + + /** + * Returns the ClassLoader which holds this plugin + * + * @return ClassLoader holding this plugin + */ + protected ClassLoader getClassLoader() { + return classLoader; + } +} diff --git a/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java new file mode 100644 index 00000000..40753b02 --- /dev/null +++ b/src/main/java/org/bukkit/plugin/java/JavaPluginLoader.java @@ -0,0 +1,123 @@ + +package org.bukkit.plugin.java; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Constructor; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.regex.Pattern; +import org.bukkit.Server; +import org.bukkit.event.Event; +import org.bukkit.event.Listener; +import org.bukkit.event.block.*; +import org.bukkit.event.player.*; +import org.bukkit.plugin.*; + +/** + * Represents a Java plugin loader, allowing plugins in the form of .jar + */ +public final class JavaPluginLoader implements PluginLoader { + private final Server server; + private final Pattern[] fileFilters = new Pattern[] { + Pattern.compile("\\.jar$"), + }; + + public JavaPluginLoader(Server instance) { + server = instance; + } + + public Plugin loadPlugin(File file) throws InvalidPluginException { + JavaPlugin result = null; + PluginDescriptionFile description = null; + + if (!file.exists()) { + throw new InvalidPluginException(new FileNotFoundException(String.format("%s does not exist", file.getPath()))); + } + try { + JarFile jar = new JarFile(file); + JarEntry entry = jar.getJarEntry("plugin.yml"); + + if (entry == null) { + throw new InvalidPluginException(new FileNotFoundException("Jar does not contain plugin.yml")); + } + + InputStream stream = jar.getInputStream(entry); + description = new PluginDescriptionFile(stream); + + stream.close(); + jar.close(); + } catch (IOException ex) { + throw new InvalidPluginException(ex); + } catch (InvalidDescriptionException ex) { + throw new InvalidPluginException(ex); + } + + try { + ClassLoader loader = URLClassLoader.newInstance(new URL[]{file.toURI().toURL()}, getClass().getClassLoader()); + Class<?> jarClass = Class.forName(description.getMain(), true, loader); + Class<? extends JavaPlugin> plugin = jarClass.asSubclass(JavaPlugin.class); + Constructor<? extends JavaPlugin> constructor = plugin.getConstructor(PluginLoader.class, Server.class, PluginDescriptionFile.class, File.class, ClassLoader.class); + + result = constructor.newInstance(this, server, description, file, loader); + } catch (Throwable ex) { + throw new InvalidPluginException(ex); + } + + return (Plugin)result; + } + + public Pattern[] getPluginFileFilters() { + return fileFilters; + } + + public void callEvent(RegisteredListener registration, Event event) { + Listener listener = registration.getListener(); + + if (listener instanceof PlayerListener) { + PlayerListener trueListener = (PlayerListener)listener; + + switch (event.getType()) { + case PLAYER_JOIN: + trueListener.onPlayerJoin((PlayerEvent)event); + break; + case PLAYER_QUIT: + trueListener.onPlayerQuit((PlayerEvent)event); + break; + case PLAYER_COMMAND: + trueListener.onPlayerCommand((PlayerChatEvent)event); + break; + case PLAYER_CHAT: + trueListener.onPlayerChat((PlayerChatEvent)event); + break; + case PLAYER_MOVE: + trueListener.onPlayerMove((PlayerMoveEvent)event); + break; + case PLAYER_TELEPORT: + trueListener.onPlayerTeleport((PlayerMoveEvent)event); + break; + case PLAYER_LOGIN: + trueListener.onPlayerLogin((PlayerLoginEvent)event); + break; + } + } else if (listener instanceof BlockListener) { + BlockListener trueListener = (BlockListener)listener; + + switch (event.getType()) { + case BLOCK_PHYSICS: + trueListener.onBlockPhysics((BlockPhysicsEvent)event); + break; + case BLOCK_CANBUILD: + trueListener.onBlockCanBuild((BlockCanBuildEvent)event); + break; + case BLOCK_FLOW: + trueListener.onBlockFlow((BlockFromToEvent)event); + break; + } + } + } +} |