diff --git a/paper-server/.gitignore b/paper-server/.gitignore index 9c0573a55d..9c628f5f76 100644 --- a/paper-server/.gitignore +++ b/paper-server/.gitignore @@ -6,6 +6,9 @@ # netbeans /nbproject +# we use maven! +/build.xml + # maven /target diff --git a/paper-server/README.md b/paper-server/README.md new file mode 100644 index 0000000000..d5719e2ff9 --- /dev/null +++ b/paper-server/README.md @@ -0,0 +1,13 @@ +CraftBukkit +=========== + +A Bukkit (Minecraft Server API) implementation + +Compilation +----------- + +We use maven to handle our dependencies. + +* Install [Maven 3](http://maven.apache.org/download.html) +* Check out and install [Bukkit](http://github.com/Bukkit/Bukkit) +* Check out this repo and: `mvn clean package` diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftBlock.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftBlock.java index 19dce3c70e..64b13a4fe3 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftBlock.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftBlock.java @@ -1,7 +1,11 @@ package org.bukkit.craftbukkit; +import net.minecraft.server.MobSpawnerBase; import org.bukkit.*; +import org.bukkit.block.BlockState; +import org.bukkit.craftbukkit.block.CraftBlockState; +import org.bukkit.craftbukkit.block.CraftSign; public class CraftBlock implements Block { private final CraftWorld world; @@ -113,10 +117,11 @@ public class CraftBlock implements Block { * Sets the type-ID of this block * * @param type Type-ID to change this block to + * @return whether the block was changed */ - public void setTypeID(final int type) { + public boolean setTypeID(final int type) { this.type = type; - world.getHandle().d(x, y, z, type); + return world.getHandle().d(x, y, z, type); } /** @@ -153,7 +158,27 @@ public class CraftBlock implements Block { * @return Block at the given face */ public Block getFace(final BlockFace face) { - return getRelative(face.getModX(), face.getModY(), face.getModZ()); + return getFace(face, 1); + } + + /** + * Gets the block at the given distance of the given face
+ *
+ * For example, the following method places water at 100,102,100; two blocks + * above 100,100,100. + *
+     * Block block = world.getBlockAt(100,100,100);
+     * Block shower = block.getFace(BlockFace.Up, 2);
+     * shower.setType(Material.WATER);
+     * 
+ * + * @param face Face of this block to return + * @param distance Distance to get the block at + * @return Block at the given face + */ + public Block getFace(final BlockFace face, final int distance) { + return getRelative(face.getModX() * distance, face.getModY() * distance, + face.getModZ() * distance); } /** @@ -168,6 +193,38 @@ public class CraftBlock implements Block { return getWorld().getBlockAt(getX() + modX, getY() + modY, getZ() + modZ); } + /** + * Gets the face relation of this block compared to the given block
+ *
+ * For example: + *
+     * Block current = world.getBlockAt(100, 100, 100);
+     * Block target = world.getBlockAt(100, 101, 100);
+     *
+     * current.getFace(target) == BlockFace.Up;
+     * 
+ *
+ * If the given block is not connected to this block, null may be returned + * + * @param block Block to compare against this block + * @return BlockFace of this block which has the requested block, or null + */ + public BlockFace getFace(final Block block) { + BlockFace[] values = BlockFace.values(); + + for (BlockFace face : values) { + if ( + (this.getX() + face.getModX() == block.getX()) && + (this.getY() + face.getModY() == block.getY()) && + (this.getZ() + face.getModZ() == block.getZ()) + ) { + return face; + } + } + + return null; + } + @Override public String toString() { return "CraftBlock{" + "world=" + world + "x=" + x + "y=" + y + "z=" + z + "type=" + type + "data=" + data + '}'; @@ -197,4 +254,50 @@ public class CraftBlock implements Block { return BlockFace.Self; } } + + public BlockState getState() { + Material material = getType(); + + switch (material) { + case Sign: + case SignPost: + case WallSign: + return new CraftSign(this); + default: + return new CraftBlockState(this); + } + } + + public Biome getBiome() { + // TODO: This may not be 100% accurate; investigate into getting per-block instead of per-chunk + MobSpawnerBase base = world.getHandle().a().a(chunk.getX(), chunk.getZ()); + + if (base == MobSpawnerBase.a) { + return Biome.RAINFOREST; + } else if (base == MobSpawnerBase.b) { + return Biome.SWAMPLAND; + } else if (base == MobSpawnerBase.c) { + return Biome.SEASONAL_FOREST; + } else if (base == MobSpawnerBase.d) { + return Biome.FOREST; + } else if (base == MobSpawnerBase.e) { + return Biome.SAVANNA; + } else if (base == MobSpawnerBase.f) { + return Biome.SHRUBLAND; + } else if (base == MobSpawnerBase.g) { + return Biome.TAIGA; + } else if (base == MobSpawnerBase.h) { + return Biome.DESERT; + } else if (base == MobSpawnerBase.i) { + return Biome.PLAINS; + } else if (base == MobSpawnerBase.j) { + return Biome.ICE_DESERT; + } else if (base == MobSpawnerBase.k) { + return Biome.TUNDRA; + } else if (base == MobSpawnerBase.l) { + return Biome.HELL; + } + + return null; + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftBoat.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftBoat.java new file mode 100644 index 0000000000..cad1e40779 --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftBoat.java @@ -0,0 +1,18 @@ +package org.bukkit.craftbukkit; + +import net.minecraft.server.EntityBoat; +import org.bukkit.Boat; + +/** + * A minecart. + * + * @author sk89q + */ +public class CraftBoat extends CraftVehicle implements Boat { + protected EntityBoat boat; + + public CraftBoat(CraftServer server, EntityBoat entity) { + super(server, entity); + boat = entity; + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftEntity.java index 11e5847e31..d9ac3190e9 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftEntity.java @@ -4,6 +4,8 @@ package org.bukkit.craftbukkit; import net.minecraft.server.Entity; import net.minecraft.server.WorldServer; import org.bukkit.Location; +import org.bukkit.Vector; +import org.bukkit.Vehicle; import org.bukkit.World; public abstract class CraftEntity implements org.bukkit.Entity { @@ -19,6 +21,16 @@ public abstract class CraftEntity implements org.bukkit.Entity { return new Location(getWorld(), entity.p, entity.q, entity.r, entity.v, entity.w); } + public Vector getVelocity() { + return new Vector(entity.s, entity.t, entity.u); + } + + public void setVelocity(Vector vel) { + entity.s = vel.getX(); + entity.t = vel.getY(); + entity.u = vel.getZ(); + } + public World getWorld() { return ((WorldServer)entity.l).getWorld(); } @@ -27,6 +39,10 @@ public abstract class CraftEntity implements org.bukkit.Entity { entity.b(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); } + public void teleportTo(org.bukkit.Entity destination) { + teleportTo(destination.getLocation()); + } + public int getEntityID() { return entity.g; } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftHumanEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftHumanEntity.java index b03f096725..91437f4f8c 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftHumanEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftHumanEntity.java @@ -2,22 +2,18 @@ package org.bukkit.craftbukkit; import net.minecraft.server.EntityPlayer; -import net.minecraft.server.InventoryPlayer; import org.bukkit.HumanEntity; import org.bukkit.ItemStack; +import org.bukkit.PlayerInventory; public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { private EntityPlayer entity; + private CraftInventoryPlayer inventory; public CraftHumanEntity(final CraftServer server, final EntityPlayer entity) { super(server, entity); this.entity = entity; - } - - public ItemStack getSelectedItem() { - // TODO: Implement inventories - final InventoryPlayer inventory = entity.an; - return new ItemStack(inventory.e().c, inventory.e().a); + this.inventory = new CraftInventoryPlayer( entity.an ); } public String getName() { @@ -34,6 +30,14 @@ public class CraftHumanEntity extends CraftLivingEntity implements HumanEntity { this.entity = entity; } + public PlayerInventory getInventory() { + return inventory; + } + + public ItemStack getItemInHand() { + return getInventory().getItemInHand(); + } + @Override public String toString() { return "CraftHumanEntity{" + "id=" + getEntityID() + "name=" + getName() + '}'; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftInventory.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftInventory.java new file mode 100644 index 0000000000..c74ecea373 --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftInventory.java @@ -0,0 +1,195 @@ +package org.bukkit.craftbukkit; + +import java.util.HashMap; + +import net.minecraft.server.IInventory; + +import org.bukkit.ItemStack; +import org.bukkit.Material; + +public class CraftInventory implements org.bukkit.Inventory { + protected IInventory inventory; + + public CraftInventory(IInventory inventory) { + this.inventory = inventory; + } + + public IInventory getInventory() { + return inventory; + } + + public int getSize() { + return getInventory().a(); + } + + public String getName() { + return getInventory().b(); + } + + public ItemStack getItem(int index) { + return new CraftItemStack(getInventory().a(index)); + } + + public ItemStack[] getContents() { + ItemStack[] items = new ItemStack[getSize()]; + net.minecraft.server.ItemStack[] mcItems = getInventory().getContents(); + + for (int i = 0; i < mcItems.length; i++ ) { + items[i] = new CraftItemStack(mcItems[i]); + } + + return items; + } + + public void setItem(int index, ItemStack item) { + getInventory().a( index, new net.minecraft.server.ItemStack( item.getTypeID(), item.getAmount())); + } + + public boolean contains(int materialId) { + for (ItemStack item: getContents()) { + if (item.getTypeID() == materialId) { + return true; + } + } + return false; + } + + public boolean contains(Material material) { + return contains(material.getID()); + } + + public boolean contains(ItemStack item) { + for (ItemStack i: getContents()) { + if (item.equals(i)) { + return true; + } + } + return false; + } + + public HashMap all(int materialId) { + HashMap slots = new HashMap(); + + ItemStack[] inventory = getContents(); + for (int i = 0; i < inventory.length; i++) { + ItemStack item = inventory[i]; + if (item.getTypeID() == materialId) { + slots.put( i, item ); + } + } + return slots; + } + + public HashMap all(Material material) { + return all(material.getID()); + } + + public HashMap all(ItemStack item) { + HashMap slots = new HashMap(); + + ItemStack[] inventory = getContents(); + for (int i = 0; i < inventory.length; i++) { + if (item.equals(inventory[i])) { + slots.put( i, item ); + } + } + return slots; + } + + public int first(int materialId) { + ItemStack[] inventory = getContents(); + for (int i = 0; i < inventory.length; i++) { + if (inventory[i].getTypeID() == materialId) { + return i; + } + } + return -1; + } + + public int first(Material material) { + return first(material.getID()); + } + + public int first(ItemStack item) { + ItemStack[] inventory = getContents(); + for (int i = 0; i < inventory.length; i++) { + if (item.equals(inventory[i])) { + return i; + } + } + return -1; + } + + public int firstEmpty() { + return first(Material.Air); + } + + public int firstPartial(int materialId) { + ItemStack[] inventory = getContents(); + for (int i = 0; i < inventory.length; i++) { + if (inventory[i].getAmount() <= inventory[i].getMaxStackSize()) { + return i; + } + } + return -1; + } + + public int firstPartial(Material material) { + return firstPartial(material.getID()); + } + + public int firstPartial(ItemStack item) { + return firstPartial(item.getTypeID()); + } + + public HashMap addItem(ItemStack... items) { + HashMap leftover = new HashMap(); + + /* TODO: some optimization + * - Create a 'firstPartial' with a 'fromIndex' + * - Record the lastPartial per Material + * - Cache firstEmpty result + */ + + for (int i = 0; i < items.length; i++) { + ItemStack item = items[i]; + while (true) { + // Do we already have a stack of it? + int firstPartial = firstPartial( item.getTypeID() ); + + // Drat! no partial stack + if (firstPartial == -1) { + // Find a free spot! + int firstFree = firstEmpty(); + + if (firstFree == -1) { + // No space at all! + leftover.put(i, item); + } else { + // Just store it + setItem( firstFree, item ); + } + break; + } + + // So, apparently it might only partially fit, well lets do just that + ItemStack partialItem = getItem(firstPartial); + + int amount = item.getAmount(); + int partialAmount = partialItem.getAmount(); + int maxAmount = partialItem.getMaxStackSize(); + + // Check if it fully fits + if (amount + partialAmount <= maxAmount) { + partialItem.setAmount( amount + partialAmount ); + break; + } + + // It fits partially + partialItem.setAmount( maxAmount ); + item.setAmount( amount + partialAmount - maxAmount ); + } + } + return leftover; + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftInventoryPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftInventoryPlayer.java new file mode 100644 index 0000000000..3ee882fc60 --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftInventoryPlayer.java @@ -0,0 +1,67 @@ +package org.bukkit.craftbukkit; + +import java.util.ArrayList; + +import net.minecraft.server.InventoryPlayer; + +import org.bukkit.ItemStack; +import org.bukkit.PlayerInventory; + +public class CraftInventoryPlayer extends CraftInventory implements PlayerInventory { + public CraftInventoryPlayer(net.minecraft.server.InventoryPlayer inventory) { + super(inventory); + } + + public InventoryPlayer getInventory() { + return (InventoryPlayer) inventory; + } + + public ArrayList getArmorContents() { + ArrayList items = new ArrayList(); + for (net.minecraft.server.ItemStack item : getInventory().getArmorContents()) { + ItemStack i = null; + if (item != null) { + i = new CraftItemStack(item); + } + items.add(i); + } + + return items; + } + + public ItemStack getItemInHand() { + return new CraftItemStack( getInventory().e() ); + } + + public ItemStack getHelmet() { + return getItem( getSize() - 4 ); + } + + public ItemStack getChestplate() { + return getItem( getSize() - 3 ); + } + + public ItemStack getLeggings() { + return getItem( getSize() - 2 ); + } + + public ItemStack getBoots() { + return getItem( getSize() - 1 ); + } + + public void setHelmet(ItemStack helmet) { + setItem( getSize() - 4, helmet ); + } + + public void setChestplate(ItemStack chestplate) { + setItem( getSize() - 3, chestplate ); + } + + public void setLeggings(ItemStack leggings) { + setItem( getSize() - 2, leggings ); + } + + public void setBoots(ItemStack boots) { + setItem( getSize() - 1, boots ); + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftItemDrop.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftItemDrop.java new file mode 100644 index 0000000000..0def182530 --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftItemDrop.java @@ -0,0 +1,23 @@ +package org.bukkit.craftbukkit; + +import net.minecraft.server.EntityItem; +import org.bukkit.ItemDrop; +import org.bukkit.ItemStack; + +/** + * Represents an item drop. + * + * @author sk89q + */ +public class CraftItemDrop extends CraftEntity implements ItemDrop { + private EntityItem item; + + public CraftItemDrop(CraftServer server, EntityItem ent) { + super(server, ent); + this.item = ent; + } + + public ItemStack getItemStack() { + return new CraftItemStack(item.a); + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftItemStack.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftItemStack.java index ed80091064..d1571ac46f 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftItemStack.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftItemStack.java @@ -7,55 +7,83 @@ public class CraftItemStack extends ItemStack { protected net.minecraft.server.ItemStack item; public CraftItemStack(net.minecraft.server.ItemStack item) { - super(item.c, item.a); + super(item != null ? item.c : 0, item != null ? item.a : 0); this.item = item; } /* - * Unsure if we have to syn before each of these calls the values in 'item' + * Unsure if we have to sync before each of these calls the values in 'item' * are all public. */ @Override public Material getType() { - super.setTypeID(item.c); // sync, needed? + super.setTypeID(item != null ? item.c : 0); // sync, needed? return super.getType(); } @Override public int getTypeID() { - super.setTypeID(item.c); // sync, needed? - return item.c; + super.setTypeID(item != null ? item.c : 0); // sync, needed? + return item != null ? item.c : 0; } @Override public void setTypeID(int type) { - super.setTypeID(item.c); - item.c = type; + if (type == 0) { + super.setTypeID(0); + super.setAmount(0); + item = null; + } else { + if (item == null) { + item = new net.minecraft.server.ItemStack(type); + super.setAmount(1); + } else { + item.c = type; + super.setTypeID(item.c); + } + } } @Override public int getAmount() { - super.setAmount(item.a); // sync, needed? + super.setAmount(item != null ? item.a : 0); // sync, needed? return item.a; } @Override public void setAmount(int amount) { - super.setAmount(amount); - item.a = amount; + if (amount == 0) { + super.setTypeID(0); + super.setAmount(0); + item = null; + } else { + super.setAmount(amount); + item.a = amount; + } } @Override public void setDamage(final byte damage) { - super.setDamage(damage); - item.d = damage; + // Ignore damage if item is null + if (item != null) { + super.setDamage(damage); + item.d = damage; + } } @Override public byte getDamage() { - super.setDamage((byte) item.d); // sync, needed? - return (byte) item.d; + if (item != null) { + super.setDamage((byte) item.d); // sync, needed? + return (byte) item.d; + } else { + return 0; + } } + @Override + public int getMaxStackSize() { + return item.a().b(); + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftLivingEntity.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftLivingEntity.java index 369314deea..449ea62fe8 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftLivingEntity.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftLivingEntity.java @@ -2,13 +2,16 @@ package org.bukkit.craftbukkit; import net.minecraft.server.Entity; +import net.minecraft.server.EntityArrow; import net.minecraft.server.EntityEgg; import net.minecraft.server.EntityLiving; import net.minecraft.server.EntitySnowball; +import org.bukkit.Arrow; import org.bukkit.Egg; import org.bukkit.LivingEntity; import org.bukkit.Snowball; +import org.bukkit.Vehicle; public class CraftLivingEntity extends CraftEntity implements LivingEntity { private EntityLiving entity; @@ -58,4 +61,37 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { world.a(snowball); return new CraftSnowball(server, snowball); } + + public Arrow shootArrow() { + net.minecraft.server.World world = ((CraftWorld)getWorld()).getHandle(); + EntityArrow snowball = new EntityArrow(world, entity); + world.a(snowball); + return new CraftArrow(server, snowball); + } + + public boolean isInsideVehicle() { + return entity.k != null; + } + + public boolean leaveVehicle() { + if (entity.k == null) { + return false; + } + + entity.setPassengerOf(null); + return true; + } + + public Vehicle getVehicle() { + if (entity.k == null) { + return null; + } + + org.bukkit.Entity vehicle = ((CraftWorld)getWorld()).toCraftEntity(entity.k); + if (vehicle instanceof Vehicle) { + return (Vehicle)vehicle; + } + + return null; + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMappable.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMappable.java new file mode 100644 index 0000000000..8e411846bd --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMappable.java @@ -0,0 +1,16 @@ +package org.bukkit.craftbukkit; + +/** + * Indicates that an object has a method to get its CraftBukkit-equivalent + * CraftEntity object from its Minecraft net.minecraft.server.Entity object. + * + * @author sk89q + */ +public interface CraftMappable { + /** + * Gets the CraftEntity version. + * + * @return + */ + public CraftEntity getCraftEntity(); +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMinecart.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMinecart.java index 44082603ba..0d55ad8219 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMinecart.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftMinecart.java @@ -1,9 +1,7 @@ package org.bukkit.craftbukkit; import net.minecraft.server.EntityMinecart; -import org.bukkit.LivingEntity; import org.bukkit.Minecart; -import org.bukkit.Vector; /** * A minecart. @@ -38,25 +36,6 @@ public class CraftMinecart extends CraftVehicle implements Minecart { minecart = entity; } - public Vector getVelocity() { - return new Vector(minecart.s, minecart.t, minecart.u); - } - - public void setVelocity(Vector vel) { - minecart.s = vel.getX(); - minecart.t = vel.getY(); - minecart.u = vel.getZ(); - } - - public LivingEntity getPassenger() { - // @TODO: Implement - return null; - } - - public boolean isEmpty() { - return minecart.j == null; - } - public void setDamage(int damage) { minecart.a = damage; } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftPlayer.java index 195f437496..90c3d7cc0e 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftPlayer.java @@ -9,11 +9,12 @@ import org.bukkit.Location; import org.bukkit.Player; public class CraftPlayer extends CraftHumanEntity implements Player { - private EntityPlayerMP entity; + private String name; public CraftPlayer(CraftServer server, EntityPlayerMP entity) { super(server, entity); + this.name = getName(); this.entity = entity; } @@ -58,6 +59,14 @@ public class CraftPlayer extends CraftHumanEntity implements Player { entity.a.a(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch()); } + public String getDisplayName() { + return name; + } + + public void setDisplayName(final String name) { + this.name = name; + } + @Override public String toString() { return "CraftPlayer{" + "name=" + getName() + '}'; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 4d814ed16f..c3b9c7cdab 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -1,6 +1,7 @@ package org.bukkit.craftbukkit; import java.io.File; +import java.util.ArrayList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -26,7 +27,9 @@ public final class CraftServer implements Server { this.server = server; pluginManager.RegisterInterface(JavaPluginLoader.class); - + } + + public void loadPlugins() { File pluginFolder = (File)console.options.valueOf("plugins"); if (pluginFolder.exists()) { @@ -78,6 +81,27 @@ public final class CraftServer implements Server { public Player getPlayer(final EntityPlayerMP entity) { return entity.a.getPlayer(); } + + public List matchPlayer(String partialName) { + List matchedPlayers = new ArrayList(); + + for (Player iterPlayer : this.getOnlinePlayers()) { + String iterPlayerName = iterPlayer.getName(); + + if (partialName.equalsIgnoreCase(iterPlayerName)) { + // Exact match + matchedPlayers.clear(); + matchedPlayers.add(iterPlayer); + break; + } + if (iterPlayerName.toLowerCase().indexOf(partialName.toLowerCase()) != -1) { + // Partial match + matchedPlayers.add(iterPlayer); + } + } + + return matchedPlayers; + } public PluginManager getPluginManager() { return pluginManager; diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftSlot.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftSlot.java new file mode 100644 index 0000000000..32b12b7a0f --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftSlot.java @@ -0,0 +1,25 @@ +package org.bukkit.craftbukkit; + +import org.bukkit.Inventory; +import org.bukkit.ItemStack; +import net.minecraft.server.Slot; + +public class CraftSlot implements org.bukkit.Slot { + private final Slot slot; + + public CraftSlot(Slot slot) { + this.slot = slot; + } + + public Inventory getInventory() { + return new CraftInventory( slot.b ); + } + + public int getIndex() { + return slot.a; + } + + public ItemStack getItem() { + return new CraftItemStack( slot.c() ); + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftStorageMinecart.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftStorageMinecart.java index 7567529e31..3063482daa 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftStorageMinecart.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftStorageMinecart.java @@ -1,11 +1,8 @@ package org.bukkit.craftbukkit; -import java.util.ArrayList; -import java.util.List; - import net.minecraft.server.EntityMinecart; -import org.bukkit.ItemStack; +import org.bukkit.Inventory; import org.bukkit.StorageMinecart; /** @@ -14,32 +11,14 @@ import org.bukkit.StorageMinecart; * @author sk89q */ public class CraftStorageMinecart extends CraftMinecart implements StorageMinecart { + private CraftInventory inventory; + public CraftStorageMinecart(CraftServer server, EntityMinecart entity) { super(server, entity); + inventory = new CraftInventory( entity ); } - public int getSize() { - return minecart.c(); - } - - public String getName() { - return minecart.b(); - } - - public ItemStack getItem(int index) { - return new CraftItemStack(minecart.a(index)); - } - - public List getContents() { - ArrayList items = new ArrayList(); - for (net.minecraft.server.ItemStack item: minecart.getContents()) { - ItemStack i = null; - if (item != null) { - i = new CraftItemStack( item ); - } - items.add(i); - } - - return items; + public Inventory getInventory() { + return inventory; } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftVehicle.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftVehicle.java index a5c03868c4..ffc93da19b 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftVehicle.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftVehicle.java @@ -1,7 +1,7 @@ package org.bukkit.craftbukkit; -import net.minecraft.server.Entity; - +import org.bukkit.Entity; +import org.bukkit.Vector; import org.bukkit.Vehicle; /** @@ -10,7 +10,29 @@ import org.bukkit.Vehicle; * @author sk89q */ public abstract class CraftVehicle extends CraftEntity implements Vehicle { - public CraftVehicle(CraftServer server, Entity entity) { + public CraftVehicle(CraftServer server, net.minecraft.server.Entity entity) { super(server, entity); } + + public Entity getPassenger() { + return ((CraftWorld)getWorld()).toCraftEntity(getHandle().j); + } + + public boolean setPassenger(Entity passenger) { + ((CraftEntity)passenger).getHandle().setPassengerOf(getHandle()); + return true; + } + + public boolean isEmpty() { + return getHandle().j == null; + } + + public boolean eject() { + if (getHandle().j == null) { + return false; + } + + getHandle().j.setPassengerOf(null); + return true; + } } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 74c49a9ec1..35f2a3a833 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -6,13 +6,25 @@ import java.util.Map; import net.minecraft.server.EntityMinecart; import java.util.Random; + +import net.minecraft.server.EntityBoat; +import net.minecraft.server.EntityEgg; +import net.minecraft.server.EntityItem; +import net.minecraft.server.EntityLiving; +import net.minecraft.server.EntityPlayerMP; +import net.minecraft.server.EntitySnowball; +import net.minecraft.server.EntityArrow; +import net.minecraft.server.EntityPlayer; +import net.minecraft.server.TileEntity; import net.minecraft.server.WorldGenBigTree; import net.minecraft.server.WorldServer; -import net.minecraft.server.EntityArrow; import net.minecraft.server.WorldGenTrees; import org.bukkit.Arrow; import org.bukkit.Block; +import org.bukkit.Boat; import org.bukkit.Chunk; +import org.bukkit.ItemDrop; +import org.bukkit.ItemStack; import org.bukkit.Location; import org.bukkit.Minecart; import org.bukkit.PoweredMinecart; @@ -101,6 +113,28 @@ public class CraftWorld implements World { public WorldServer getHandle() { return world; } + + public ItemDrop dropItem(Location loc, ItemStack item) { + net.minecraft.server.ItemStack stack = + new net.minecraft.server.ItemStack( + item.getTypeID(), item.getAmount(), item.getDamage()); + EntityItem entity = new EntityItem(world, loc.getX(), loc.getY(), + loc.getZ(), stack); + entity.c = 10; + world.a(entity); + return new CraftItemDrop(world.getServer(), entity); + } + + public ItemDrop dropItemNaturally(Location loc, ItemStack item) { + double xs = world.l.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D; + double ys = world.l.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D; + double zs = world.l.nextFloat() * 0.7F + (1.0F - 0.7F) * 0.5D; + loc = loc.clone(); + loc.setX(loc.getX() + xs); + loc.setX(loc.getY() + ys); + loc.setX(loc.getZ() + zs); + return dropItem(loc, item); + } public Arrow spawnArrow(Location loc, Vector velocity, float speed, float spread) { @@ -138,6 +172,13 @@ public class CraftWorld implements World { return new CraftPoweredMinecart(world.getServer(), minecart); } + public Boat spawnBoat(Location loc) { + EntityBoat boat = + new EntityBoat(world, loc.getX(), loc.getY(), loc.getZ()); + world.a(boat); + return new CraftBoat(world.getServer(), boat); + } + public boolean generateTree(Location loc) { WorldGenTrees treeGen = new WorldGenTrees(); return treeGen.a(world, rand, @@ -149,6 +190,40 @@ public class CraftWorld implements World { return treeGen.a(world, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()); } + + public CraftEntity toCraftEntity(net.minecraft.server.Entity entity) { + if (entity instanceof CraftMappable) { + return ((CraftMappable)entity).getCraftEntity(); + } else if (entity instanceof EntityItem) { + return new CraftItemDrop(world.getServer(), (EntityItem)entity); + } else if (entity instanceof EntityArrow) { + return new CraftArrow(world.getServer(), (EntityArrow)entity); + } else if (entity instanceof EntityEgg) { + return new CraftEgg(world.getServer(), (EntityEgg)entity); + } else if (entity instanceof EntityPlayerMP) { + return new CraftPlayer(world.getServer(), (EntityPlayerMP)entity); + } else if (entity instanceof EntitySnowball) { + return new CraftSnowball(world.getServer(), (EntitySnowball)entity); + } else if (entity instanceof EntityPlayer) { + return new CraftHumanEntity(world.getServer(), (EntityPlayer)entity); + } else if (entity instanceof EntityLiving) { + return new CraftLivingEntity(world.getServer(), (EntityLiving)entity); + } else { + return null; + } + } + + public TileEntity getTileEntityAt(final int x, final int y, final int z) { + return world.l(x, y, z); + } + + public String getName() { + return world.w; + } + + public long getId() { + return world.u; + } @Override public String toString() { diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java new file mode 100644 index 0000000000..f2a0c2756d --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftBlockState.java @@ -0,0 +1,168 @@ + +package org.bukkit.craftbukkit.block; + +import org.bukkit.Block; +import org.bukkit.Chunk; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.BlockState; +import org.bukkit.craftbukkit.CraftChunk; +import org.bukkit.craftbukkit.CraftWorld; + +public class CraftBlockState implements BlockState { + private final CraftWorld world; + private final CraftChunk chunk; + private final int x; + private final int y; + private final int z; + protected int type; + protected byte data; + protected byte light; + + public CraftBlockState(final Block block) { + this.world = (CraftWorld)block.getWorld(); + this.x = block.getX(); + this.y = block.getY(); + this.z = block.getZ(); + this.type = block.getTypeID(); + this.data = block.getData(); + this.light = block.getLightLevel(); + this.chunk = (CraftChunk)block.getChunk(); + } + + /** + * Gets the world which contains this Block + * + * @return World containing this block + */ + public World getWorld() { + return world; + } + + /** + * Gets the x-coordinate of this block + * + * @return x-coordinate + */ + public int getX() { + return x; + } + + /** + * Gets the y-coordinate of this block + * + * @return y-coordinate + */ + public int getY() { + return y; + } + + /** + * Gets the z-coordinate of this block + * + * @return z-coordinate + */ + public int getZ() { + return z; + } + + /** + * Gets the chunk which contains this block + * + * @return Containing Chunk + */ + public Chunk getChunk() { + return chunk; + } + + /** + * Sets the metadata for this block + * + * @param data New block specific metadata + */ + public void setData(final byte data) { + this.data = data; + world.getHandle().c(x, y, z, data); + } + + /** + * Gets the metadata for this block + * + * @return block specific metadata + */ + public byte getData() { + return data; + } + + /** + * Sets the type of this block + * + * @param type Material to change this block to + */ + public void setType(final Material type) { + setTypeID(type.getID()); + } + + /** + * Sets the type-ID of this block + * + * @param type Type-ID to change this block to + */ + public void setTypeID(final int type) { + this.type = type; + world.getHandle().d(x, y, z, type); + } + + /** + * Gets the type of this block + * + * @return block type + */ + public Material getType() { + return Material.getMaterial(getTypeID()); + } + + /** + * Gets the type-ID of this block + * + * @return block type-ID + */ + public int getTypeID() { + return type; + } + + /** + * Gets the light level between 0-15 + * + * @return light level + */ + public byte getLightLevel() { + return light; + } + + public Block getBlock() { + return world.getBlockAt(x, y, z); + } + + public boolean update() { + return update(false); + } + + public boolean update(boolean force) { // TODO + Block block = getBlock(); + + synchronized (block) { + if (block.getType() != this.getType()) { + if (force) { + block.setTypeID(this.getTypeID()); + } else { + return false; + } + } + + block.setData(data); + } + + return true; + } +} diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java new file mode 100644 index 0000000000..a3a8649b93 --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/block/CraftSign.java @@ -0,0 +1,42 @@ + +package org.bukkit.craftbukkit.block; + +import net.minecraft.server.TileEntitySign; +import org.bukkit.Block; +import org.bukkit.block.Sign; +import org.bukkit.craftbukkit.CraftWorld; + +public class CraftSign extends CraftBlockState implements Sign { + private final CraftWorld world; + private final TileEntitySign sign; + + public CraftSign(final Block block) { + super(block); + + world = (CraftWorld)block.getWorld(); + sign = (TileEntitySign)world.getTileEntityAt(getX(), getY(), getZ()); + } + + public String[] getLines() { + return sign.e; + } + + public String getLine(int index) throws IndexOutOfBoundsException { + return sign.e[index]; + } + + public void setLine(int index, String line) throws IndexOutOfBoundsException { + sign.e[index] = line; + } + + @Override + public boolean update(boolean force) { + boolean result = super.update(force); + + if (result) { + sign.d(); + } + + return result; + } +}