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;
+ }
+}