From 6903f2024217f0959c015e76b23297af8e3b573f Mon Sep 17 00:00:00 2001
From: Dinnerbone <dinnerbone@dinnerbone.com>
Date: Thu, 26 May 2011 13:48:22 +0100
Subject: [PATCH] Implemented 1.6!

---
 pom.xml                                       |   2 +-
 .../net/minecraft/server/BlockButton.java     |  18 +-
 .../net/minecraft/server/BlockCactus.java     |   6 +-
 .../net/minecraft/server/BlockDispenser.java  |  90 +--
 .../java/net/minecraft/server/BlockDoor.java  |  19 +-
 .../java/net/minecraft/server/BlockFire.java  | 124 ++--
 .../net/minecraft/server/BlockFlowing.java    |  20 +-
 .../net/minecraft/server/BlockLeaves.java     |   4 +-
 .../java/net/minecraft/server/BlockLever.java |  28 +-
 .../net/minecraft/server/BlockPortal.java     | 141 -----
 .../minecraft/server/BlockPressurePlate.java  |  16 +-
 .../minecraft/server/BlockRedstoneTorch.java  |   8 +-
 .../minecraft/server/BlockRedstoneWire.java   |  14 +-
 .../net/minecraft/server/BlockSapling.java    |  16 +-
 .../java/net/minecraft/server/BlockSign.java  |   6 +-
 .../java/net/minecraft/server/BlockSoil.java  |   6 +-
 .../net/minecraft/server/BlockStationary.java |   6 +-
 src/main/java/net/minecraft/server/Chunk.java |  92 +--
 .../minecraft/server/ChunkProviderServer.java |  31 +-
 .../server/ConsoleCommandHandler.java         | 347 ++++++-----
 .../net/minecraft/server/ContainerPlayer.java |  34 ++
 .../minecraft/server/ContainerWorkbench.java  |  34 ++
 .../net/minecraft/server/CraftingManager.java |   6 +-
 .../java/net/minecraft/server/Entity.java     | 460 +++++++++------
 .../net/minecraft/server/EntityArrow.java     | 359 ++++++------
 .../java/net/minecraft/server/EntityBoat.java | 104 ++--
 .../net/minecraft/server/EntityCreature.java  |  24 +-
 .../net/minecraft/server/EntityCreeper.java   |  27 +-
 .../java/net/minecraft/server/EntityEgg.java  |   8 +-
 .../net/minecraft/server/EntityFireball.java  | 114 ++--
 .../java/net/minecraft/server/EntityFish.java |  10 +-
 .../net/minecraft/server/EntityHuman.java     |  53 +-
 .../java/net/minecraft/server/EntityItem.java |  84 +--
 .../net/minecraft/server/EntityLiving.java    | 289 +++++-----
 .../net/minecraft/server/EntityMinecart.java  |  86 ++-
 .../net/minecraft/server/EntityMonster.java   |  10 +-
 .../net/minecraft/server/EntityPainting.java  |   2 +-
 .../java/net/minecraft/server/EntityPig.java  |  28 +-
 .../net/minecraft/server/EntityPigZombie.java |   6 +-
 .../net/minecraft/server/EntityPlayer.java    | 148 +++--
 .../net/minecraft/server/EntitySkeleton.java  |   2 +-
 .../net/minecraft/server/EntitySnowball.java  |   8 +-
 .../net/minecraft/server/EntitySpider.java    |   2 +-
 .../net/minecraft/server/EntityTNTPrimed.java |  12 +-
 .../net/minecraft/server/EntityTracker.java   |  18 +-
 .../minecraft/server/EntityTrackerEntry.java  |  25 +-
 .../minecraft/server/EntityWeatherStorm.java  |   5 +-
 .../net/minecraft/server/EntityZombie.java    |   2 +-
 .../net/minecraft/server/InventoryPlayer.java |  58 +-
 .../java/net/minecraft/server/ItemBlock.java  |  21 +-
 .../java/net/minecraft/server/ItemBoat.java   |   6 +-
 .../java/net/minecraft/server/ItemDoor.java   |  15 +-
 .../java/net/minecraft/server/ItemHoe.java    |  19 +-
 .../minecraft/server/ItemInWorldManager.java  |  38 +-
 .../java/net/minecraft/server/ItemReed.java   |  16 +-
 .../java/net/minecraft/server/ItemStack.java  |  31 +-
 .../net/minecraft/server/MinecraftServer.java | 154 +++--
 .../net/minecraft/server/NetLoginHandler.java |  26 +-
 .../minecraft/server/NetServerHandler.java    | 155 ++---
 .../net/minecraft/server/NetworkManager.java  | 245 ++++----
 .../java/net/minecraft/server/Packet.java     |   4 +-
 .../net/minecraft/server/PlayerInstance.java  |  43 +-
 .../net/minecraft/server/PlayerManager.java   |  78 +--
 .../server/ServerConfigurationManager.java    | 233 +++++---
 src/main/java/net/minecraft/server/Slot.java  |   4 -
 .../net/minecraft/server/StatisticList.java   | 186 ------
 .../minecraft/server/ThreadLoginVerifier.java |   1 +
 .../minecraft/server/TileEntityDispenser.java |   4 +-
 .../server/TileEntityMobSpawner.java          |   2 +-
 src/main/java/net/minecraft/server/World.java | 538 +++++++++++-------
 .../net/minecraft/server/WorldGenBigTree.java |   8 +-
 .../net/minecraft/server/WorldManager.java    |  18 +-
 .../net/minecraft/server/WorldServer.java     |  29 +-
 .../org/bukkit/craftbukkit/CraftServer.java   |   9 +-
 .../craftbukkit/entity/CraftCreeper.java      |   6 +-
 .../craftbukkit/entity/CraftPlayer.java       |  64 +--
 76 files changed, 2699 insertions(+), 2266 deletions(-)
 delete mode 100644 src/main/java/net/minecraft/server/BlockPortal.java
 delete mode 100644 src/main/java/net/minecraft/server/StatisticList.java

diff --git a/pom.xml b/pom.xml
index ffaa4124ee..ba889c8549 100644
--- a/pom.xml
+++ b/pom.xml
@@ -39,7 +39,7 @@
     <dependency>
       <groupId>org.bukkit</groupId>
       <artifactId>minecraft-server</artifactId>
-      <version>1.5</version>
+      <version>1.6</version>
       <type>jar</type>
       <scope>compile</scope>
     </dependency>
diff --git a/src/main/java/net/minecraft/server/BlockButton.java b/src/main/java/net/minecraft/server/BlockButton.java
index 3a36bb9d1a..883e340a55 100644
--- a/src/main/java/net/minecraft/server/BlockButton.java
+++ b/src/main/java/net/minecraft/server/BlockButton.java
@@ -20,7 +20,7 @@ public class BlockButton extends Block {
         return null;
     }
 
-    public int b() {
+    public int c() {
         return 20;
     }
 
@@ -28,6 +28,14 @@ public class BlockButton extends Block {
         return false;
     }
 
+    public boolean b() {
+        return false;
+    }
+
+    public boolean canPlace(World world, int i, int j, int k, int l) {
+        return l == 2 && world.d(i, j, k + 1) ? true : (l == 3 && world.d(i, j, k - 1) ? true : (l == 4 && world.d(i + 1, j, k) ? true : l == 5 && world.d(i - 1, j, k)));
+    }
+
     public boolean canPlace(World world, int i, int j, int k) {
         return world.d(i - 1, j, k) ? true : (world.d(i + 1, j, k) ? true : (world.d(i, j, k - 1) ? true : world.d(i, j, k + 1)));
     }
@@ -78,7 +86,7 @@ public class BlockButton extends Block {
             }
 
             if (flag) {
-                this.a_(world, i, j, k, world.getData(i, j, k));
+                this.b_(world, i, j, k, world.getData(i, j, k));
                 world.setTypeId(i, j, k, 0);
             }
         }
@@ -86,7 +94,7 @@ public class BlockButton extends Block {
 
     private boolean h(World world, int i, int j, int k) {
         if (!this.canPlace(world, i, j, k)) {
-            this.a_(world, i, j, k, world.getData(i, j, k));
+            this.b_(world, i, j, k, world.getData(i, j, k));
             world.setTypeId(i, j, k, 0);
             return false;
         } else {
@@ -160,7 +168,7 @@ public class BlockButton extends Block {
                 world.applyPhysics(i, j - 1, k, this.id);
             }
 
-            world.c(i, j, k, this.id, this.b());
+            world.c(i, j, k, this.id, this.c());
             return true;
         }
     }
@@ -188,7 +196,7 @@ public class BlockButton extends Block {
         super.remove(world, i, j, k);
     }
 
-    public boolean b(IBlockAccess iblockaccess, int i, int j, int k, int l) {
+    public boolean a(IBlockAccess iblockaccess, int i, int j, int k, int l) {
         return (iblockaccess.getData(i, j, k) & 8) > 0;
     }
 
diff --git a/src/main/java/net/minecraft/server/BlockCactus.java b/src/main/java/net/minecraft/server/BlockCactus.java
index c187615e53..4475234769 100644
--- a/src/main/java/net/minecraft/server/BlockCactus.java
+++ b/src/main/java/net/minecraft/server/BlockCactus.java
@@ -47,6 +47,10 @@ public class BlockCactus extends Block {
         return i == 1 ? this.textureId - 1 : (i == 0 ? this.textureId + 1 : this.textureId);
     }
 
+    public boolean b() {
+        return false;
+    }
+
     public boolean a() {
         return false;
     }
@@ -57,7 +61,7 @@ public class BlockCactus extends Block {
 
     public void doPhysics(World world, int i, int j, int k, int l) {
         if (!this.f(world, i, j, k)) {
-            this.a_(world, i, j, k, world.getData(i, j, k));
+            this.b_(world, i, j, k, world.getData(i, j, k));
             world.setTypeId(i, j, k, 0);
         }
     }
diff --git a/src/main/java/net/minecraft/server/BlockDispenser.java b/src/main/java/net/minecraft/server/BlockDispenser.java
index 8d6b82e0eb..4b4bb85476 100644
--- a/src/main/java/net/minecraft/server/BlockDispenser.java
+++ b/src/main/java/net/minecraft/server/BlockDispenser.java
@@ -16,12 +16,14 @@ import org.bukkit.util.Vector;
 
 public class BlockDispenser extends BlockContainer {
 
+    private Random a = new Random();
+
     protected BlockDispenser(int i) {
         super(i, Material.STONE);
         this.textureId = 45;
     }
 
-    public int b() {
+    public int c() {
         return 4;
     }
 
@@ -80,17 +82,17 @@ public class BlockDispenser extends BlockContainer {
     // CraftBukkit - private -> public
     public void dispense(World world, int i, int j, int k, Random random) {
         int l = world.getData(i, j, k);
-        float f = 0.0F;
-        float f1 = 0.0F;
+        byte b0 = 0;
+        byte b1 = 0;
 
         if (l == 3) {
-            f1 = 1.0F;
+            b1 = 1;
         } else if (l == 2) {
-            f1 = -1.0F;
+            b1 = -1;
         } else if (l == 5) {
-            f = 1.0F;
+            b0 = 1;
         } else {
-            f = -1.0F;
+            b0 = -1;
         }
 
         TileEntityDispenser tileentitydispenser = (TileEntityDispenser) world.getTileEntity(i, j, k);
@@ -105,20 +107,20 @@ public class BlockDispenser extends BlockContainer {
         }
         // CraftBukkit end
 
-        double d0 = (double) i + (double) f * 0.5D + 0.5D;
+        double d0 = (double) i + (double) b0 * 0.6D + 0.5D;
         double d1 = (double) j + 0.5D;
-        double d2 = (double) k + (double) f1 * 0.5D + 0.5D;
+        double d2 = (double) k + (double) b1 * 0.6D + 0.5D;
 
         if (itemstack == null) {
-            world.makeSound((double) i, (double) j, (double) k, "random.click", 1.0F, 1.2F);
+            world.e(1001, i, j, k, 0);
         } else {
             double d3;
 
             // CraftBukkit start
             d3 = random.nextDouble() * 0.1D + 0.2D;
-            double motX = (double) f * d3;
+            double motX = (double) b0 * d3;
             double motY = 0.20000000298023224D;
-            double motZ = (double) f1 * d3;
+            double motZ = (double) b1 * d3;
             motX += random.nextGaussian() * 0.007499999832361937D * 6.0D;
             motY += random.nextGaussian() * 0.007499999832361937D * 6.0D;
             motZ += random.nextGaussian() * 0.007499999832361937D * 6.0D;
@@ -147,45 +149,36 @@ public class BlockDispenser extends BlockContainer {
             if (itemstack.id == Item.ARROW.id) {
                 EntityArrow entityarrow = new EntityArrow(world, d0, d1, d2);
 
-                entityarrow.a((double) f, 0.10000000149011612D, (double) f1, 1.1F, 6.0F);
+                entityarrow.a((double) b0, 0.10000000149011612D, (double) b1, 1.1F, 6.0F);
+                entityarrow.a = true;
                 world.addEntity(entityarrow);
-                world.makeSound((double) i, (double) j, (double) k, "random.bow", 1.0F, 1.2F);
+                world.e(1002, i, j, k, 0);
             } else if (itemstack.id == Item.EGG.id) {
                 EntityEgg entityegg = new EntityEgg(world, d0, d1, d2);
 
-                entityegg.a((double) f, 0.10000000149011612D, (double) f1, 1.1F, 6.0F);
+                entityegg.a((double) b0, 0.10000000149011612D, (double) b1, 1.1F, 6.0F);
                 world.addEntity(entityegg);
-                world.makeSound((double) i, (double) j, (double) k, "random.bow", 1.0F, 1.2F);
+                world.e(1002, i, j, k, 0);
             } else if (itemstack.id == Item.SNOW_BALL.id) {
                 EntitySnowball entitysnowball = new EntitySnowball(world, d0, d1, d2);
 
-                entitysnowball.a((double) f, 0.10000000149011612D, (double) f1, 1.1F, 6.0F);
+                entitysnowball.a((double) b0, 0.10000000149011612D, (double) b1, 1.1F, 6.0F);
                 world.addEntity(entitysnowball);
-                world.makeSound((double) i, (double) j, (double) k, "random.bow", 1.0F, 1.2F);
+                world.e(1002, i, j, k, 0);
             } else {
                 EntityItem entityitem = new EntityItem(world, d0, d1 - 0.3D, d2, itemstack);
 
-                d3 = random.nextDouble() * 0.1D + 0.2D;
                 // CraftBukkit start
+                d3 = random.nextDouble() * 0.1D + 0.2D;
                 entityitem.motX = motX;
                 entityitem.motY = motY;
                 entityitem.motZ = motZ;
                 // CraftBukkit end
                 world.addEntity(entityitem);
-                world.makeSound((double) i, (double) j, (double) k, "random.click", 1.0F, 1.0F);
+                world.e(1000, i, j, k, 0);
             }
 
-            for (int i1 = 0; i1 < 10; ++i1) {
-                d3 = random.nextDouble() * 0.2D + 0.01D;
-                double d4 = d0 + (double) f * 0.01D + (random.nextDouble() - 0.5D) * (double) f1 * 0.5D;
-                double d5 = d1 + (random.nextDouble() - 0.5D) * 0.5D;
-                double d6 = d2 + (double) f1 * 0.01D + (random.nextDouble() - 0.5D) * (double) f * 0.5D;
-                double d7 = (double) f * d3 + random.nextGaussian() * 0.01D;
-                double d8 = -0.03D + random.nextGaussian() * 0.01D;
-                double d9 = (double) f1 * d3 + random.nextGaussian() * 0.01D;
-
-                world.a("smoke", d4, d5, d6, d7, d8, d9);
-            }
+            world.e(2000, i, j, k, b0 + 1 + (b1 + 1) * 3);
         }
     }
 
@@ -194,7 +187,7 @@ public class BlockDispenser extends BlockContainer {
             boolean flag = world.isBlockIndirectlyPowered(i, j, k) || world.isBlockIndirectlyPowered(i, j + 1, k);
 
             if (flag) {
-                world.c(i, j, k, this.id, this.b());
+                world.c(i, j, k, this.id, this.c());
             }
         }
     }
@@ -228,4 +221,37 @@ public class BlockDispenser extends BlockContainer {
             world.setData(i, j, k, 4);
         }
     }
+
+    public void remove(World world, int i, int j, int k) {
+        TileEntityDispenser tileentitydispenser = (TileEntityDispenser) world.getTileEntity(i, j, k);
+
+        for (int l = 0; l < tileentitydispenser.getSize(); ++l) {
+            ItemStack itemstack = tileentitydispenser.getItem(l);
+
+            if (itemstack != null) {
+                float f = this.a.nextFloat() * 0.8F + 0.1F;
+                float f1 = this.a.nextFloat() * 0.8F + 0.1F;
+                float f2 = this.a.nextFloat() * 0.8F + 0.1F;
+
+                while (itemstack.count > 0) {
+                    int i1 = this.a.nextInt(21) + 10;
+
+                    if (i1 > itemstack.count) {
+                        i1 = itemstack.count;
+                    }
+
+                    itemstack.count -= i1;
+                    EntityItem entityitem = new EntityItem(world, (double) ((float) i + f), (double) ((float) j + f1), (double) ((float) k + f2), new ItemStack(itemstack.id, i1, itemstack.getData()));
+                    float f3 = 0.05F;
+
+                    entityitem.motX = (double) ((float) this.a.nextGaussian() * f3);
+                    entityitem.motY = (double) ((float) this.a.nextGaussian() * f3 + 0.2F);
+                    entityitem.motZ = (double) ((float) this.a.nextGaussian() * f3);
+                    world.addEntity(entityitem);
+                }
+            }
+        }
+
+        super.remove(world, i, j, k);
+    }
 }
diff --git a/src/main/java/net/minecraft/server/BlockDoor.java b/src/main/java/net/minecraft/server/BlockDoor.java
index f39cbb8059..7f81129036 100644
--- a/src/main/java/net/minecraft/server/BlockDoor.java
+++ b/src/main/java/net/minecraft/server/BlockDoor.java
@@ -50,6 +50,10 @@ public class BlockDoor extends Block {
         return false;
     }
 
+    public boolean b() {
+        return false;
+    }
+
     public AxisAlignedBB d(World world, int i, int j, int k) {
         this.a(world, i, j, k);
         return super.d(world, i, j, k);
@@ -103,12 +107,7 @@ public class BlockDoor extends Block {
 
                 world.setData(i, j, k, l ^ 4);
                 world.b(i, j - 1, k, i, j, k);
-                if (Math.random() < 0.5D) {
-                    world.makeSound((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D, "random.door_open", 1.0F, world.random.nextFloat() * 0.1F + 0.9F);
-                } else {
-                    world.makeSound((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D, "random.door_close", 1.0F, world.random.nextFloat() * 0.1F + 0.9F);
-                }
-
+                world.a(entityhuman, 1003, i, j, k, 0);
                 return true;
             }
         }
@@ -131,11 +130,7 @@ public class BlockDoor extends Block {
 
                 world.setData(i, j, k, l ^ 4);
                 world.b(i, j - 1, k, i, j, k);
-                if (Math.random() < 0.5D) {
-                    world.makeSound((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D, "random.door_open", 1.0F, world.random.nextFloat() * 0.1F + 0.9F);
-                } else {
-                    world.makeSound((double) i + 0.5D, (double) j + 0.5D, (double) k + 0.5D, "random.door_close", 1.0F, world.random.nextFloat() * 0.1F + 0.9F);
-                }
+                world.a((EntityHuman) null, 1003, i, j, k, 0);
             }
         }
     }
@@ -169,7 +164,7 @@ public class BlockDoor extends Block {
 
             if (flag) {
                 if (!world.isStatic) {
-                    this.a_(world, i, j, k, i1);
+                    this.b_(world, i, j, k, i1);
                 }
             } else if (l > 0 && Block.byId[l].isPowerSource()) {
                 boolean flag1 = world.isBlockIndirectlyPowered(i, j, k) || world.isBlockIndirectlyPowered(i, j + 1, k);
diff --git a/src/main/java/net/minecraft/server/BlockFire.java b/src/main/java/net/minecraft/server/BlockFire.java
index d1fef90795..8714c45a8d 100644
--- a/src/main/java/net/minecraft/server/BlockFire.java
+++ b/src/main/java/net/minecraft/server/BlockFire.java
@@ -18,13 +18,19 @@ public class BlockFire extends Block {
 
     protected BlockFire(int i, int j) {
         super(i, j, Material.FIRE);
+        this.a(true);
+    }
+
+    public void f() {
         this.a(Block.WOOD.id, 5, 20);
+        this.a(Block.FENCE.id, 5, 20);
+        this.a(Block.WOOD_STAIRS.id, 5, 20);
         this.a(Block.LOG.id, 5, 5);
         this.a(Block.LEAVES.id, 30, 60);
         this.a(Block.BOOKSHELF.id, 30, 20);
         this.a(Block.TNT.id, 15, 100);
+        this.a(Block.LONG_GRASS.id, 60, 100);
         this.a(Block.WOOL.id, 30, 60);
-        this.a(true);
     }
 
     private void a(int i, int j, int k) {
@@ -40,27 +46,35 @@ public class BlockFire extends Block {
         return false;
     }
 
+    public boolean b() {
+        return false;
+    }
+
     public int a(Random random) {
         return 0;
     }
 
-    public int b() {
-        return 10;
+    public int c() {
+        return 40;
     }
 
     public void a(World world, int i, int j, int k, Random random) {
         boolean flag = world.getTypeId(i, j - 1, k) == Block.NETHERRACK.id;
 
-        if (!flag && world.v() && (world.q(i, j, k) || world.q(i - 1, j, k) || world.q(i + 1, j, k) || world.q(i, j, k - 1) || world.q(i, j, k + 1))) {
+        if (!this.canPlace(world, i, j, k)) {
+            world.setTypeId(i, j, k, 0);
+        }
+
+        if (!flag && world.v() && (world.s(i, j, k) || world.s(i - 1, j, k) || world.s(i + 1, j, k) || world.s(i, j, k - 1) || world.s(i, j, k + 1))) {
             world.setTypeId(i, j, k, 0);
         } else {
             int l = world.getData(i, j, k);
 
             if (l < 15) {
-                world.setData(i, j, k, l + 1);
-                world.c(i, j, k, this.id, this.b());
+                world.setRawData(i, j, k, l + random.nextInt(3) / 2);
             }
 
+            world.c(i, j, k, this.id, this.c());
             if (!flag && !this.g(world, i, j, k)) {
                 if (!world.d(i, j - 1, k) || l > 3) {
                     world.setTypeId(i, j, k, 0);
@@ -68,35 +82,42 @@ public class BlockFire extends Block {
             } else if (!flag && !this.b(world, i, j - 1, k) && l == 15 && random.nextInt(4) == 0) {
                 world.setTypeId(i, j, k, 0);
             } else {
-                if (l % 2 == 0 && l > 2) {
-                    this.a(world, i + 1, j, k, 300, random);
-                    this.a(world, i - 1, j, k, 300, random);
-                    this.a(world, i, j - 1, k, 250, random);
-                    this.a(world, i, j + 1, k, 250, random);
-                    this.a(world, i, j, k - 1, 300, random);
-                    this.a(world, i, j, k + 1, 300, random);
+                this.a(world, i + 1, j, k, 300, random, l);
+                this.a(world, i - 1, j, k, 300, random, l);
+                this.a(world, i, j - 1, k, 250, random, l);
+                this.a(world, i, j + 1, k, 250, random, l);
+                this.a(world, i, j, k - 1, 300, random, l);
+                this.a(world, i, j, k + 1, 300, random, l);
 
-                    // CraftBukkit start - Call to stop spread of fire.
-                    Server server = ((WorldServer) world).getServer();
-                    CraftWorld cworld = ((WorldServer) world).getWorld();
+                // CraftBukkit start - Call to stop spread of fire.
+                Server server = ((WorldServer) world).getServer();
+                CraftWorld cworld = ((WorldServer) world).getWorld();
 
-                    IgniteCause igniteCause = BlockIgniteEvent.IgniteCause.SPREAD;
-                    Player thePlayer = null;
-                    // CraftBukkit
+                IgniteCause igniteCause = BlockIgniteEvent.IgniteCause.SPREAD;
+                Player thePlayer = null;
+                // CraftBukkit
 
-                    for (int i1 = i - 1; i1 <= i + 1; ++i1) {
-                        for (int j1 = k - 1; j1 <= k + 1; ++j1) {
-                            for (int k1 = j - 1; k1 <= j + 4; ++k1) {
-                                if (i1 != i || k1 != j || j1 != k) {
-                                    int l1 = 100;
+                for (int i1 = i - 1; i1 <= i + 1; ++i1) {
+                    for (int j1 = k - 1; j1 <= k + 1; ++j1) {
+                        for (int k1 = j - 1; k1 <= j + 4; ++k1) {
+                            if (i1 != i || k1 != j || j1 != k) {
+                                int l1 = 100;
 
-                                    if (k1 > j + 1) {
-                                        l1 += (k1 - (j + 1)) * 100;
-                                    }
+                                if (k1 > j + 1) {
+                                    l1 += (k1 - (j + 1)) * 100;
+                                }
 
-                                    int i2 = this.h(world, i1, k1, j1);
+                                int i2 = this.h(world, i1, k1, j1);
 
-                                    if (i2 > 0 && random.nextInt(l1) <= i2 && (!world.v() || !world.q(i1, k1, j1)) && !world.q(i1 - 1, k1, k) && !world.q(i1 + 1, k1, j1) && !world.q(i1, k1, j1 - 1) && !world.q(i1, k1, j1 + 1)) {
+                                if (i2 > 0) {
+                                    int j2 = (i2 + 40) / (l + 30);
+
+                                    if (j2 > 0 && random.nextInt(l1) <= j2 && (!world.v() || !world.s(i1, k1, j1)) && !world.s(i1 - 1, k1, k) && !world.s(i1 + 1, k1, j1) && !world.s(i1, k1, j1 - 1) && !world.s(i1, k1, j1 + 1)) {
+                                        int k2 = l + random.nextInt(5) / 4;
+
+                                        if (k2 > 15) {
+                                            k2 = 15;
+                                        }
                                         // CraftBukkit start - Call to stop spread of fire.
                                         org.bukkit.block.Block theBlock = cworld.getBlockAt(i1, k1, j1);
 
@@ -106,33 +127,24 @@ public class BlockFire extends Block {
                                             if (event.isCancelled()) {
                                                 continue;
                                             }
+
+                                            world.setTypeIdAndData(i1, k1, j1, this.id, k2);
                                         }
                                         // CraftBukkit end
-
-                                        world.setTypeId(i1, k1, j1, this.id);
                                     }
                                 }
                             }
                         }
                     }
                 }
-
-                if (l == 15) {
-                    this.a(world, i + 1, j, k, 1, random);
-                    this.a(world, i - 1, j, k, 1, random);
-                    this.a(world, i, j - 1, k, 1, random);
-                    this.a(world, i, j + 1, k, 1, random);
-                    this.a(world, i, j, k - 1, 1, random);
-                    this.a(world, i, j, k + 1, 1, random);
-                }
             }
         }
     }
 
-    private void a(World world, int i, int j, int k, int l, Random random) {
-        int i1 = this.b[world.getTypeId(i, j, k)];
+    private void a(World world, int i, int j, int k, int l, Random random, int i1) {
+        int j1 = this.b[world.getTypeId(i, j, k)];
 
-        if (random.nextInt(l) < i1) {
+        if (random.nextInt(l) < j1) {
             boolean flag = world.getTypeId(i, j, k) == Block.TNT.id;
             // CraftBukkit start
             Server server = ((WorldServer) world).getServer();
@@ -145,8 +157,14 @@ public class BlockFire extends Block {
             }
             // CraftBukkit end
 
-            if (random.nextInt(2) == 0 && !world.q(i, j, k)) {
-                world.setTypeId(i, j, k, this.id);
+            if (random.nextInt(i1 + 10) < 5 && !world.s(i, j, k)) {
+                int k1 = i1 + random.nextInt(5) / 4;
+
+                if (k1 > 15) {
+                    k1 = 15;
+                }
+
+                world.setTypeIdAndData(i, j, k, this.id, k1);
             } else {
                 world.setTypeId(i, j, k, 0);
             }
@@ -167,13 +185,13 @@ public class BlockFire extends Block {
         if (!world.isEmpty(i, j, k)) {
             return 0;
         } else {
-            int l = this.f(world, i + 1, j, k, b0);
+            int l = this.g(world, i + 1, j, k, b0);
 
-            l = this.f(world, i - 1, j, k, l);
-            l = this.f(world, i, j - 1, k, l);
-            l = this.f(world, i, j + 1, k, l);
-            l = this.f(world, i, j, k - 1, l);
-            l = this.f(world, i, j, k + 1, l);
+            l = this.g(world, i - 1, j, k, l);
+            l = this.g(world, i, j - 1, k, l);
+            l = this.g(world, i, j + 1, k, l);
+            l = this.g(world, i, j, k - 1, l);
+            l = this.g(world, i, j, k + 1, l);
             return l;
         }
     }
@@ -186,7 +204,7 @@ public class BlockFire extends Block {
         return this.a[iblockaccess.getTypeId(i, j, k)] > 0;
     }
 
-    public int f(World world, int i, int j, int k, int l) {
+    public int g(World world, int i, int j, int k, int l) {
         int i1 = this.a[world.getTypeId(i, j, k)];
 
         return i1 > l ? i1 : l;
@@ -207,7 +225,7 @@ public class BlockFire extends Block {
             if (!world.d(i, j - 1, k) && !this.g(world, i, j, k)) {
                 world.setTypeId(i, j, k, 0);
             } else {
-                world.c(i, j, k, this.id, this.b());
+                world.c(i, j, k, this.id, this.c());
             }
         }
     }
diff --git a/src/main/java/net/minecraft/server/BlockFlowing.java b/src/main/java/net/minecraft/server/BlockFlowing.java
index 74f669d83c..9cadaa687d 100644
--- a/src/main/java/net/minecraft/server/BlockFlowing.java
+++ b/src/main/java/net/minecraft/server/BlockFlowing.java
@@ -49,11 +49,11 @@ public class BlockFlowing extends BlockFluids {
             byte b1 = -100;
 
             this.a = 0;
-            int j1 = this.e(world, i - 1, j, k, b1);
+            int j1 = this.f(world, i - 1, j, k, b1);
 
-            j1 = this.e(world, i + 1, j, k, j1);
-            j1 = this.e(world, i, j, k - 1, j1);
-            j1 = this.e(world, i, j, k + 1, j1);
+            j1 = this.f(world, i + 1, j, k, j1);
+            j1 = this.f(world, i, j, k - 1, j1);
+            j1 = this.f(world, i, j, k + 1, j1);
             i1 = j1 + b0;
             if (i1 >= 8 || j1 < 0) {
                 i1 = -1;
@@ -70,7 +70,7 @@ public class BlockFlowing extends BlockFluids {
             }
 
             if (this.a >= 2 && this.material == Material.WATER) {
-                if (world.d(i, j - 1, k)) {
+                if (world.getMaterial(i, j - 1, k).isBuildable()) {
                     i1 = 0;
                 } else if (world.getMaterial(i, j - 1, k) == this.material && world.getData(i, j, k) == 0) {
                     i1 = 0;
@@ -88,7 +88,7 @@ public class BlockFlowing extends BlockFluids {
                     world.setTypeId(i, j, k, 0);
                 } else {
                     world.setData(i, j, k, i1);
-                    world.c(i, j, k, this.id, this.b());
+                    world.c(i, j, k, this.id, this.c());
                     world.applyPhysics(i, j, k, this.id);
                 }
             } else if (flag) {
@@ -154,7 +154,7 @@ public class BlockFlowing extends BlockFluids {
                 if (this.material == Material.LAVA) {
                     this.h(world, i, j, k);
                 } else {
-                    Block.byId[i1].a_(world, i, j, k, world.getData(i, j, k));
+                    Block.byId[i1].b_(world, i, j, k, world.getData(i, j, k));
                 }
             }
 
@@ -263,14 +263,14 @@ public class BlockFlowing extends BlockFluids {
             } else {
                 Material material = Block.byId[l].material;
 
-                return material.isBuildable();
+                return material.isSolid();
             }
         } else {
             return true;
         }
     }
 
-    protected int e(World world, int i, int j, int k, int l) {
+    protected int f(World world, int i, int j, int k, int l) {
         int i1 = this.g(world, i, j, k);
 
         if (i1 < 0) {
@@ -297,7 +297,7 @@ public class BlockFlowing extends BlockFluids {
     public void e(World world, int i, int j, int k) {
         super.e(world, i, j, k);
         if (world.getTypeId(i, j, k) == this.id) {
-            world.c(i, j, k, this.id, this.b());
+            world.c(i, j, k, this.id, this.c());
         }
     }
 }
diff --git a/src/main/java/net/minecraft/server/BlockLeaves.java b/src/main/java/net/minecraft/server/BlockLeaves.java
index 3c5a063bcd..037881ef4b 100644
--- a/src/main/java/net/minecraft/server/BlockLeaves.java
+++ b/src/main/java/net/minecraft/server/BlockLeaves.java
@@ -114,7 +114,7 @@ public class BlockLeaves extends BlockLeavesBase {
 
                 l1 = this.a[k1 * j1 + k1 * b1 + k1];
                 if (l1 >= 0) {
-                    world.setData(i, j, k, l & -9);
+                    world.setRawData(i, j, k, l & -9);
                 } else {
                     this.g(world, i, j, k);
                 }
@@ -132,7 +132,7 @@ public class BlockLeaves extends BlockLeavesBase {
         if (event.isCancelled()) return;
         // CraftBukkit end
 
-        this.a_(world, i, j, k, world.getData(i, j, k));
+        this.b_(world, i, j, k, world.getData(i, j, k));
         world.setTypeId(i, j, k, 0);
     }
 
diff --git a/src/main/java/net/minecraft/server/BlockLever.java b/src/main/java/net/minecraft/server/BlockLever.java
index aee41afa01..ba408119bd 100644
--- a/src/main/java/net/minecraft/server/BlockLever.java
+++ b/src/main/java/net/minecraft/server/BlockLever.java
@@ -21,6 +21,14 @@ public class BlockLever extends Block {
         return false;
     }
 
+    public boolean b() {
+        return false;
+    }
+
+    public boolean canPlace(World world, int i, int j, int k, int l) {
+        return l == 1 && world.d(i, j - 1, k) ? true : (l == 2 && world.d(i, j, k + 1) ? true : (l == 3 && world.d(i, j, k - 1) ? true : (l == 4 && world.d(i + 1, j, k) ? true : l == 5 && world.d(i - 1, j, k))));
+    }
+
     public boolean canPlace(World world, int i, int j, int k) {
         return world.d(i - 1, j, k) ? true : (world.d(i + 1, j, k) ? true : (world.d(i, j, k - 1) ? true : (world.d(i, j, k + 1) ? true : world.d(i, j - 1, k))));
     }
@@ -30,6 +38,7 @@ public class BlockLever extends Block {
         int j1 = i1 & 8;
 
         i1 &= 7;
+        i1 = -1;
         if (l == 1 && world.d(i, j - 1, k)) {
             i1 = 5 + world.random.nextInt(2);
         }
@@ -50,7 +59,12 @@ public class BlockLever extends Block {
             i1 = 1;
         }
 
-        world.setData(i, j, k, i1 + j1);
+        if (i1 == -1) {
+            this.b_(world, i, j, k, world.getData(i, j, k));
+            world.setTypeId(i, j, k, 0);
+        } else {
+            world.setData(i, j, k, i1 + j1);
+        }
     }
 
     public void doPhysics(World world, int i, int j, int k, int l) {
@@ -78,8 +92,12 @@ public class BlockLever extends Block {
                 flag = true;
             }
 
+            if (!world.d(i, j - 1, k) && i1 == 6) {
+                flag = true;
+            }
+
             if (flag) {
-                this.a_(world, i, j, k, world.getData(i, j, k));
+                this.b_(world, i, j, k, world.getData(i, j, k));
                 world.setTypeId(i, j, k, 0);
             }
         }
@@ -87,7 +105,7 @@ public class BlockLever extends Block {
 
     private boolean g(World world, int i, int j, int k) {
         if (!this.canPlace(world, i, j, k)) {
-            this.a_(world, i, j, k, world.getData(i, j, k));
+            this.b_(world, i, j, k, world.getData(i, j, k));
             world.setTypeId(i, j, k, 0);
             return false;
         } else {
@@ -183,7 +201,7 @@ public class BlockLever extends Block {
         super.remove(world, i, j, k);
     }
 
-    public boolean b(IBlockAccess iblockaccess, int i, int j, int k, int l) {
+    public boolean a(IBlockAccess iblockaccess, int i, int j, int k, int l) {
         return (iblockaccess.getData(i, j, k) & 8) > 0;
     }
 
@@ -195,7 +213,7 @@ public class BlockLever extends Block {
         } else {
             int j1 = i1 & 7;
 
-            return j1 == 5 && l == 1 ? true : (j1 == 4 && l == 2 ? true : (j1 == 3 && l == 3 ? true : (j1 == 2 && l == 4 ? true : j1 == 1 && l == 5)));
+            return j1 == 6 && l == 1 ? true : (j1 == 5 && l == 1 ? true : (j1 == 4 && l == 2 ? true : (j1 == 3 && l == 3 ? true : (j1 == 2 && l == 4 ? true : j1 == 1 && l == 5))));
         }
     }
 
diff --git a/src/main/java/net/minecraft/server/BlockPortal.java b/src/main/java/net/minecraft/server/BlockPortal.java
deleted file mode 100644
index 90bdb8e7fa..0000000000
--- a/src/main/java/net/minecraft/server/BlockPortal.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package net.minecraft.server;
-
-import java.util.Random;
-
-public class BlockPortal extends BlockBreakable {
-
-    public BlockPortal(int i, int j) {
-        super(i, j, Material.PORTAL, false);
-    }
-
-    public AxisAlignedBB d(World world, int i, int j, int k) {
-        return null;
-    }
-
-    public void a(IBlockAccess iblockaccess, int i, int j, int k) {
-        float f;
-        float f1;
-
-        if (iblockaccess.getTypeId(i - 1, j, k) != this.id && iblockaccess.getTypeId(i + 1, j, k) != this.id) {
-            f = 0.125F;
-            f1 = 0.5F;
-            this.a(0.5F - f, 0.0F, 0.5F - f1, 0.5F + f, 1.0F, 0.5F + f1);
-        } else {
-            f = 0.5F;
-            f1 = 0.125F;
-            this.a(0.5F - f, 0.0F, 0.5F - f1, 0.5F + f, 1.0F, 0.5F + f1);
-        }
-    }
-
-    public boolean a() {
-        return false;
-    }
-
-    public boolean a_(World world, int i, int j, int k) {
-        byte b0 = 0;
-        byte b1 = 0;
-
-        if (world.getTypeId(i - 1, j, k) == Block.OBSIDIAN.id || world.getTypeId(i + 1, j, k) == Block.OBSIDIAN.id) {
-            b0 = 1;
-        }
-
-        if (world.getTypeId(i, j, k - 1) == Block.OBSIDIAN.id || world.getTypeId(i, j, k + 1) == Block.OBSIDIAN.id) {
-            b1 = 1;
-        }
-
-        //System.out.println(b0 + ", " + b1); // CraftBukkit
-        if (b0 == b1) {
-            return false;
-        } else {
-            if (world.getTypeId(i - b0, j, k - b1) == 0) {
-                i -= b0;
-                k -= b1;
-            }
-
-            int l;
-            int i1;
-
-            for (l = -1; l <= 2; ++l) {
-                for (i1 = -1; i1 <= 3; ++i1) {
-                    boolean flag = l == -1 || l == 2 || i1 == -1 || i1 == 3;
-
-                    if (l != -1 && l != 2 || i1 != -1 && i1 != 3) {
-                        int j1 = world.getTypeId(i + b0 * l, j + i1, k + b1 * l);
-
-                        if (flag) {
-                            if (j1 != Block.OBSIDIAN.id) {
-                                return false;
-                            }
-                        } else if (j1 != 0 && j1 != Block.FIRE.id) {
-                            return false;
-                        }
-                    }
-                }
-            }
-
-            world.j = true;
-
-            for (l = 0; l < 2; ++l) {
-                for (i1 = 0; i1 < 3; ++i1) {
-                    world.setTypeId(i + b0 * l, j + i1, k + b1 * l, Block.PORTAL.id);
-                }
-            }
-
-            world.j = false;
-            return true;
-        }
-    }
-
-    public void doPhysics(World world, int i, int j, int k, int l) {
-        byte b0 = 0;
-        byte b1 = 1;
-
-        if (world.getTypeId(i - 1, j, k) == this.id || world.getTypeId(i + 1, j, k) == this.id) {
-            b0 = 1;
-            b1 = 0;
-        }
-
-        int i1;
-
-        for (i1 = j; world.getTypeId(i, i1 - 1, k) == this.id; --i1) {
-            ;
-        }
-
-        if (world.getTypeId(i, i1 - 1, k) != Block.OBSIDIAN.id) {
-            world.setTypeId(i, j, k, 0);
-        } else {
-            int j1;
-
-            for (j1 = 1; j1 < 4 && world.getTypeId(i, i1 + j1, k) == this.id; ++j1) {
-                ;
-            }
-
-            if (j1 == 3 && world.getTypeId(i, i1 + j1, k) == Block.OBSIDIAN.id) {
-                boolean flag = world.getTypeId(i - 1, j, k) == this.id || world.getTypeId(i + 1, j, k) == this.id;
-                boolean flag1 = world.getTypeId(i, j, k - 1) == this.id || world.getTypeId(i, j, k + 1) == this.id;
-
-                if (flag && flag1) {
-                    world.setTypeId(i, j, k, 0);
-                } else if ((world.getTypeId(i + b0, j, k + b1) != Block.OBSIDIAN.id || world.getTypeId(i - b0, j, k - b1) != this.id) && (world.getTypeId(i - b0, j, k - b1) != Block.OBSIDIAN.id || world.getTypeId(i + b0, j, k + b1) != this.id)) {
-                    world.setTypeId(i, j, k, 0);
-                }
-            } else {
-                world.setTypeId(i, j, k, 0);
-            }
-        }
-    }
-
-    public boolean a(IBlockAccess iblockaccess, int i, int j, int k, int l) {
-        return true;
-    }
-
-    public int a(Random random) {
-        return 0;
-    }
-
-    public void a(World world, int i, int j, int k, Entity entity) {
-        if (!world.isStatic) {
-            entity.ad();
-        }
-    }
-}
diff --git a/src/main/java/net/minecraft/server/BlockPressurePlate.java b/src/main/java/net/minecraft/server/BlockPressurePlate.java
index 1a158d2d4d..2afbb30986 100644
--- a/src/main/java/net/minecraft/server/BlockPressurePlate.java
+++ b/src/main/java/net/minecraft/server/BlockPressurePlate.java
@@ -20,8 +20,8 @@ public class BlockPressurePlate extends Block {
 
     private EnumMobType a;
 
-    protected BlockPressurePlate(int i, int j, EnumMobType enummobtype) {
-        super(i, j, Material.STONE);
+    protected BlockPressurePlate(int i, int j, EnumMobType enummobtype, Material material) {
+        super(i, j, material);
         this.a = enummobtype;
         this.a(true);
         float f = 0.0625F;
@@ -29,7 +29,7 @@ public class BlockPressurePlate extends Block {
         this.a(f, 0.0F, f, 1.0F - f, 0.03125F, 1.0F - f);
     }
 
-    public int b() {
+    public int c() {
         return 20;
     }
 
@@ -41,6 +41,10 @@ public class BlockPressurePlate extends Block {
         return false;
     }
 
+    public boolean b() {
+        return false;
+    }
+
     public boolean canPlace(World world, int i, int j, int k) {
         return world.d(i, j - 1, k);
     }
@@ -55,7 +59,7 @@ public class BlockPressurePlate extends Block {
         }
 
         if (flag) {
-            this.a_(world, i, j, k, world.getData(i, j, k));
+            this.b_(world, i, j, k, world.getData(i, j, k));
             world.setTypeId(i, j, k, 0);
         }
     }
@@ -147,7 +151,7 @@ public class BlockPressurePlate extends Block {
         }
 
         if (flag1) {
-            world.c(i, j, k, this.id, this.b());
+            world.c(i, j, k, this.id, this.c());
         }
     }
 
@@ -173,7 +177,7 @@ public class BlockPressurePlate extends Block {
         }
     }
 
-    public boolean b(IBlockAccess iblockaccess, int i, int j, int k, int l) {
+    public boolean a(IBlockAccess iblockaccess, int i, int j, int k, int l) {
         return iblockaccess.getData(i, j, k) > 0;
     }
 
diff --git a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
index 6cea952839..5608983c6a 100644
--- a/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
+++ b/src/main/java/net/minecraft/server/BlockRedstoneTorch.java
@@ -46,7 +46,7 @@ public class BlockRedstoneTorch extends BlockTorch {
         this.a(true);
     }
 
-    public int b() {
+    public int c() {
         return 2;
     }
 
@@ -76,7 +76,7 @@ public class BlockRedstoneTorch extends BlockTorch {
         }
     }
 
-    public boolean b(IBlockAccess iblockaccess, int i, int j, int k, int l) {
+    public boolean a(IBlockAccess iblockaccess, int i, int j, int k, int l) {
         if (!this.isOn) {
             return false;
         } else {
@@ -148,11 +148,11 @@ public class BlockRedstoneTorch extends BlockTorch {
 
     public void doPhysics(World world, int i, int j, int k, int l) {
         super.doPhysics(world, i, j, k, l);
-        world.c(i, j, k, this.id, this.b());
+        world.c(i, j, k, this.id, this.c());
     }
 
     public boolean c(World world, int i, int j, int k, int l) {
-        return l == 0 ? this.b(world, i, j, k, l) : false;
+        return l == 0 ? this.a(world, i, j, k, l) : false;
     }
 
     public int a(int i, Random random) {
diff --git a/src/main/java/net/minecraft/server/BlockRedstoneWire.java b/src/main/java/net/minecraft/server/BlockRedstoneWire.java
index 4bd41b637d..82e74257ae 100644
--- a/src/main/java/net/minecraft/server/BlockRedstoneWire.java
+++ b/src/main/java/net/minecraft/server/BlockRedstoneWire.java
@@ -32,6 +32,10 @@ public class BlockRedstoneWire extends Block {
         return false;
     }
 
+    public boolean b() {
+        return false;
+    }
+
     public boolean canPlace(World world, int i, int j, int k) {
         return world.d(i, j - 1, k);
     }
@@ -113,10 +117,10 @@ public class BlockRedstoneWire extends Block {
         // CraftBukkit end
 
         if (k1 != l1) {
-            world.j = true;
+            world.o = true;
             world.setData(i, j, k, l1);
             world.b(i, j, k, i, j, k);
-            world.j = false;
+            world.o = false;
 
             for (i2 = 0; i2 < 4; ++i2) {
                 j2 = i;
@@ -279,7 +283,7 @@ public class BlockRedstoneWire extends Block {
             boolean flag = this.canPlace(world, i, j, k);
 
             if (!flag) {
-                this.a_(world, i, j, k, i1);
+                this.b_(world, i, j, k, i1);
                 world.setTypeId(i, j, k, 0);
             } else {
                 this.g(world, i, j, k);
@@ -294,10 +298,10 @@ public class BlockRedstoneWire extends Block {
     }
 
     public boolean c(World world, int i, int j, int k, int l) {
-        return !this.a ? false : this.b(world, i, j, k, l);
+        return !this.a ? false : this.a(world, i, j, k, l);
     }
 
-    public boolean b(IBlockAccess iblockaccess, int i, int j, int k, int l) {
+    public boolean a(IBlockAccess iblockaccess, int i, int j, int k, int l) {
         if (!this.a) {
             return false;
         } else if (iblockaccess.getData(i, j, k) == 0) {
diff --git a/src/main/java/net/minecraft/server/BlockSapling.java b/src/main/java/net/minecraft/server/BlockSapling.java
index 2f2fae00cc..58e6bf58d9 100644
--- a/src/main/java/net/minecraft/server/BlockSapling.java
+++ b/src/main/java/net/minecraft/server/BlockSapling.java
@@ -14,14 +14,16 @@ public class BlockSapling extends BlockFlower {
     }
 
     public void a(World world, int i, int j, int k, Random random) {
-        super.a(world, i, j, k, random);
-        if (world.getLightLevel(i, j + 1, k) >= 9 && random.nextInt(30) == 0) {
-            int l = world.getData(i, j, k);
+        if (!world.isStatic) {
+            super.a(world, i, j, k, random);
+            if (world.getLightLevel(i, j + 1, k) >= 9 && random.nextInt(30) == 0) {
+                int l = world.getData(i, j, k);
 
-            if ((l & 8) == 0) {
-                world.setData(i, j, k, l | 8);
-            } else {
-                this.b(world, i, j, k, random);
+                if ((l & 8) == 0) {
+                    world.setData(i, j, k, l | 8);
+                } else {
+                    this.b(world, i, j, k, random);
+                }
             }
         }
     }
diff --git a/src/main/java/net/minecraft/server/BlockSign.java b/src/main/java/net/minecraft/server/BlockSign.java
index c9dd407fe6..545718432a 100644
--- a/src/main/java/net/minecraft/server/BlockSign.java
+++ b/src/main/java/net/minecraft/server/BlockSign.java
@@ -57,6 +57,10 @@ public class BlockSign extends BlockContainer {
         }
     }
 
+    public boolean b() {
+        return false;
+    }
+
     public boolean a() {
         return false;
     }
@@ -102,7 +106,7 @@ public class BlockSign extends BlockContainer {
         }
 
         if (flag) {
-            this.a_(world, i, j, k, world.getData(i, j, k));
+            this.b_(world, i, j, k, world.getData(i, j, k));
             world.setTypeId(i, j, k, 0);
         }
 
diff --git a/src/main/java/net/minecraft/server/BlockSoil.java b/src/main/java/net/minecraft/server/BlockSoil.java
index 69b95c9201..a37b3cfd0e 100644
--- a/src/main/java/net/minecraft/server/BlockSoil.java
+++ b/src/main/java/net/minecraft/server/BlockSoil.java
@@ -29,13 +29,17 @@ public class BlockSoil extends Block {
         return false;
     }
 
+    public boolean b() {
+        return false;
+    }
+
     public int a(int i, int j) {
         return i == 1 && j > 0 ? this.textureId - 1 : (i == 1 ? this.textureId : 2);
     }
 
     public void a(World world, int i, int j, int k, Random random) {
         if (random.nextInt(5) == 0) {
-            if (!this.h(world, i, j, k) && !world.q(i, j + 1, k)) {
+            if (!this.h(world, i, j, k) && !world.s(i, j + 1, k)) {
                 int l = world.getData(i, j, k);
 
                 if (l > 0) {
diff --git a/src/main/java/net/minecraft/server/BlockStationary.java b/src/main/java/net/minecraft/server/BlockStationary.java
index 1850b14c0a..09cd512911 100644
--- a/src/main/java/net/minecraft/server/BlockStationary.java
+++ b/src/main/java/net/minecraft/server/BlockStationary.java
@@ -30,11 +30,11 @@ public class BlockStationary extends BlockFluids {
     private void i(World world, int i, int j, int k) {
         int l = world.getData(i, j, k);
 
-        world.j = true;
+        world.o = true;
         world.setRawTypeIdAndData(i, j, k, this.id - 1, l);
         world.b(i, j, k, i, j, k);
-        world.c(i, j, k, this.id - 1, this.b());
-        world.j = false;
+        world.c(i, j, k, this.id - 1, this.c());
+        world.o = false;
     }
 
     public void a(World world, int i, int j, int k, Random random) {
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
index 1ff640b1dc..2aa0c3de34 100644
--- a/src/main/java/net/minecraft/server/Chunk.java
+++ b/src/main/java/net/minecraft/server/Chunk.java
@@ -377,15 +377,15 @@ public class Chunk {
             k = this.entitySlices.length - 1;
         }
 
-        entity.bB = true;
-        entity.chunkX = this.x;
-        entity.bD = k;
-        entity.chunkZ = this.z;
+        entity.bE = true;
+        entity.bF = this.x;
+        entity.bG = k;
+        entity.bH = this.z;
         this.entitySlices[k].add(entity);
     }
 
     public void b(Entity entity) {
-        this.a(entity, entity.bD);
+        this.a(entity, entity.bG);
     }
 
     public void a(Entity entity, int i) {
@@ -566,48 +566,64 @@ public class Chunk {
     }
 
     public int a(byte[] abyte, int i, int j, int k, int l, int i1, int j1, int k1) {
-        int l1;
-        int i2;
-        int j2;
-        int k2;
+        int l1 = l - i;
+        int i2 = i1 - j;
+        int j2 = j1 - k;
 
-        for (l1 = i; l1 < l; ++l1) {
-            for (i2 = k; i2 < j1; ++i2) {
-                j2 = l1 << 11 | i2 << 7 | j;
-                k2 = i1 - j;
-                System.arraycopy(this.b, j2, abyte, k1, k2);
-                k1 += k2;
+        if (l1 * i2 * j2 == this.b.length) {
+            System.arraycopy(this.b, 0, abyte, k1, this.b.length);
+            k1 += this.b.length;
+            System.arraycopy(this.e.a, 0, abyte, k1, this.e.a.length);
+            k1 += this.e.a.length;
+            System.arraycopy(this.g.a, 0, abyte, k1, this.g.a.length);
+            k1 += this.g.a.length;
+            System.arraycopy(this.f.a, 0, abyte, k1, this.f.a.length);
+            k1 += this.f.a.length;
+            return k1;
+        } else {
+            int k2;
+            int l2;
+            int i3;
+            int j3;
+
+            for (k2 = i; k2 < l; ++k2) {
+                for (l2 = k; l2 < j1; ++l2) {
+                    i3 = k2 << 11 | l2 << 7 | j;
+                    j3 = i1 - j;
+                    System.arraycopy(this.b, i3, abyte, k1, j3);
+                    k1 += j3;
+                }
             }
-        }
 
-        for (l1 = i; l1 < l; ++l1) {
-            for (i2 = k; i2 < j1; ++i2) {
-                j2 = (l1 << 11 | i2 << 7 | j) >> 1;
-                k2 = (i1 - j) / 2;
-                System.arraycopy(this.e.a, j2, abyte, k1, k2);
-                k1 += k2;
+            for (k2 = i; k2 < l; ++k2) {
+                for (l2 = k; l2 < j1; ++l2) {
+                    i3 = (k2 << 11 | l2 << 7 | j) >> 1;
+                    j3 = (i1 - j) / 2;
+                    System.arraycopy(this.e.a, i3, abyte, k1, j3);
+                    k1 += j3;
+                }
             }
-        }
 
-        for (l1 = i; l1 < l; ++l1) {
-            for (i2 = k; i2 < j1; ++i2) {
-                j2 = (l1 << 11 | i2 << 7 | j) >> 1;
-                k2 = (i1 - j) / 2;
-                System.arraycopy(this.g.a, j2, abyte, k1, k2);
-                k1 += k2;
+            for (k2 = i; k2 < l; ++k2) {
+                for (l2 = k; l2 < j1; ++l2) {
+                    i3 = (k2 << 11 | l2 << 7 | j) >> 1;
+                    j3 = (i1 - j) / 2;
+                    System.arraycopy(this.g.a, i3, abyte, k1, j3);
+                    k1 += j3;
+                }
             }
-        }
 
-        for (l1 = i; l1 < l; ++l1) {
-            for (i2 = k; i2 < j1; ++i2) {
-                j2 = (l1 << 11 | i2 << 7 | j) >> 1;
-                k2 = (i1 - j) / 2;
-                System.arraycopy(this.f.a, j2, abyte, k1, k2);
-                k1 += k2;
+            for (k2 = i; k2 < l; ++k2) {
+                for (l2 = k; l2 < j1; ++l2) {
+                    i3 = (k2 << 11 | l2 << 7 | j) >> 1;
+                    j3 = (i1 - j) / 2;
+                    System.arraycopy(this.f.a, i3, abyte, k1, j3);
+                    k1 += j3;
+                }
             }
-        }
 
-        return k1;
+            return k1;
+        }
     }
 
     public Random a(long i) {
diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 8dd30d8054..8d790184f4 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -24,7 +24,8 @@ public class ChunkProviderServer implements IChunkProvider {
     public LongHashset unloadQueue = new LongHashset();
     public Chunk emptyChunk;
     public IChunkProvider chunkProvider; // CraftBukkit
-    private IChunkLoader d;
+    private IChunkLoader e;
+    public boolean a = false;
     public LongHashtable<Chunk> chunks = new LongHashtable<Chunk>();
     public List chunkList = new ArrayList();
     public WorldServer world;
@@ -33,7 +34,7 @@ public class ChunkProviderServer implements IChunkProvider {
     public ChunkProviderServer(WorldServer worldserver, IChunkLoader ichunkloader, IChunkProvider ichunkprovider) {
         this.emptyChunk = new EmptyChunk(worldserver, new byte['\u8000'], 0, 0);
         this.world = worldserver;
-        this.d = ichunkloader;
+        this.e = ichunkloader;
         this.chunkProvider = ichunkprovider;
     }
 
@@ -111,7 +112,7 @@ public class ChunkProviderServer implements IChunkProvider {
         // CraftBukkit start
         Chunk chunk = (Chunk) this.chunks.get(i, j);
 
-        chunk = chunk == null ? (this.world.isLoading ? this.getChunkAt(i, j) : this.emptyChunk) : chunk;
+        chunk = chunk == null ? (!this.world.isLoading && !this.a ? this.emptyChunk : this.getChunkAt(i, j)) : chunk;
         if (chunk == this.emptyChunk) return chunk;
         if (i != chunk.x || j != chunk.z) {
             MinecraftServer.log.info("Chunk (" + chunk.x + ", " + chunk.z +") stored at  (" + i + ", " + j + ")");
@@ -125,11 +126,11 @@ public class ChunkProviderServer implements IChunkProvider {
     }
 
     public Chunk loadChunk(int i, int j) { // CraftBukkit - private -> public
-        if (this.d == null) {
+        if (this.e == null) {
             return null;
         } else {
             try {
-                Chunk chunk = this.d.a(this.world, i, j);
+                Chunk chunk = this.e.a(this.world, i, j);
 
                 if (chunk != null) {
                     chunk.r = this.world.getTime();
@@ -144,9 +145,9 @@ public class ChunkProviderServer implements IChunkProvider {
     }
 
     public void saveChunkNOP(Chunk chunk) { // CraftBukkit - private -> public
-        if (this.d != null) {
+        if (this.e != null) {
             try {
-                this.d.b(this.world, chunk);
+                this.e.b(this.world, chunk);
             } catch (Exception exception) {
                 exception.printStackTrace();
             }
@@ -154,10 +155,10 @@ public class ChunkProviderServer implements IChunkProvider {
     }
 
     public void saveChunk(Chunk chunk) { // CraftBukkit - private -> public
-        if (this.d != null) {
+        if (this.e != null) {
             try {
                 chunk.r = this.world.getTime();
-                this.d.a(this.world, chunk);
+                this.e.a(this.world, chunk);
             } catch (Exception ioexception) { // CraftBukkit - IOException -> Exception
                 ioexception.printStackTrace();
             }
@@ -197,18 +198,18 @@ public class ChunkProviderServer implements IChunkProvider {
         }
 
         if (flag) {
-            if (this.d == null) {
+            if (this.e == null) {
                 return true;
             }
 
-            this.d.b();
+            this.e.b();
         }
 
         return true;
     }
 
     public boolean unloadChunks() {
-        if (!this.world.y) {
+        if (!this.world.E) {
             // CraftBukkit start
             Server server = this.world.getServer();
             for (int i = 0; i < 50 && !this.unloadQueue.isEmpty(); i++) {
@@ -231,8 +232,8 @@ public class ChunkProviderServer implements IChunkProvider {
             }
             // CraftBukkit end
 
-            if (this.d != null) {
-                this.d.a();
+            if (this.e != null) {
+                this.e.a();
             }
         }
 
@@ -240,6 +241,6 @@ public class ChunkProviderServer implements IChunkProvider {
     }
 
     public boolean b() {
-        return !this.world.y;
+        return !this.world.E;
     }
 }
diff --git a/src/main/java/net/minecraft/server/ConsoleCommandHandler.java b/src/main/java/net/minecraft/server/ConsoleCommandHandler.java
index d6f3bfb3c0..c8d857803e 100644
--- a/src/main/java/net/minecraft/server/ConsoleCommandHandler.java
+++ b/src/main/java/net/minecraft/server/ConsoleCommandHandler.java
@@ -3,6 +3,7 @@ package net.minecraft.server;
 import java.util.Iterator;
 import java.util.Set;
 import java.util.logging.Logger;
+
 // Craftbukkit start
 import java.util.List;
 import org.bukkit.craftbukkit.command.ServerCommandListener;
@@ -24,7 +25,6 @@ public class ConsoleCommandHandler {
         String s = servercommand.command;
         ICommandListener icommandlistener = servercommand.b;
         String s1 = icommandlistener.getName();
-        WorldServer worldserver = this.server.worlds.get(0); // CraftBukkit
         listener = icommandlistener; // CraftBukkit
         ServerConfigurationManager serverconfigurationmanager = this.server.serverConfigurationManager;
 
@@ -34,183 +34,218 @@ public class ConsoleCommandHandler {
             } else if (s.toLowerCase().startsWith("stop")) {
                 this.print(s1, "Stopping the server..");
                 this.server.a();
-            } else if (s.toLowerCase().startsWith("save-all")) {
-                this.print(s1, "Forcing save..");
-                boolean save = worldserver.y; // CraftBukkit - record current save flag state.
-                worldserver.y = false; // CraftBukkit - If save-all is used, we can assume saving should be turned on to allow for saving.
-                this.server.saveChunks(); // CraftBukkit - We should save all worlds on save-all.
-                worldserver.y = save;  // CraftBukkit start - Once done saving, we should turn it back off to avoid confusion if it was originally off.
-                this.print(s1, "Save complete.");
-            } else if (s.toLowerCase().startsWith("save-off")) {
-                this.print(s1, "Disabling level saving..");
-                worldserver.y = true;
-            } else if (s.toLowerCase().startsWith("save-on")) {
-                this.print(s1, "Enabling level saving..");
-                worldserver.y = false;
             } else {
-                String s2;
+                int i;
+                WorldServer worldserver;
 
-                if (s.toLowerCase().startsWith("op ")) {
-                    s2 = s.substring(s.indexOf(" ")).trim();
-                    serverconfigurationmanager.e(s2);
-                    this.print(s1, "Opping " + s2);
-                    serverconfigurationmanager.a(s2, "\u00A7eYou are now op!");
-                } else if (s.toLowerCase().startsWith("deop ")) {
-                    s2 = s.substring(s.indexOf(" ")).trim();
-                    serverconfigurationmanager.f(s2);
-                    serverconfigurationmanager.a(s2, "\u00A7eYou are no longer op!");
-                    this.print(s1, "De-opping " + s2);
-                } else if (s.toLowerCase().startsWith("ban-ip ")) {
-                    s2 = s.substring(s.indexOf(" ")).trim();
-                    serverconfigurationmanager.c(s2);
-                    this.print(s1, "Banning ip " + s2);
-                } else if (s.toLowerCase().startsWith("pardon-ip ")) {
-                    s2 = s.substring(s.indexOf(" ")).trim();
-                    serverconfigurationmanager.d(s2);
-                    this.print(s1, "Pardoning ip " + s2);
+                if (s.toLowerCase().startsWith("save-all")) {
+                    this.print(s1, "Forcing save..");
+                    if (serverconfigurationmanager != null) {
+                        serverconfigurationmanager.savePlayers();
+                    }
+
+                    // Craftbukkit start
+                    for (i = 0; i < this.server.worlds.size(); ++i) {
+                        worldserver = this.server.worlds.get(i);
+                        boolean save = worldserver.E;
+                        worldserver.E = false;
+                        worldserver.save(true, (IProgressUpdate) null);
+                        worldserver.E = save;
+                    }
+                    // CraftBukkit end
+
+                    this.print(s1, "Save complete.");
+                } else if (s.toLowerCase().startsWith("save-off")) {
+                    this.print(s1, "Disabling level saving..");
+
+                    for (i = 0; i < this.server.worlds.size(); ++i) { // Craftbukkit start
+                        worldserver = this.server.worlds.get(i); // Craftbukkit start
+                        worldserver.E = true;
+                    }
+                } else if (s.toLowerCase().startsWith("save-on")) {
+                    this.print(s1, "Enabling level saving..");
+
+                    for (i = 0; i < this.server.worlds.size(); ++i) { // Craftbukkit start
+                        worldserver = this.server.worlds.get(i); // Craftbukkit start
+                        worldserver.E = false;
+                    }
                 } else {
-                    EntityPlayer entityplayer;
+                    String s2;
 
-                    if (s.toLowerCase().startsWith("ban ")) {
+                    if (s.toLowerCase().startsWith("op ")) {
                         s2 = s.substring(s.indexOf(" ")).trim();
-                        serverconfigurationmanager.a(s2);
-                        this.print(s1, "Banning " + s2);
-                        entityplayer = serverconfigurationmanager.i(s2);
-                        if (entityplayer != null) {
-                            entityplayer.netServerHandler.disconnect("Banned by admin");
-                        }
-                    } else if (s.toLowerCase().startsWith("pardon ")) {
+                        serverconfigurationmanager.e(s2);
+                        this.print(s1, "Opping " + s2);
+                        serverconfigurationmanager.a(s2, "\u00A7eYou are now op!");
+                    } else if (s.toLowerCase().startsWith("deop ")) {
                         s2 = s.substring(s.indexOf(" ")).trim();
-                        serverconfigurationmanager.b(s2);
-                        this.print(s1, "Pardoning " + s2);
+                        serverconfigurationmanager.f(s2);
+                        serverconfigurationmanager.a(s2, "\u00A7eYou are no longer op!");
+                        this.print(s1, "De-opping " + s2);
+                    } else if (s.toLowerCase().startsWith("ban-ip ")) {
+                        s2 = s.substring(s.indexOf(" ")).trim();
+                        serverconfigurationmanager.c(s2);
+                        this.print(s1, "Banning ip " + s2);
+                    } else if (s.toLowerCase().startsWith("pardon-ip ")) {
+                        s2 = s.substring(s.indexOf(" ")).trim();
+                        serverconfigurationmanager.d(s2);
+                        this.print(s1, "Pardoning ip " + s2);
                     } else {
-                        int i;
-
-                        if (s.toLowerCase().startsWith("kick ")) {
-                            // CraftBukkit start - Add kick message compatibility
-                            String[] parts = s.split(" ");
-                            s2 = parts.length >= 2 ? parts[1] : "";
-                            // CraftBukkit end
-                            entityplayer = null;
-
-                            for (i = 0; i < serverconfigurationmanager.players.size(); ++i) {
-                                EntityPlayer entityplayer1 = (EntityPlayer) serverconfigurationmanager.players.get(i);
-
-                                if (entityplayer1.name.equalsIgnoreCase(s2)) {
-                                    entityplayer = entityplayer1;
-                                }
-                            }
+                        EntityPlayer entityplayer;
 
+                        if (s.toLowerCase().startsWith("ban ")) {
+                            s2 = s.substring(s.indexOf(" ")).trim();
+                            serverconfigurationmanager.a(s2);
+                            this.print(s1, "Banning " + s2);
+                            entityplayer = serverconfigurationmanager.i(s2);
                             if (entityplayer != null) {
-                                entityplayer.netServerHandler.disconnect("Kicked by admin");
-                                this.print(s1, "Kicking " + entityplayer.name);
-                            } else {
-                                icommandlistener.sendMessage("Can\'t find user " + s2 + ". No kick.");
+                                entityplayer.netServerHandler.disconnect("Banned by admin");
                             }
+                        } else if (s.toLowerCase().startsWith("pardon ")) {
+                            s2 = s.substring(s.indexOf(" ")).trim();
+                            serverconfigurationmanager.b(s2);
+                            this.print(s1, "Pardoning " + s2);
                         } else {
-                            String[] astring;
-                            EntityPlayer entityplayer2;
+                            int j;
 
-                            if (s.toLowerCase().startsWith("tp ")) {
-                                astring = s.split(" ");
-                                if (astring.length == 3) {
-                                    entityplayer = serverconfigurationmanager.i(astring[1]);
-                                    entityplayer2 = serverconfigurationmanager.i(astring[2]);
-                                    if (entityplayer == null) {
-                                        icommandlistener.sendMessage("Can\'t find user " + astring[1] + ". No tp.");
-                                    } else if (entityplayer2 == null) {
-                                        icommandlistener.sendMessage("Can\'t find user " + astring[2] + ". No tp.");
-                                    } else {
-                                        entityplayer.netServerHandler.a(entityplayer2.locX, entityplayer2.locY, entityplayer2.locZ, entityplayer2.yaw, entityplayer2.pitch);
-                                        this.print(s1, "Teleporting " + astring[1] + " to " + astring[2] + ".");
+                            if (s.toLowerCase().startsWith("kick ")) {
+                                // CraftBukkit start - Add kick message compatibility
+                                String[] parts = s.split(" ");
+                                s2 = parts.length >= 2 ? parts[1] : "";
+                                // CraftBukkit end
+                                entityplayer = null;
+
+                                for (j = 0; j < serverconfigurationmanager.players.size(); ++j) {
+                                    EntityPlayer entityplayer1 = (EntityPlayer) serverconfigurationmanager.players.get(j);
+
+                                    if (entityplayer1.name.equalsIgnoreCase(s2)) {
+                                        entityplayer = entityplayer1;
                                     }
+                                }
+
+                                if (entityplayer != null) {
+                                    entityplayer.netServerHandler.disconnect("Kicked by admin");
+                                    this.print(s1, "Kicking " + entityplayer.name);
                                 } else {
-                                    icommandlistener.sendMessage("Syntax error, please provice a source and a target.");
+                                    icommandlistener.sendMessage("Can\'t find user " + s2 + ". No kick.");
                                 }
                             } else {
-                                String s3;
+                                EntityPlayer entityplayer2;
+                                String[] astring;
 
-                                if (s.toLowerCase().startsWith("give ")) {
+                                if (s.toLowerCase().startsWith("tp ")) {
                                     astring = s.split(" ");
-                                    if (astring.length != 3 && astring.length != 4) {
-                                        return true; // CraftBukkit
-                                    }
-
-                                    s3 = astring[1];
-                                    entityplayer2 = serverconfigurationmanager.i(s3);
-                                    if (entityplayer2 != null) {
-                                        try {
-                                            int j = Integer.parseInt(astring[2]);
-
-                                            if (Item.byId[j] != null) {
-                                                this.print(s1, "Giving " + entityplayer2.name + " some " + j);
-                                                int k = 1;
-
-                                                if (astring.length > 3) {
-                                                    k = this.a(astring[3], 1);
-                                                }
-
-                                                if (k < 1) {
-                                                    k = 1;
-                                                }
-
-                                                if (k > 64) {
-                                                    k = 64;
-                                                }
-
-                                                entityplayer2.b(new ItemStack(j, k, 0));
-                                            } else {
-                                                icommandlistener.sendMessage("There\'s no item with id " + j);
-                                            }
-                                        } catch (NumberFormatException numberformatexception) {
-                                            icommandlistener.sendMessage("There\'s no item with id " + astring[2]);
+                                    if (astring.length == 3) {
+                                        entityplayer = serverconfigurationmanager.i(astring[1]);
+                                        entityplayer2 = serverconfigurationmanager.i(astring[2]);
+                                        if (entityplayer == null) {
+                                            icommandlistener.sendMessage("Can\'t find user " + astring[1] + ". No tp.");
+                                        } else if (entityplayer2 == null) {
+                                            icommandlistener.sendMessage("Can\'t find user " + astring[2] + ". No tp.");
+                                        } else if (entityplayer.dimension != entityplayer2.dimension) {
+                                            icommandlistener.sendMessage("User " + astring[1] + " and " + astring[2] + " are in different dimensions. No tp.");
+                                        } else {
+                                            entityplayer.netServerHandler.a(entityplayer2.locX, entityplayer2.locY, entityplayer2.locZ, entityplayer2.yaw, entityplayer2.pitch);
+                                            this.print(s1, "Teleporting " + astring[1] + " to " + astring[2] + ".");
                                         }
                                     } else {
-                                        icommandlistener.sendMessage("Can\'t find user " + s3);
+                                        icommandlistener.sendMessage("Syntax error, please provice a source and a target.");
                                     }
-                                } else if (s.toLowerCase().startsWith("time ")) {
-                                    astring = s.split(" ");
-                                    if (astring.length != 3) {
-                                        return true; // CraftBukkit
-                                    }
-
-                                    s3 = astring[1];
-
-                                    try {
-                                        i = Integer.parseInt(astring[2]);
-                                        if ("add".equalsIgnoreCase(s3)) {
-                                            worldserver.setTime(worldserver.getTime() + (long) i);
-                                            this.print(s1, "Added " + i + " to time");
-                                        } else if ("set".equalsIgnoreCase(s3)) {
-                                            worldserver.setTime((long) i);
-                                            this.print(s1, "Set time to " + i);
-                                        } else {
-                                            icommandlistener.sendMessage("Unknown method, use either \"add\" or \"set\"");
-                                        }
-                                    } catch (NumberFormatException numberformatexception1) {
-                                        icommandlistener.sendMessage("Unable to convert time value, " + astring[2]);
-                                    }
-                                } else if (s.toLowerCase().startsWith("say ")) {
-                                    s = s.substring(s.indexOf(" ")).trim();
-                                    a.info("[" + s1 + "] " + s);
-                                    serverconfigurationmanager.sendAll(new Packet3Chat("\u00A7d[Server] " + s));
-                                } else if (s.toLowerCase().startsWith("tell ")) {
-                                    astring = s.split(" ");
-                                    if (astring.length >= 3) {
-                                        s = s.substring(s.indexOf(" ")).trim();
-                                        s = s.substring(s.indexOf(" ")).trim();
-                                        a.info("[" + s1 + "->" + astring[1] + "] " + s);
-                                        s = "\u00A77" + s1 + " whispers " + s;
-                                        a.info(s);
-                                        if (!serverconfigurationmanager.a(astring[1], (Packet) (new Packet3Chat(s)))) {
-                                            icommandlistener.sendMessage("There\'s no player by that name online.");
-                                        }
-                                    }
-                                } else if (s.toLowerCase().startsWith("whitelist ")) {
-                                    this.a(s1, s, icommandlistener);
                                 } else {
-                                    icommandlistener.sendMessage("Unknown console command. Type \"help\" for help."); // CraftBukkit
-                                    return false; // CraftBukkit
+                                    String s3;
+                                    int k;
+
+                                    if (s.toLowerCase().startsWith("give ")) {
+                                        astring = s.split(" ");
+                                        if (astring.length != 3 && astring.length != 4) {
+                                            return true; // CraftBukkit
+                                        }
+
+                                        s3 = astring[1];
+                                        entityplayer2 = serverconfigurationmanager.i(s3);
+                                        if (entityplayer2 != null) {
+                                            try {
+                                                k = Integer.parseInt(astring[2]);
+                                                if (Item.byId[k] != null) {
+                                                    this.print(s1, "Giving " + entityplayer2.name + " some " + k);
+                                                    int l = 1;
+
+                                                    if (astring.length > 3) {
+                                                        l = this.a(astring[3], 1);
+                                                    }
+
+                                                    if (l < 1) {
+                                                        l = 1;
+                                                    }
+
+                                                    if (l > 64) {
+                                                        l = 64;
+                                                    }
+
+                                                    entityplayer2.b(new ItemStack(k, l, 0));
+                                                } else {
+                                                    icommandlistener.sendMessage("There\'s no item with id " + k);
+                                                }
+                                            } catch (NumberFormatException numberformatexception) {
+                                                icommandlistener.sendMessage("There\'s no item with id " + astring[2]);
+                                            }
+                                        } else {
+                                            icommandlistener.sendMessage("Can\'t find user " + s3);
+                                        }
+                                    } else if (s.toLowerCase().startsWith("time ")) {
+                                        astring = s.split(" ");
+                                        if (astring.length != 3) {
+                                            return true; // CraftBukkit
+                                        }
+
+                                        s3 = astring[1];
+
+                                        try {
+                                            j = Integer.parseInt(astring[2]);
+                                            WorldServer worldserver1;
+
+                                            if ("add".equalsIgnoreCase(s3)) {
+                                                for (k = 0; k < this.server.worlds.size(); ++k) { // Craftbukkit start
+                                                    worldserver1 = this.server.worlds.get(k); // Craftbukkit start
+                                                    worldserver1.setTime(worldserver1.getTime() + (long) j);
+                                                }
+
+                                                this.print(s1, "Added " + j + " to time");
+                                            } else if ("set".equalsIgnoreCase(s3)) {
+                                                for (k = 0; k < this.server.worlds.size(); ++k) { // Craftbukkit start
+                                                    worldserver1 = this.server.worlds.get(k); // Craftbukkit start
+                                                    worldserver1.setTime((long) j);
+                                                }
+
+                                                this.print(s1, "Set time to " + j);
+                                            } else {
+                                                icommandlistener.sendMessage("Unknown method, use either \"add\" or \"set\"");
+                                            }
+                                        } catch (NumberFormatException numberformatexception1) {
+                                            icommandlistener.sendMessage("Unable to convert time value, " + astring[2]);
+                                        }
+                                    } else if (s.toLowerCase().startsWith("say ")) {
+                                        s = s.substring(s.indexOf(" ")).trim();
+                                        a.info("[" + s1 + "] " + s);
+                                        serverconfigurationmanager.sendAll(new Packet3Chat("\u00A7d[Server] " + s));
+                                    } else if (s.toLowerCase().startsWith("tell ")) {
+                                        astring = s.split(" ");
+                                        if (astring.length >= 3) {
+                                            s = s.substring(s.indexOf(" ")).trim();
+                                            s = s.substring(s.indexOf(" ")).trim();
+                                            a.info("[" + s1 + "->" + astring[1] + "] " + s);
+                                            s = "\u00A77" + s1 + " whispers " + s;
+                                            a.info(s);
+                                            if (!serverconfigurationmanager.a(astring[1], (Packet) (new Packet3Chat(s)))) {
+                                                icommandlistener.sendMessage("There\'s no player by that name online.");
+                                            }
+                                        }
+                                    } else if (s.toLowerCase().startsWith("whitelist ")) {
+                                        this.a(s1, s, icommandlistener);
+                                    } else {
+                                        icommandlistener.sendMessage("Unknown console command. Type \"help\" for help."); // CraftBukkit
+                                        return false; // CraftBukkit
+                                    }
                                 }
                             }
                         }
diff --git a/src/main/java/net/minecraft/server/ContainerPlayer.java b/src/main/java/net/minecraft/server/ContainerPlayer.java
index 2614a57d4c..8a4fb18234 100644
--- a/src/main/java/net/minecraft/server/ContainerPlayer.java
+++ b/src/main/java/net/minecraft/server/ContainerPlayer.java
@@ -75,4 +75,38 @@ public class ContainerPlayer extends Container {
     public boolean b(EntityHuman entityhuman) {
         return true;
     }
+
+    public ItemStack a(int i) {
+        ItemStack itemstack = null;
+        Slot slot = (Slot) this.e.get(i);
+
+        if (slot != null && slot.b()) {
+            ItemStack itemstack1 = slot.getItem();
+
+            itemstack = itemstack1.j();
+            if (i == 0) {
+                this.a(itemstack1, 9, 45, true);
+            } else if (i >= 9 && i < 36) {
+                this.a(itemstack1, 36, 45, false);
+            } else if (i >= 36 && i < 45) {
+                this.a(itemstack1, 9, 36, false);
+            } else {
+                this.a(itemstack1, 9, 45, false);
+            }
+
+            if (itemstack1.count == 0) {
+                slot.c((ItemStack) null);
+            } else {
+                slot.c();
+            }
+
+            if (itemstack1.count == itemstack.count) {
+                return null;
+            }
+
+            slot.a(itemstack1);
+        }
+
+        return itemstack;
+    }
 }
diff --git a/src/main/java/net/minecraft/server/ContainerWorkbench.java b/src/main/java/net/minecraft/server/ContainerWorkbench.java
index 6666353e7d..4a735872b5 100644
--- a/src/main/java/net/minecraft/server/ContainerWorkbench.java
+++ b/src/main/java/net/minecraft/server/ContainerWorkbench.java
@@ -69,4 +69,38 @@ public class ContainerWorkbench extends Container {
     public boolean b(EntityHuman entityhuman) {
         return this.c.getTypeId(this.h, this.i, this.j) != Block.WORKBENCH.id ? false : entityhuman.d((double) this.h + 0.5D, (double) this.i + 0.5D, (double) this.j + 0.5D) <= 64.0D;
     }
+
+    public ItemStack a(int i) {
+        ItemStack itemstack = null;
+        Slot slot = (Slot) this.e.get(i);
+
+        if (slot != null && slot.b()) {
+            ItemStack itemstack1 = slot.getItem();
+
+            itemstack = itemstack1.j();
+            if (i == 0) {
+                this.a(itemstack1, 10, 46, true);
+            } else if (i >= 10 && i < 37) {
+                this.a(itemstack1, 37, 46, false);
+            } else if (i >= 37 && i < 46) {
+                this.a(itemstack1, 10, 37, false);
+            } else {
+                this.a(itemstack1, 10, 46, false);
+            }
+
+            if (itemstack1.count == 0) {
+                slot.c((ItemStack) null);
+            } else {
+                slot.c();
+            }
+
+            if (itemstack1.count == itemstack.count) {
+                return null;
+            }
+
+            slot.a(itemstack1);
+        }
+
+        return itemstack;
+    }
 }
diff --git a/src/main/java/net/minecraft/server/CraftingManager.java b/src/main/java/net/minecraft/server/CraftingManager.java
index c5ec460e13..5280be2091 100644
--- a/src/main/java/net/minecraft/server/CraftingManager.java
+++ b/src/main/java/net/minecraft/server/CraftingManager.java
@@ -40,6 +40,7 @@ public class CraftingManager {
         this.a(new ItemStack(Block.STEP, 3, 2), new Object[] { "###", Character.valueOf('#'), Block.WOOD});
         this.a(new ItemStack(Block.LADDER, 2), new Object[] { "# #", "###", "# #", Character.valueOf('#'), Item.STICK});
         this.a(new ItemStack(Item.WOOD_DOOR, 1), new Object[] { "##", "##", "##", Character.valueOf('#'), Block.WOOD});
+        this.a(new ItemStack(Block.TRAP_DOOR, 2), new Object[] { "###", "###", Character.valueOf('#'), Block.WOOD});
         this.a(new ItemStack(Item.IRON_DOOR, 1), new Object[] { "##", "##", "##", Character.valueOf('#'), Item.IRON_INGOT});
         this.a(new ItemStack(Item.SIGN, 1), new Object[] { "###", "###", " X ", Character.valueOf('#'), Block.WOOD, Character.valueOf('X'), Item.STICK});
         this.a(new ItemStack(Item.CAKE, 1), new Object[] { "AAA", "BEB", "CCC", Character.valueOf('A'), Item.MILK_BUCKET, Character.valueOf('B'), Item.SUGAR, Character.valueOf('C'), Item.WHEAT, Character.valueOf('E'), Item.EGG});
@@ -70,6 +71,7 @@ public class CraftingManager {
         this.a(new ItemStack(Item.DIODE, 1), new Object[] { "#X#", "III", Character.valueOf('#'), Block.REDSTONE_TORCH_ON, Character.valueOf('X'), Item.REDSTONE, Character.valueOf('I'), Block.STONE});
         this.a(new ItemStack(Item.WATCH, 1), new Object[] { " # ", "#X#", " # ", Character.valueOf('#'), Item.GOLD_INGOT, Character.valueOf('X'), Item.REDSTONE});
         this.a(new ItemStack(Item.COMPASS, 1), new Object[] { " # ", "#X#", " # ", Character.valueOf('#'), Item.IRON_INGOT, Character.valueOf('X'), Item.REDSTONE});
+        this.a(new ItemStack(Item.MAP, 1), new Object[] { "###", "#X#", "###", Character.valueOf('#'), Item.PAPER, Character.valueOf('X'), Item.COMPASS});
         this.a(new ItemStack(Block.STONE_BUTTON, 1), new Object[] { "#", "#", Character.valueOf('#'), Block.STONE});
         this.a(new ItemStack(Block.STONE_PLATE, 1), new Object[] { "##", Character.valueOf('#'), Block.STONE});
         this.a(new ItemStack(Block.WOOD_PLATE, 1), new Object[] { "##", Character.valueOf('#'), Block.WOOD});
@@ -79,7 +81,7 @@ public class CraftingManager {
         System.out.println(this.b.size() + " recipes");
     }
 
-    public void a(ItemStack itemstack, Object[] aobject) { // CraftBukkit - default -> public and Object... -> Object[]
+    public void a(ItemStack itemstack, Object... aobject) { // CraftBukkit - default -> public
         String s = "";
         int i = 0;
         int j = 0;
@@ -137,7 +139,7 @@ public class CraftingManager {
         this.b.add(new ShapedRecipes(j, k, aitemstack, itemstack));
     }
 
-    public void b(ItemStack itemstack, Object[] aobject) { // CraftBukkit - default -> public and Object... -> Object[]
+    public void b(ItemStack itemstack, Object... aobject) { // CraftBukkit - default -> public
         ArrayList arraylist = new ArrayList();
         Object[] aobject1 = aobject;
         int i = aobject.length;
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index 9bc5eb2c29..cdeab5c426 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -1,5 +1,6 @@
 package net.minecraft.server;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
 
@@ -24,8 +25,8 @@ public abstract class Entity {
 
     private static int entityCount = 0;
     public int id;
-    public double aD;
-    public boolean aE;
+    public double aG;
+    public boolean aH;
     public Entity passenger;
     public Entity vehicle;
     public World world;
@@ -45,77 +46,80 @@ public abstract class Entity {
     public final AxisAlignedBB boundingBox;
     public boolean onGround;
     public boolean positionChanged;
-    public boolean aY;
-    public boolean aZ;
-    public boolean velocityChanged;
     public boolean bb;
     public boolean bc;
+    public boolean velocityChanged;
+    public boolean be;
+    public boolean bf;
     public boolean dead;
     public float height;
     public float length;
     public float width;
-    public float bh;
-    public float bi;
+    public float bk;
+    public float bl;
     public float fallDistance; // CraftBukkit - private -> public
     private int b;
-    public double bk;
-    public double bl;
-    public double bm;
-    public float bn;
-    public float bo;
-    public boolean bp;
+    public double bn;
+    public double bo;
+    public double bp;
     public float bq;
+    public float br;
+    public boolean bs;
+    public float bt;
     protected Random random;
     public int ticksLived;
     public int maxFireTicks;
     public int fireTicks;
     public int maxAirTicks; // CraftBukkit - protected - >public
-    protected boolean bw;
+    protected boolean bz;
     public int noDamageTicks;
     public int airTicks;
     private boolean justCreated;
-    protected boolean bz;
+    protected boolean bC;
     protected DataWatcher datawatcher;
     private double d;
     private double e;
-    public boolean bB;
-    public int chunkX;
-    public int bD;
-    public int chunkZ;
+    public boolean bE;
+    public int bF;
+    public int bG;
+    public int bH;
+    public boolean bI;
+    private ArrayList f;
 
     public Entity(World world) {
         this.id = entityCount++;
-        this.aD = 1.0D;
-        this.aE = false;
+        this.aG = 1.0D;
+        this.aH = false;
         this.boundingBox = AxisAlignedBB.a(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
         this.onGround = false;
-        this.aZ = false;
+        this.bc = false;
         this.velocityChanged = false;
-        this.bc = true;
+        this.bf = true;
         this.dead = false;
         this.height = 0.0F;
         this.length = 0.6F;
         this.width = 1.8F;
-        this.bh = 0.0F;
-        this.bi = 0.0F;
+        this.bk = 0.0F;
+        this.bl = 0.0F;
         this.fallDistance = 0.0F;
         this.b = 1;
-        this.bn = 0.0F;
-        this.bo = 0.0F;
-        this.bp = false;
         this.bq = 0.0F;
+        this.br = 0.0F;
+        this.bs = false;
+        this.bt = 0.0F;
         this.random = new Random();
         this.ticksLived = 0;
         this.maxFireTicks = 1;
         this.fireTicks = 0;
         this.maxAirTicks = 300;
-        this.bw = false;
+        this.bz = false;
         this.noDamageTicks = 0;
         this.airTicks = 300;
         this.justCreated = true;
-        this.bz = false;
+        this.bC = false;
         this.datawatcher = new DataWatcher();
-        this.bB = false;
+        this.bE = false;
+        this.f = new ArrayList();
         this.world = world;
         this.setPosition(0.0D, 0.0D, 0.0D);
         this.datawatcher.a(0, Byte.valueOf((byte) 0));
@@ -124,7 +128,7 @@ public abstract class Entity {
 
     protected abstract void b();
 
-    public DataWatcher W() {
+    public DataWatcher X() {
         return this.datawatcher;
     }
 
@@ -184,27 +188,27 @@ public abstract class Entity {
         float f = this.length / 2.0F;
         float f1 = this.width;
 
-        this.boundingBox.c(d0 - (double) f, d1 - (double) this.height + (double) this.bn, d2 - (double) f, d0 + (double) f, d1 - (double) this.height + (double) this.bn + (double) f1, d2 + (double) f);
+        this.boundingBox.c(d0 - (double) f, d1 - (double) this.height + (double) this.bq, d2 - (double) f, d0 + (double) f, d1 - (double) this.height + (double) this.bq + (double) f1, d2 + (double) f);
     }
 
     public void p_() {
-        this.N();
+        this.O();
     }
 
-    public void N() {
+    public void O() {
         if (this.vehicle != null && this.vehicle.dead) {
             this.vehicle = null;
         }
 
         ++this.ticksLived;
-        this.bh = this.bi;
+        this.bk = this.bl;
         this.lastX = this.locX;
         this.lastY = this.locY;
         this.lastZ = this.locZ;
         this.lastPitch = this.pitch;
         this.lastYaw = this.yaw;
         if (this.f_()) {
-            if (!this.bw && !this.justCreated) {
+            if (!this.bz && !this.justCreated) {
                 float f = MathHelper.a(this.motX * this.motX * 0.20000000298023224D + this.motY * this.motY + this.motZ * this.motZ * 0.20000000298023224D) * 0.2F;
 
                 if (f > 1.0F) {
@@ -232,16 +236,16 @@ public abstract class Entity {
             }
 
             this.fallDistance = 0.0F;
-            this.bw = true;
+            this.bz = true;
             this.fireTicks = 0;
         } else {
-            this.bw = false;
+            this.bz = false;
         }
 
         if (this.world.isStatic) {
             this.fireTicks = 0;
         } else if (this.fireTicks > 0) {
-            if (this.bz) {
+            if (this.bC) {
                 this.fireTicks -= 4;
                 if (this.fireTicks < 0) {
                     this.fireTicks = 0;
@@ -272,12 +276,12 @@ public abstract class Entity {
             }
         }
 
-        if (this.aa()) {
-            this.X();
+        if (this.ab()) {
+            this.Y();
         }
 
         if (this.locY < -64.0D) {
-            this.U();
+            this.V();
         }
 
         if (!this.world.isStatic) {
@@ -288,8 +292,8 @@ public abstract class Entity {
         this.justCreated = false;
     }
 
-    protected void X() {
-        if (!this.bz) {
+    protected void Y() {
+        if (!this.bC) {
             // CraftBukkit start - TODO: this event spams!
             if (this instanceof EntityLiving) {
                 CraftServer server = ((WorldServer) this.world).getServer();
@@ -326,7 +330,7 @@ public abstract class Entity {
         }
     }
 
-    protected void U() {
+    protected void V() {
         this.die();
     }
 
@@ -338,17 +342,17 @@ public abstract class Entity {
     }
 
     public void move(double d0, double d1, double d2) {
-        if (this.bp) {
+        if (this.bs) {
             this.boundingBox.d(d0, d1, d2);
             this.locX = (this.boundingBox.a + this.boundingBox.d) / 2.0D;
-            this.locY = this.boundingBox.b + (double) this.height - (double) this.bn;
+            this.locY = this.boundingBox.b + (double) this.height - (double) this.bq;
             this.locZ = (this.boundingBox.c + this.boundingBox.f) / 2.0D;
         } else {
             double d3 = this.locX;
             double d4 = this.locZ;
 
-            if (this.bb) {
-                this.bb = false;
+            if (this.be) {
+                this.be = false;
                 d0 *= 0.25D;
                 d1 *= 0.05000000074505806D;
                 d2 *= 0.25D;
@@ -394,7 +398,7 @@ public abstract class Entity {
             }
 
             this.boundingBox.d(0.0D, d1, 0.0D);
-            if (!this.bc && d6 != d1) {
+            if (!this.bf && d6 != d1) {
                 d2 = 0.0D;
                 d1 = 0.0D;
                 d0 = 0.0D;
@@ -409,7 +413,7 @@ public abstract class Entity {
             }
 
             this.boundingBox.d(d0, 0.0D, 0.0D);
-            if (!this.bc && d5 != d0) {
+            if (!this.bf && d5 != d0) {
                 d2 = 0.0D;
                 d1 = 0.0D;
                 d0 = 0.0D;
@@ -420,7 +424,7 @@ public abstract class Entity {
             }
 
             this.boundingBox.d(0.0D, 0.0D, d2);
-            if (!this.bc && d7 != d2) {
+            if (!this.bf && d7 != d2) {
                 d2 = 0.0D;
                 d1 = 0.0D;
                 d0 = 0.0D;
@@ -430,13 +434,13 @@ public abstract class Entity {
             double d10;
             int k;
 
-            if (this.bo > 0.0F && flag1 && this.bn < 0.05F && (d5 != d0 || d7 != d2)) {
+            if (this.br > 0.0F && flag1 && (flag || this.bq < 0.05F) && (d5 != d0 || d7 != d2)) {
                 d9 = d0;
                 d10 = d1;
                 double d11 = d2;
 
                 d0 = d5;
-                d1 = (double) this.bo;
+                d1 = (double) this.br;
                 d2 = d7;
                 AxisAlignedBB axisalignedbb1 = this.boundingBox.clone();
 
@@ -448,7 +452,7 @@ public abstract class Entity {
                 }
 
                 this.boundingBox.d(0.0D, d1, 0.0D);
-                if (!this.bc && d6 != d1) {
+                if (!this.bf && d6 != d1) {
                     d2 = 0.0D;
                     d1 = 0.0D;
                     d0 = 0.0D;
@@ -459,7 +463,7 @@ public abstract class Entity {
                 }
 
                 this.boundingBox.d(d0, 0.0D, 0.0D);
-                if (!this.bc && d5 != d0) {
+                if (!this.bf && d5 != d0) {
                     d2 = 0.0D;
                     d1 = 0.0D;
                     d0 = 0.0D;
@@ -470,29 +474,47 @@ public abstract class Entity {
                 }
 
                 this.boundingBox.d(0.0D, 0.0D, d2);
-                if (!this.bc && d7 != d2) {
+                if (!this.bf && d7 != d2) {
                     d2 = 0.0D;
                     d1 = 0.0D;
                     d0 = 0.0D;
                 }
 
+                if (!this.bf && d6 != d1) {
+                    d2 = 0.0D;
+                    d1 = 0.0D;
+                    d0 = 0.0D;
+                } else {
+                    d1 = (double) (-this.br);
+
+                    for (k = 0; k < list.size(); ++k) {
+                        d1 = ((AxisAlignedBB) list.get(k)).b(this.boundingBox, d1);
+                    }
+
+                    this.boundingBox.d(0.0D, d1, 0.0D);
+                }
+
                 if (d9 * d9 + d11 * d11 >= d0 * d0 + d2 * d2) {
                     d0 = d9;
                     d1 = d10;
                     d2 = d11;
                     this.boundingBox.b(axisalignedbb1);
                 } else {
-                    this.bn = (float) ((double) this.bn + 0.5D);
+                    double d12 = this.boundingBox.b - (double) ((int) this.boundingBox.b);
+
+                    if (d12 > 0.0D) {
+                        this.bq = (float) ((double) this.bq + d12 + 0.01D);
+                    }
                 }
             }
 
             this.locX = (this.boundingBox.a + this.boundingBox.d) / 2.0D;
-            this.locY = this.boundingBox.b + (double) this.height - (double) this.bn;
+            this.locY = this.boundingBox.b + (double) this.height - (double) this.bq;
             this.locZ = (this.boundingBox.c + this.boundingBox.f) / 2.0D;
             this.positionChanged = d5 != d0 || d7 != d2;
-            this.aY = d6 != d1;
+            this.bb = d6 != d1;
             this.onGround = d6 != d1 && d6 < 0.0D;
-            this.aZ = this.positionChanged || this.aY;
+            this.bc = this.positionChanged || this.bb;
             this.a(d1, this.onGround);
             if (d5 != d0) {
                 this.motX = 0.0D;
@@ -533,13 +555,17 @@ public abstract class Entity {
             }
             // CraftBukkit end
 
-            if (this.n() && !flag) {
-                this.bi = (float) ((double) this.bi + (double) MathHelper.a(d9 * d9 + d10 * d10) * 0.6D);
+            if (this.n() && !flag && this.vehicle == null) {
+                this.bl = (float) ((double) this.bl + (double) MathHelper.a(d9 * d9 + d10 * d10) * 0.6D);
                 l = MathHelper.floor(this.locX);
                 i1 = MathHelper.floor(this.locY - 0.20000000298023224D - (double) this.height);
                 j1 = MathHelper.floor(this.locZ);
                 k = this.world.getTypeId(l, i1, j1);
-                if (this.bi > (float) this.b && k > 0) {
+                if (this.world.getTypeId(l, i1 - 1, j1) == Block.FENCE.id) {
+                    k = this.world.getTypeId(l, i1 - 1, j1);
+                }
+
+                if (this.bl > (float) this.b && k > 0) {
                     ++this.b;
                     StepSound stepsound = Block.byId[k].stepSound;
 
@@ -554,12 +580,12 @@ public abstract class Entity {
                 }
             }
 
-            l = MathHelper.floor(this.boundingBox.a);
-            i1 = MathHelper.floor(this.boundingBox.b);
-            j1 = MathHelper.floor(this.boundingBox.c);
-            k = MathHelper.floor(this.boundingBox.d);
-            int k1 = MathHelper.floor(this.boundingBox.e);
-            int l1 = MathHelper.floor(this.boundingBox.f);
+            l = MathHelper.floor(this.boundingBox.a + 0.0010D);
+            i1 = MathHelper.floor(this.boundingBox.b + 0.0010D);
+            j1 = MathHelper.floor(this.boundingBox.c + 0.0010D);
+            k = MathHelper.floor(this.boundingBox.d - 0.0010D);
+            int k1 = MathHelper.floor(this.boundingBox.e - 0.0010D);
+            int l1 = MathHelper.floor(this.boundingBox.f - 0.0010D);
 
             if (this.world.a(l, i1, j1, k, k1, l1)) {
                 for (int i2 = l; i2 <= k; ++i2) {
@@ -575,10 +601,10 @@ public abstract class Entity {
                 }
             }
 
-            this.bn *= 0.4F;
-            boolean flag2 = this.Y();
+            this.bq *= 0.4F;
+            boolean flag2 = this.Z();
 
-            if (this.world.d(this.boundingBox)) {
+            if (this.world.d(this.boundingBox.shrink(0.0010D, 0.0010D, 0.0010D))) {
                 this.a(1);
                 if (!flag2) {
                     ++this.fireTicks;
@@ -630,7 +656,7 @@ public abstract class Entity {
     }
 
     protected void a(int i) {
-        if (!this.bz) {
+        if (!this.bC) {
             // CraftBukkit start
             if (this instanceof EntityLiving) {
                 CraftServer server = ((WorldServer) this.world).getServer();
@@ -652,18 +678,22 @@ public abstract class Entity {
         }
     }
 
-    protected void a(float f) {}
-
-    public boolean Y() {
-        return this.bw || this.world.q(MathHelper.floor(this.locX), MathHelper.floor(this.locY), MathHelper.floor(this.locZ));
+    protected void a(float f) {
+        if (this.passenger != null) {
+            this.passenger.a(f);
+        }
     }
 
     public boolean Z() {
-        return this.bw;
+        return this.bz || this.world.s(MathHelper.floor(this.locX), MathHelper.floor(this.locY), MathHelper.floor(this.locZ));
+    }
+
+    public boolean aa() {
+        return this.bz;
     }
 
     public boolean f_() {
-        return this.world.a(this.boundingBox.b(0.0D, -0.4000000059604645D, 0.0D), Material.WATER, this);
+        return this.world.a(this.boundingBox.b(0.0D, -0.4000000059604645D, 0.0D).shrink(0.0010D, 0.0010D, 0.0010D), Material.WATER, this);
     }
 
     public boolean a(Material material) {
@@ -687,7 +717,7 @@ public abstract class Entity {
         return 0.0F;
     }
 
-    public boolean aa() {
+    public boolean ab() {
         return this.world.a(this.boundingBox.b(-0.10000000149011612D, -0.4000000059604645D, -0.10000000149011612D), Material.LAVA);
     }
 
@@ -716,7 +746,11 @@ public abstract class Entity {
         int j = MathHelper.floor(this.locY - (double) this.height + d0);
         int k = MathHelper.floor(this.locZ);
 
-        return this.world.a(MathHelper.floor(this.boundingBox.a), MathHelper.floor(this.boundingBox.b), MathHelper.floor(this.boundingBox.c), MathHelper.floor(this.boundingBox.d), MathHelper.floor(this.boundingBox.e), MathHelper.floor(this.boundingBox.f)) ? this.world.l(i, j, k) : 0.0F;
+        return this.world.a(MathHelper.floor(this.boundingBox.a), MathHelper.floor(this.boundingBox.b), MathHelper.floor(this.boundingBox.c), MathHelper.floor(this.boundingBox.d), MathHelper.floor(this.boundingBox.e), MathHelper.floor(this.boundingBox.f)) ? this.world.m(i, j, k) : 0.0F;
+    }
+
+    public void a(World world) {
+        this.world = world;
     }
 
     public void setLocation(double d0, double d1, double d2, float f, float f1) {
@@ -725,7 +759,7 @@ public abstract class Entity {
         this.lastZ = this.locZ = d2;
         this.lastYaw = this.yaw = f;
         this.lastPitch = this.pitch = f1;
-        this.bn = 0.0F;
+        this.bq = 0.0F;
         double d3 = (double) (this.lastYaw - f);
 
         if (d3 < -180.0D) {
@@ -741,9 +775,9 @@ public abstract class Entity {
     }
 
     public void setPositionRotation(double d0, double d1, double d2, float f, float f1) {
-        this.bk = this.lastX = this.locX = d0;
-        this.bl = this.lastY = this.locY = d1 + (double) this.height;
-        this.bm = this.lastZ = this.locZ = d2;
+        this.bn = this.lastX = this.locX = d0;
+        this.bo = this.lastY = this.locY = d1 + (double) this.height;
+        this.bp = this.lastZ = this.locZ = d2;
         this.yaw = f;
         this.pitch = f1;
         this.setPosition(this.locX, this.locY, this.locZ);
@@ -803,8 +837,8 @@ public abstract class Entity {
                 d1 *= d3;
                 d0 *= 0.05000000074505806D;
                 d1 *= 0.05000000074505806D;
-                d0 *= (double) (1.0F - this.bq);
-                d1 *= (double) (1.0F - this.bq);
+                d0 *= (double) (1.0F - this.bt);
+                d1 *= (double) (1.0F - this.bt);
                 this.f(-d0, 0.0D, -d1);
                 entity.f(d0, 0.0D, d1);
             }
@@ -817,12 +851,12 @@ public abstract class Entity {
         this.motZ += d2;
     }
 
-    protected void ab() {
+    protected void ac() {
         this.velocityChanged = true;
     }
 
     public boolean damageEntity(Entity entity, int i) {
-        this.ab();
+        this.ac();
         return false;
     }
 
@@ -837,7 +871,7 @@ public abstract class Entity {
     public void c(Entity entity, int i) {}
 
     public boolean c(NBTTagCompound nbttagcompound) {
-        String s = this.ac();
+        String s = this.ad();
 
         if (!this.dead && s != null) {
             nbttagcompound.setString("id", s);
@@ -849,7 +883,7 @@ public abstract class Entity {
     }
 
     public void d(NBTTagCompound nbttagcompound) {
-        nbttagcompound.a("Pos", (NBTBase) this.a(new double[] { this.locX, this.locY, this.locZ}));
+        nbttagcompound.a("Pos", (NBTBase) this.a(new double[] { this.locX, this.locY + (double) this.height - (double) this.bq, this.locZ}));
         nbttagcompound.a("Motion", (NBTBase) this.a(new double[] { this.motX, this.motY, this.motZ}));
 
         // CraftBukkit start - checking for NaN pitch/yaw and resetting to zero
@@ -881,36 +915,29 @@ public abstract class Entity {
         this.motX = ((NBTTagDouble) nbttaglist1.a(0)).a;
         this.motY = ((NBTTagDouble) nbttaglist1.a(1)).a;
         this.motZ = ((NBTTagDouble) nbttaglist1.a(2)).a;
+        if (Math.abs(this.motX) > 10.0D) {
+            this.motX = 0.0D;
+        }
 
-        this.lastX = this.bk = this.locX = ((NBTTagDouble) nbttaglist.a(0)).a;
-        this.lastY = this.bl = this.locY = ((NBTTagDouble) nbttaglist.a(1)).a;
-        this.lastZ = this.bm = this.locZ = ((NBTTagDouble) nbttaglist.a(2)).a;
-        this.lastYaw = this.yaw = ((NBTTagFloat) nbttaglist2.a(0)).a % 6.2831855F;
-        this.lastPitch = this.pitch = ((NBTTagFloat) nbttaglist2.a(1)).a % 6.2831855F;
+        if (Math.abs(this.motY) > 10.0D) {
+            this.motY = 0.0D;
+        }
+
+        if (Math.abs(this.motZ) > 10.0D) {
+            this.motZ = 0.0D;
+        }
+
+        this.lastX = this.bn = this.locX = ((NBTTagDouble) nbttaglist.a(0)).a;
+        this.lastY = this.bo = this.locY = ((NBTTagDouble) nbttaglist.a(1)).a;
+        this.lastZ = this.bp = this.locZ = ((NBTTagDouble) nbttaglist.a(2)).a;
+        this.lastYaw = this.yaw = ((NBTTagFloat) nbttaglist2.a(0)).a;
+        this.lastPitch = this.pitch = ((NBTTagFloat) nbttaglist2.a(1)).a;
         this.fallDistance = nbttagcompound.g("FallDistance");
         this.fireTicks = nbttagcompound.d("Fire");
         this.airTicks = nbttagcompound.d("Air");
         this.onGround = nbttagcompound.m("OnGround");
-
-        // CraftBukkit start
-        if (nbttagcompound.hasKey("World")) {
-            String worldName = nbttagcompound.getString("World");
-
-            for (WorldServer world: ((WorldServer) this.world).getServer().getServer().worlds) {
-                if ((world.worldData.name.equals(worldName)) && (world != this.world)) {
-                    this.world = world;
-                    if (this instanceof EntityHuman) {
-                        EntityPlayer player = (EntityPlayer)this;
-                        player.itemInWorldManager = new ItemInWorldManager(world);
-                        player.itemInWorldManager.player = player;
-                    }
-                    break;
-                }
-            }
-        }
-        // CraftBukkit end
-
         this.setPosition(this.locX, this.locY, this.locZ);
+        this.c(this.yaw, this.pitch);
         this.a(nbttagcompound);
 
         // CraftBukkit start - Exempt Vehicles from notch's sanity check
@@ -930,7 +957,7 @@ public abstract class Entity {
         // CraftBukkit end
     }
 
-    protected final String ac() {
+    protected final String ad() {
         return EntityTypes.b(this);
     }
 
@@ -982,16 +1009,25 @@ public abstract class Entity {
         return entityitem;
     }
 
-    public boolean P() {
+    public boolean Q() {
         return !this.dead;
     }
 
     public boolean H() {
-        int i = MathHelper.floor(this.locX);
-        int j = MathHelper.floor(this.locY + (double) this.s());
-        int k = MathHelper.floor(this.locZ);
+        for (int i = 0; i < 8; ++i) {
+            float f = ((float) ((i >> 0) % 2) - 0.5F) * this.length * 0.9F;
+            float f1 = ((float) ((i >> 1) % 2) - 0.5F) * 0.1F;
+            float f2 = ((float) ((i >> 2) % 2) - 0.5F) * this.length * 0.9F;
+            int j = MathHelper.floor(this.locX + (double) f);
+            int k = MathHelper.floor(this.locY + (double) this.s() + (double) f1);
+            int l = MathHelper.floor(this.locZ + (double) f2);
 
-        return this.world.d(i, j, k);
+            if (this.world.d(j, k, l)) {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     public boolean a(EntityHuman entityhuman) {
@@ -1010,49 +1046,51 @@ public abstract class Entity {
             this.motY = 0.0D;
             this.motZ = 0.0D;
             this.p_();
-            this.vehicle.f();
-            this.e += (double) (this.vehicle.yaw - this.vehicle.lastYaw);
+            if (this.vehicle != null) {
+                this.vehicle.f();
+                this.e += (double) (this.vehicle.yaw - this.vehicle.lastYaw);
 
-            for (this.d += (double) (this.vehicle.pitch - this.vehicle.lastPitch); this.e >= 180.0D; this.e -= 360.0D) {
-                ;
+                for (this.d += (double) (this.vehicle.pitch - this.vehicle.lastPitch); this.e >= 180.0D; this.e -= 360.0D) {
+                    ;
+                }
+
+                while (this.e < -180.0D) {
+                    this.e += 360.0D;
+                }
+
+                while (this.d >= 180.0D) {
+                    this.d -= 360.0D;
+                }
+
+                while (this.d < -180.0D) {
+                    this.d += 360.0D;
+                }
+
+                double d0 = this.e * 0.5D;
+                double d1 = this.d * 0.5D;
+                float f = 10.0F;
+
+                if (d0 > (double) f) {
+                    d0 = (double) f;
+                }
+
+                if (d0 < (double) (-f)) {
+                    d0 = (double) (-f);
+                }
+
+                if (d1 > (double) f) {
+                    d1 = (double) f;
+                }
+
+                if (d1 < (double) (-f)) {
+                    d1 = (double) (-f);
+                }
+
+                this.e -= d0;
+                this.d -= d1;
+                this.yaw = (float) ((double) this.yaw + d0);
+                this.pitch = (float) ((double) this.pitch + d1);
             }
-
-            while (this.e < -180.0D) {
-                this.e += 360.0D;
-            }
-
-            while (this.d >= 180.0D) {
-                this.d -= 360.0D;
-            }
-
-            while (this.d < -180.0D) {
-                this.d += 360.0D;
-            }
-
-            double d0 = this.e * 0.5D;
-            double d1 = this.d * 0.5D;
-            float f = 10.0F;
-
-            if (d0 > (double) f) {
-                d0 = (double) f;
-            }
-
-            if (d0 < (double) (-f)) {
-                d0 = (double) (-f);
-            }
-
-            if (d1 > (double) f) {
-                d1 = (double) f;
-            }
-
-            if (d1 < (double) (-f)) {
-                d1 = (double) (-f);
-            }
-
-            this.e -= d0;
-            this.d -= d1;
-            this.yaw = (float) ((double) this.yaw + d0);
-            this.pitch = (float) ((double) this.pitch + d1);
         }
     }
 
@@ -1134,11 +1172,11 @@ public abstract class Entity {
         }
     }
 
-    public Vec3D V() {
+    public Vec3D W() {
         return null;
     }
 
-    public void ad() {}
+    public void M() {}
 
     public ItemStack[] getEquipment() {
         return null;
@@ -1187,4 +1225,94 @@ public abstract class Entity {
     }
 
     public void a(EntityLiving entityliving) {}
+
+    private boolean a(int i, int j, int k) {
+        int l = this.world.getTypeId(i, j, k);
+
+        if (l == 0) {
+            return false;
+        } else {
+            this.f.clear();
+            Block.byId[l].a(this.world, i, j, k, this.boundingBox, this.f);
+            return this.f.size() > 0;
+        }
+    }
+
+    protected boolean g(double d0, double d1, double d2) {
+        int i = MathHelper.floor(d0);
+        int j = MathHelper.floor(d1);
+        int k = MathHelper.floor(d2);
+        double d3 = d0 - (double) i;
+        double d4 = d1 - (double) j;
+        double d5 = d2 - (double) k;
+
+        if (this.a(i, j, k)) {
+            boolean flag = !this.a(i - 1, j, k);
+            boolean flag1 = !this.a(i + 1, j, k);
+            boolean flag2 = !this.a(i, j - 1, k);
+            boolean flag3 = !this.a(i, j + 1, k);
+            boolean flag4 = !this.a(i, j, k - 1);
+            boolean flag5 = !this.a(i, j, k + 1);
+            byte b0 = -1;
+            double d6 = 9999.0D;
+
+            if (flag && d3 < d6) {
+                d6 = d3;
+                b0 = 0;
+            }
+
+            if (flag1 && 1.0D - d3 < d6) {
+                d6 = 1.0D - d3;
+                b0 = 1;
+            }
+
+            if (flag2 && d4 < d6) {
+                d6 = d4;
+                b0 = 2;
+            }
+
+            if (flag3 && 1.0D - d4 < d6) {
+                d6 = 1.0D - d4;
+                b0 = 3;
+            }
+
+            if (flag4 && d5 < d6) {
+                d6 = d5;
+                b0 = 4;
+            }
+
+            if (flag5 && 1.0D - d5 < d6) {
+                d6 = 1.0D - d5;
+                b0 = 5;
+            }
+
+            float f = this.random.nextFloat() * 0.2F + 0.1F;
+
+            if (b0 == 0) {
+                this.motX = (double) (-f);
+            }
+
+            if (b0 == 1) {
+                this.motX = (double) f;
+            }
+
+            if (b0 == 2) {
+                this.motY = (double) (-f);
+            }
+
+            if (b0 == 3) {
+                this.motY = (double) f;
+            }
+
+            if (b0 == 4) {
+                this.motZ = (double) (-f);
+            }
+
+            if (b0 == 5) {
+                this.motZ = (double) f;
+            }
+        }
+
+        return false;
+    }
 }
diff --git a/src/main/java/net/minecraft/server/EntityArrow.java b/src/main/java/net/minecraft/server/EntityArrow.java
index f123c12d95..f5ab4028f7 100644
--- a/src/main/java/net/minecraft/server/EntityArrow.java
+++ b/src/main/java/net/minecraft/server/EntityArrow.java
@@ -11,15 +11,17 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
 
 public class EntityArrow extends Entity {
 
-    private int c = -1;
     private int d = -1;
     private int e = -1;
-    private int f = 0;
-    private boolean g = false;
-    public int a = 0;
+    private int f = -1;
+    private int g = 0;
+    private int h = 0;
+    private boolean i = false;
+    public boolean a = false;
+    public int b = 0;
     public EntityLiving shooter;
-    private int h;
-    private int i = 0;
+    private int j;
+    private int k = 0;
 
     public EntityArrow(World world) {
         super(world);
@@ -36,6 +38,7 @@ public class EntityArrow extends Entity {
     public EntityArrow(World world, EntityLiving entityliving) {
         super(world);
         this.shooter = entityliving;
+        this.a = entityliving instanceof EntityHuman;
         this.b(0.5F, 0.5F);
         this.setPositionRotation(entityliving.locX, entityliving.locY + (double) entityliving.s(), entityliving.locZ, entityliving.yaw, entityliving.pitch);
         this.locX -= (double) (MathHelper.cos(this.yaw / 180.0F * 3.1415927F) * 0.16F);
@@ -70,7 +73,7 @@ public class EntityArrow extends Entity {
 
         this.lastYaw = this.yaw = (float) (Math.atan2(d0, d2) * 180.0D / 3.1415927410125732D);
         this.lastPitch = this.pitch = (float) (Math.atan2(d1, (double) f3) * 180.0D / 3.1415927410125732D);
-        this.h = 0;
+        this.j = 0;
     }
 
     public void p_() {
@@ -82,196 +85,208 @@ public class EntityArrow extends Entity {
             this.lastPitch = this.pitch = (float) (Math.atan2(this.motY, (double) f) * 180.0D / 3.1415927410125732D);
         }
 
-        if (this.a > 0) {
-            --this.a;
-        }
+        int i = this.world.getTypeId(this.d, this.e, this.f);
 
-        if (this.g) {
-            int i = this.world.getTypeId(this.c, this.d, this.e);
-
-            if (i == this.f) {
-                ++this.h;
-                if (this.h == 1200) {
-                    this.die();
-                }
-
-                return;
-            }
-
-            this.g = false;
-            this.motX *= (double) (this.random.nextFloat() * 0.2F);
-            this.motY *= (double) (this.random.nextFloat() * 0.2F);
-            this.motZ *= (double) (this.random.nextFloat() * 0.2F);
-            this.h = 0;
-            this.i = 0;
-        } else {
-            ++this.i;
-        }
-
-        Vec3D vec3d = Vec3D.create(this.locX, this.locY, this.locZ);
-        Vec3D vec3d1 = Vec3D.create(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ);
-        MovingObjectPosition movingobjectposition = this.world.a(vec3d, vec3d1);
-
-        vec3d = Vec3D.create(this.locX, this.locY, this.locZ);
-        vec3d1 = Vec3D.create(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ);
-        if (movingobjectposition != null) {
-            vec3d1 = Vec3D.create(movingobjectposition.f.a, movingobjectposition.f.b, movingobjectposition.f.c);
-        }
-
-        Entity entity = null;
-        List list = this.world.b((Entity) this, this.boundingBox.a(this.motX, this.motY, this.motZ).b(1.0D, 1.0D, 1.0D));
-        double d0 = 0.0D;
-
-        float f1;
-
-        for (int j = 0; j < list.size(); ++j) {
-            Entity entity1 = (Entity) list.get(j);
-
-            if (entity1.o_() && (entity1 != this.shooter || this.i >= 5)) {
-                f1 = 0.3F;
-                AxisAlignedBB axisalignedbb = entity1.boundingBox.b((double) f1, (double) f1, (double) f1);
-                MovingObjectPosition movingobjectposition1 = axisalignedbb.a(vec3d, vec3d1);
-
-                if (movingobjectposition1 != null) {
-                    double d1 = vec3d.a(movingobjectposition1.f);
-
-                    if (d1 < d0 || d0 == 0.0D) {
-                        entity = entity1;
-                        d0 = d1;
-                    }
-                }
+        if (i > 0) {
+            Block.byId[i].a(this.world, this.d, this.e, this.f);
+            if (Block.byId[i].d(this.world, this.d, this.e, this.f).a(Vec3D.create(this.locX, this.locY, this.locZ))) {
+                this.i = true;
             }
         }
 
-        if (entity != null) {
-            movingobjectposition = new MovingObjectPosition(entity);
+        if (this.b > 0) {
+            --this.b;
         }
 
-        float f2;
+        if (this.i) {
+            i = this.world.getTypeId(this.d, this.e, this.f);
+            int j = this.world.getData(this.d, this.e, this.f);
 
-        if (movingobjectposition != null) {
-            if (movingobjectposition.entity != null) {
-                // CraftBukkit start
-                boolean stick;
-                if (entity instanceof EntityLiving) {
-                    CraftServer server = ((WorldServer) this.world).getServer();
-
-                    // TODO decide if we should create DamageCause.ARROW, DamageCause.PROJECTILE
-                    // or leave as DamageCause.ENTITY_ATTACK
-                    org.bukkit.entity.Entity shooter = (this.shooter == null) ? null : this.shooter.getBukkitEntity();
-                    org.bukkit.entity.Entity damagee = movingobjectposition.entity.getBukkitEntity();
-                    org.bukkit.entity.Entity projectile = this.getBukkitEntity();
-                    // TODO deal with arrows being fired from a non-entity
-                    DamageCause damageCause = EntityDamageEvent.DamageCause.ENTITY_ATTACK;
-                    int damage = 4;
-
-                    EntityDamageByProjectileEvent event = new EntityDamageByProjectileEvent(shooter, damagee, projectile, damageCause, damage);
-                    server.getPluginManager().callEvent(event);
-                    if (!event.isCancelled()) {
-                        // this function returns if the arrow should stick in or not, i.e. !bounce
-                        stick = movingobjectposition.entity.damageEntity(this.shooter, event.getDamage());
-                    } else {
-                        // event was cancelled, get if the arrow should bounce or not
-                        stick = !event.getBounce();
-                    }
-                } else {
-                    stick = movingobjectposition.entity.damageEntity(this.shooter, 4);
-                }
-                if (stick) {
-                // CraftBukkit end
-                    this.world.makeSound(this, "random.drr", 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F));
+            if (i == this.g && j == this.h) {
+                ++this.j;
+                if (this.j == 1200) {
                     this.die();
-                } else {
-                    this.motX *= -0.10000000149011612D;
-                    this.motY *= -0.10000000149011612D;
-                    this.motZ *= -0.10000000149011612D;
-                    this.yaw += 180.0F;
-                    this.lastYaw += 180.0F;
-                    this.i = 0;
                 }
             } else {
-                this.c = movingobjectposition.b;
-                this.d = movingobjectposition.c;
-                this.e = movingobjectposition.d;
-                this.f = this.world.getTypeId(this.c, this.d, this.e);
-                this.motX = (double) ((float) (movingobjectposition.f.a - this.locX));
-                this.motY = (double) ((float) (movingobjectposition.f.b - this.locY));
-                this.motZ = (double) ((float) (movingobjectposition.f.c - this.locZ));
-                f2 = MathHelper.a(this.motX * this.motX + this.motY * this.motY + this.motZ * this.motZ);
-                this.locX -= this.motX / (double) f2 * 0.05000000074505806D;
-                this.locY -= this.motY / (double) f2 * 0.05000000074505806D;
-                this.locZ -= this.motZ / (double) f2 * 0.05000000074505806D;
-                this.world.makeSound(this, "random.drr", 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F));
-                this.g = true;
-                this.a = 7;
+                this.i = false;
+                this.motX *= (double) (this.random.nextFloat() * 0.2F);
+                this.motY *= (double) (this.random.nextFloat() * 0.2F);
+                this.motZ *= (double) (this.random.nextFloat() * 0.2F);
+                this.j = 0;
+                this.k = 0;
             }
-        }
+        } else {
+            ++this.k;
+            Vec3D vec3d = Vec3D.create(this.locX, this.locY, this.locZ);
+            Vec3D vec3d1 = Vec3D.create(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ);
+            MovingObjectPosition movingobjectposition = this.world.rayTrace(vec3d, vec3d1, false, true);
 
-        this.locX += this.motX;
-        this.locY += this.motY;
-        this.locZ += this.motZ;
-        f2 = MathHelper.a(this.motX * this.motX + this.motZ * this.motZ);
-        this.yaw = (float) (Math.atan2(this.motX, this.motZ) * 180.0D / 3.1415927410125732D);
-
-        for (this.pitch = (float) (Math.atan2(this.motY, (double) f2) * 180.0D / 3.1415927410125732D); this.pitch - this.lastPitch < -180.0F; this.lastPitch -= 360.0F) {
-            ;
-        }
-
-        while (this.pitch - this.lastPitch >= 180.0F) {
-            this.lastPitch += 360.0F;
-        }
-
-        while (this.yaw - this.lastYaw < -180.0F) {
-            this.lastYaw -= 360.0F;
-        }
-
-        while (this.yaw - this.lastYaw >= 180.0F) {
-            this.lastYaw += 360.0F;
-        }
-
-        this.pitch = this.lastPitch + (this.pitch - this.lastPitch) * 0.2F;
-        this.yaw = this.lastYaw + (this.yaw - this.lastYaw) * 0.2F;
-        float f3 = 0.99F;
-
-        f1 = 0.03F;
-        if (this.Z()) {
-            for (int k = 0; k < 4; ++k) {
-                float f4 = 0.25F;
-
-                this.world.a("bubble", this.locX - this.motX * (double) f4, this.locY - this.motY * (double) f4, this.locZ - this.motZ * (double) f4, this.motX, this.motY, this.motZ);
+            vec3d = Vec3D.create(this.locX, this.locY, this.locZ);
+            vec3d1 = Vec3D.create(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ);
+            if (movingobjectposition != null) {
+                vec3d1 = Vec3D.create(movingobjectposition.f.a, movingobjectposition.f.b, movingobjectposition.f.c);
             }
 
-            f3 = 0.8F;
-        }
+            Entity entity = null;
+            List list = this.world.b((Entity) this, this.boundingBox.a(this.motX, this.motY, this.motZ).b(1.0D, 1.0D, 1.0D));
+            double d0 = 0.0D;
 
-        this.motX *= (double) f3;
-        this.motY *= (double) f3;
-        this.motZ *= (double) f3;
-        this.motY -= (double) f1;
-        this.setPosition(this.locX, this.locY, this.locZ);
+            float f1;
+
+            for (int k = 0; k < list.size(); ++k) {
+                Entity entity1 = (Entity) list.get(k);
+
+                if (entity1.o_() && (entity1 != this.shooter || this.k >= 5)) {
+                    f1 = 0.3F;
+                    AxisAlignedBB axisalignedbb = entity1.boundingBox.b((double) f1, (double) f1, (double) f1);
+                    MovingObjectPosition movingobjectposition1 = axisalignedbb.a(vec3d, vec3d1);
+
+                    if (movingobjectposition1 != null) {
+                        double d1 = vec3d.a(movingobjectposition1.f);
+
+                        if (d1 < d0 || d0 == 0.0D) {
+                            entity = entity1;
+                            d0 = d1;
+                        }
+                    }
+                }
+            }
+
+            if (entity != null) {
+                movingobjectposition = new MovingObjectPosition(entity);
+            }
+
+            float f2;
+
+            if (movingobjectposition != null) {
+                if (movingobjectposition.entity != null) {
+                    // CraftBukkit start
+                    boolean stick;
+                    if (entity instanceof EntityLiving) {
+                        CraftServer server = ((WorldServer) this.world).getServer();
+
+                        // TODO decide if we should create DamageCause.ARROW, DamageCause.PROJECTILE
+                        // or leave as DamageCause.ENTITY_ATTACK
+                        org.bukkit.entity.Entity shooter = (this.shooter == null) ? null : this.shooter.getBukkitEntity();
+                        org.bukkit.entity.Entity damagee = movingobjectposition.entity.getBukkitEntity();
+                        org.bukkit.entity.Entity projectile = this.getBukkitEntity();
+                        // TODO deal with arrows being fired from a non-entity
+                        DamageCause damageCause = EntityDamageEvent.DamageCause.ENTITY_ATTACK;
+                        int damage = 4;
+
+                        EntityDamageByProjectileEvent event = new EntityDamageByProjectileEvent(shooter, damagee, projectile, damageCause, damage);
+                        server.getPluginManager().callEvent(event);
+                        if (!event.isCancelled()) {
+                            // this function returns if the arrow should stick in or not, i.e. !bounce
+                            stick = movingobjectposition.entity.damageEntity(this.shooter, event.getDamage());
+                        } else {
+                            // event was cancelled, get if the arrow should bounce or not
+                            stick = !event.getBounce();
+                        }
+                    } else {
+                        stick = movingobjectposition.entity.damageEntity(this.shooter, 4);
+                    }
+                    if (stick) {
+                    // CraftBukkit end
+                        this.world.makeSound(this, "random.drr", 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F));
+                        this.die();
+                    } else {
+                        this.motX *= -0.10000000149011612D;
+                        this.motY *= -0.10000000149011612D;
+                        this.motZ *= -0.10000000149011612D;
+                        this.yaw += 180.0F;
+                        this.lastYaw += 180.0F;
+                        this.k = 0;
+                    }
+                } else {
+                    this.d = movingobjectposition.b;
+                    this.e = movingobjectposition.c;
+                    this.f = movingobjectposition.d;
+                    this.g = this.world.getTypeId(this.d, this.e, this.f);
+                    this.h = this.world.getData(this.d, this.e, this.f);
+                    this.motX = (double) ((float) (movingobjectposition.f.a - this.locX));
+                    this.motY = (double) ((float) (movingobjectposition.f.b - this.locY));
+                    this.motZ = (double) ((float) (movingobjectposition.f.c - this.locZ));
+                    f2 = MathHelper.a(this.motX * this.motX + this.motY * this.motY + this.motZ * this.motZ);
+                    this.locX -= this.motX / (double) f2 * 0.05000000074505806D;
+                    this.locY -= this.motY / (double) f2 * 0.05000000074505806D;
+                    this.locZ -= this.motZ / (double) f2 * 0.05000000074505806D;
+                    this.world.makeSound(this, "random.drr", 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F));
+                    this.i = true;
+                    this.b = 7;
+                }
+            }
+
+            this.locX += this.motX;
+            this.locY += this.motY;
+            this.locZ += this.motZ;
+            f2 = MathHelper.a(this.motX * this.motX + this.motZ * this.motZ);
+            this.yaw = (float) (Math.atan2(this.motX, this.motZ) * 180.0D / 3.1415927410125732D);
+
+            for (this.pitch = (float) (Math.atan2(this.motY, (double) f2) * 180.0D / 3.1415927410125732D); this.pitch - this.lastPitch < -180.0F; this.lastPitch -= 360.0F) {
+                ;
+            }
+
+            while (this.pitch - this.lastPitch >= 180.0F) {
+                this.lastPitch += 360.0F;
+            }
+
+            while (this.yaw - this.lastYaw < -180.0F) {
+                this.lastYaw -= 360.0F;
+            }
+
+            while (this.yaw - this.lastYaw >= 180.0F) {
+                this.lastYaw += 360.0F;
+            }
+
+            this.pitch = this.lastPitch + (this.pitch - this.lastPitch) * 0.2F;
+            this.yaw = this.lastYaw + (this.yaw - this.lastYaw) * 0.2F;
+            float f3 = 0.99F;
+
+            f1 = 0.03F;
+            if (this.aa()) {
+                for (int l = 0; l < 4; ++l) {
+                    float f4 = 0.25F;
+
+                    this.world.a("bubble", this.locX - this.motX * (double) f4, this.locY - this.motY * (double) f4, this.locZ - this.motZ * (double) f4, this.motX, this.motY, this.motZ);
+                }
+
+                f3 = 0.8F;
+            }
+
+            this.motX *= (double) f3;
+            this.motY *= (double) f3;
+            this.motZ *= (double) f3;
+            this.motY -= (double) f1;
+            this.setPosition(this.locX, this.locY, this.locZ);
+        }
     }
 
     public void b(NBTTagCompound nbttagcompound) {
-        nbttagcompound.a("xTile", (short) this.c);
-        nbttagcompound.a("yTile", (short) this.d);
-        nbttagcompound.a("zTile", (short) this.e);
-        nbttagcompound.a("inTile", (byte) this.f);
-        nbttagcompound.a("shake", (byte) this.a);
-        nbttagcompound.a("inGround", (byte) (this.g ? 1 : 0));
+        nbttagcompound.a("xTile", (short) this.d);
+        nbttagcompound.a("yTile", (short) this.e);
+        nbttagcompound.a("zTile", (short) this.f);
+        nbttagcompound.a("inTile", (byte) this.g);
+        nbttagcompound.a("inData", (byte) this.h);
+        nbttagcompound.a("shake", (byte) this.b);
+        nbttagcompound.a("inGround", (byte) (this.i ? 1 : 0));
+        nbttagcompound.a("player", this.a);
     }
 
     public void a(NBTTagCompound nbttagcompound) {
-        this.c = nbttagcompound.d("xTile");
-        this.d = nbttagcompound.d("yTile");
-        this.e = nbttagcompound.d("zTile");
-        this.f = nbttagcompound.c("inTile") & 255;
-        this.a = nbttagcompound.c("shake") & 255;
-        this.g = nbttagcompound.c("inGround") == 1;
+        this.d = nbttagcompound.d("xTile");
+        this.e = nbttagcompound.d("yTile");
+        this.f = nbttagcompound.d("zTile");
+        this.g = nbttagcompound.c("inTile") & 255;
+        this.h = nbttagcompound.c("inData") & 255;
+        this.b = nbttagcompound.c("shake") & 255;
+        this.i = nbttagcompound.c("inGround") == 1;
+        this.a = nbttagcompound.m("player");
     }
 
     public void b(EntityHuman entityhuman) {
         if (!this.world.isStatic) {
-            if (this.g && this.shooter == entityhuman && this.a <= 0 && entityhuman.inventory.canHold(new ItemStack(Item.ARROW, 1))) {
+            if (this.i && this.a && this.b <= 0 && entityhuman.inventory.canHold(new ItemStack(Item.ARROW, 1))) {
                 this.world.makeSound(this, "random.pop", 0.2F, ((this.random.nextFloat() - this.random.nextFloat()) * 0.7F + 1.0F) * 2.0F);
                 entityhuman.receive(this, 1);
                 this.die();
diff --git a/src/main/java/net/minecraft/server/EntityBoat.java b/src/main/java/net/minecraft/server/EntityBoat.java
index 26b16fa886..1b569cc53f 100644
--- a/src/main/java/net/minecraft/server/EntityBoat.java
+++ b/src/main/java/net/minecraft/server/EntityBoat.java
@@ -53,7 +53,7 @@ public class EntityBoat extends Entity {
         this.damage = 0;
         this.b = 0;
         this.c = 1;
-        this.aE = true;
+        this.aH = true;
         this.b(1.5F, 0.6F);
         this.height = this.width / 2.0F;
     }
@@ -116,7 +116,7 @@ public class EntityBoat extends Entity {
             this.c = -this.c;
             this.b = 10;
             this.damage += i * 10;
-            this.ab();
+            this.ac();
             if (this.damage > 40) {
 
                 // CraftBukkit start
@@ -226,29 +226,34 @@ public class EntityBoat extends Entity {
                 this.motZ *= 0.9900000095367432D;
             }
         } else {
-            d3 = d0 * 2.0D - 1.0D;
-            this.motY += 0.03999999910593033D * d3;
+            if (d0 < 1.0D) {
+                d3 = d0 * 2.0D - 1.0D;
+                this.motY += 0.03999999910593033D * d3;
+            } else {
+                this.motY += 0.0010000000474974513D;
+            }
+
             if (this.passenger != null) {
                 this.motX += this.passenger.motX * 0.2D;
                 this.motZ += this.passenger.motZ * 0.2D;
             }
 
             // CraftBukkit
-            d4 = this.maxSpeed;
-            if (this.motX < -d4) {
-                this.motX = -d4;
+            d3 = this.maxSpeed;
+            if (this.motX < -d3) {
+                this.motX = -d3;
             }
 
-            if (this.motX > d4) {
-                this.motX = d4;
+            if (this.motX > d3) {
+                this.motX = d3;
             }
 
-            if (this.motZ < -d4) {
-                this.motZ = -d4;
+            if (this.motZ < -d3) {
+                this.motZ = -d3;
             }
 
-            if (this.motZ > d4) {
-                this.motZ = d4;
+            if (this.motZ > d3) {
+                this.motZ = d3;
             }
 
             if (this.onGround) {
@@ -258,32 +263,30 @@ public class EntityBoat extends Entity {
             }
 
             this.move(this.motX, this.motY, this.motZ);
-            d5 = Math.sqrt(this.motX * this.motX + this.motZ * this.motZ);
-            double d7;
+            d4 = Math.sqrt(this.motX * this.motX + this.motZ * this.motZ);
+            if (d4 > 0.15D) {
+                d5 = Math.cos((double) this.yaw * 3.141592653589793D / 180.0D);
+                d6 = Math.sin((double) this.yaw * 3.141592653589793D / 180.0D);
 
-            if (d5 > 0.15D) {
-                d6 = Math.cos((double) this.yaw * 3.141592653589793D / 180.0D);
-                d7 = Math.sin((double) this.yaw * 3.141592653589793D / 180.0D);
-
-                for (int j = 0; (double) j < 1.0D + d5 * 60.0D; ++j) {
-                    double d8 = (double) (this.random.nextFloat() * 2.0F - 1.0F);
-                    double d9 = (double) (this.random.nextInt(2) * 2 - 1) * 0.7D;
+                for (int j = 0; (double) j < 1.0D + d4 * 60.0D; ++j) {
+                    double d7 = (double) (this.random.nextFloat() * 2.0F - 1.0F);
+                    double d8 = (double) (this.random.nextInt(2) * 2 - 1) * 0.7D;
+                    double d9;
                     double d10;
-                    double d11;
 
                     if (this.random.nextBoolean()) {
-                        d10 = this.locX - d6 * d8 * 0.8D + d7 * d9;
-                        d11 = this.locZ - d7 * d8 * 0.8D - d6 * d9;
-                        this.world.a("splash", d10, this.locY - 0.125D, d11, this.motX, this.motY, this.motZ);
+                        d9 = this.locX - d5 * d7 * 0.8D + d6 * d8;
+                        d10 = this.locZ - d6 * d7 * 0.8D - d5 * d8;
+                        this.world.a("splash", d9, this.locY - 0.125D, d10, this.motX, this.motY, this.motZ);
                     } else {
-                        d10 = this.locX + d6 + d7 * d8 * 0.7D;
-                        d11 = this.locZ + d7 - d6 * d8 * 0.7D;
-                        this.world.a("splash", d10, this.locY - 0.125D, d11, this.motX, this.motY, this.motZ);
+                        d9 = this.locX + d5 + d6 * d7 * 0.7D;
+                        d10 = this.locZ + d6 - d5 * d7 * 0.7D;
+                        this.world.a("splash", d9, this.locY - 0.125D, d10, this.motX, this.motY, this.motZ);
                     }
                 }
             }
 
-            if (this.positionChanged && d5 > 0.15D) {
+            if (this.positionChanged && d4 > 0.15D) {
                 if (!this.world.isStatic) {
                     this.die();
 
@@ -304,33 +307,33 @@ public class EntityBoat extends Entity {
             }
 
             this.pitch = 0.0F;
-            d6 = (double) this.yaw;
-            d7 = this.lastX - this.locX;
-            double d12 = this.lastZ - this.locZ;
+            d5 = (double) this.yaw;
+            d6 = this.lastX - this.locX;
+            double d11 = this.lastZ - this.locZ;
 
-            if (d7 * d7 + d12 * d12 > 0.0010D) {
-                d6 = (double) ((float) (Math.atan2(d12, d7) * 180.0D / 3.141592653589793D));
+            if (d6 * d6 + d11 * d11 > 0.0010D) {
+                d5 = (double) ((float) (Math.atan2(d11, d6) * 180.0D / 3.141592653589793D));
             }
 
-            double d13;
+            double d12;
 
-            for (d13 = d6 - (double) this.yaw; d13 >= 180.0D; d13 -= 360.0D) {
+            for (d12 = d5 - (double) this.yaw; d12 >= 180.0D; d12 -= 360.0D) {
                 ;
             }
 
-            while (d13 < -180.0D) {
-                d13 += 360.0D;
+            while (d12 < -180.0D) {
+                d12 += 360.0D;
             }
 
-            if (d13 > 20.0D) {
-                d13 = 20.0D;
+            if (d12 > 20.0D) {
+                d12 = 20.0D;
             }
 
-            if (d13 < -20.0D) {
-                d13 = -20.0D;
+            if (d12 < -20.0D) {
+                d12 = -20.0D;
             }
 
-            this.yaw = (float) ((double) this.yaw + d13);
+            this.yaw = (float) ((double) this.yaw + d12);
             this.c(this.yaw, this.pitch);
 
             // CraftBukkit start
@@ -349,9 +352,10 @@ public class EntityBoat extends Entity {
             // CraftBukkit end
 
             List list = this.world.b((Entity) this, this.boundingBox.b(0.20000000298023224D, 0.0D, 0.20000000298023224D));
+            int l;
 
             if (list != null && list.size() > 0) {
-                for (int l = 0; l < list.size(); ++l) {
+                for (l = 0; l < list.size(); ++l) {
                     Entity entity = (Entity) list.get(l);
 
                     if (entity != this.passenger && entity.d_() && entity instanceof EntityBoat) {
@@ -360,6 +364,16 @@ public class EntityBoat extends Entity {
                 }
             }
 
+            for (l = 0; l < 4; ++l) {
+                int i1 = MathHelper.floor(this.locX + ((double) (l % 2) - 0.5D) * 0.8D);
+                int j1 = MathHelper.floor(this.locY);
+                int k1 = MathHelper.floor(this.locZ + ((double) (l / 2) - 0.5D) * 0.8D);
+
+                if (this.world.getTypeId(i1, j1, k1) == Block.SNOW.id) {
+                    this.world.setTypeId(i1, j1, k1, 0);
+                }
+            }
+
             if (this.passenger != null && this.passenger.dead) {
                 this.passenger = null;
             }
diff --git a/src/main/java/net/minecraft/server/EntityCreature.java b/src/main/java/net/minecraft/server/EntityCreature.java
index b08d6b6ae0..6c4f896915 100644
--- a/src/main/java/net/minecraft/server/EntityCreature.java
+++ b/src/main/java/net/minecraft/server/EntityCreature.java
@@ -47,7 +47,7 @@ public class EntityCreature extends EntityLiving {
             if (this.target != null) {
                 this.pathEntity = this.world.findPath(this, this.target, f);
             }
-        } else if (!this.target.P()) {
+        } else if (!this.target.Q()) {
             // CraftBukkit start
             EntityTargetEvent event = new EntityTargetEvent(this.getBukkitEntity(), null, TargetReason.TARGET_DIED);
             CraftServer server = ((WorldServer) this.world).getServer();
@@ -66,6 +66,8 @@ public class EntityCreature extends EntityLiving {
 
             if (this.e(this.target)) {
                 this.a(this.target, f1);
+            } else {
+                this.b(this.target, f1);
             }
         }
 
@@ -99,8 +101,8 @@ public class EntityCreature extends EntityLiving {
         }
 
         int l1 = MathHelper.floor(this.boundingBox.b + 0.5D);
-        boolean flag1 = this.Z();
-        boolean flag2 = this.aa();
+        boolean flag1 = this.aa();
+        boolean flag2 = this.ab();
 
         this.pitch = 0.0F;
         if (this.pathEntity != null && this.random.nextInt(100) != 0) {
@@ -117,7 +119,7 @@ public class EntityCreature extends EntityLiving {
                 }
             }
 
-            this.ay = false;
+            this.aB = false;
             if (vec3d != null) {
                 double d1 = vec3d.a - this.locX;
                 double d2 = vec3d.c - this.locZ;
@@ -126,7 +128,7 @@ public class EntityCreature extends EntityLiving {
                 float f4 = (float) (TrigMath.atan2(d2, d1) * 180.0D / 3.1415927410125732D) - 90.0F;
                 float f5 = f4 - this.yaw;
 
-                for (this.aw = this.aA; f5 < -180.0F; f5 += 360.0F) {
+                for (this.az = this.aD; f5 < -180.0F; f5 += 360.0F) {
                     ;
                 }
 
@@ -150,12 +152,12 @@ public class EntityCreature extends EntityLiving {
 
                     this.yaw = (float) (Math.atan2(d5, d4) * 180.0D / 3.1415927410125732D) - 90.0F;
                     f5 = (f6 - this.yaw + 90.0F) * 3.1415927F / 180.0F;
-                    this.av = -MathHelper.sin(f5) * this.aw * 1.0F;
-                    this.aw = MathHelper.cos(f5) * this.aw * 1.0F;
+                    this.ay = -MathHelper.sin(f5) * this.az * 1.0F;
+                    this.az = MathHelper.cos(f5) * this.az * 1.0F;
                 }
 
                 if (d3 > 0.0D) {
-                    this.ay = true;
+                    this.aB = true;
                 }
             }
 
@@ -164,11 +166,11 @@ public class EntityCreature extends EntityLiving {
             }
 
             if (this.positionChanged && !this.C()) {
-                this.ay = true;
+                this.aB = true;
             }
 
             if (this.random.nextFloat() < 0.8F && (flag1 || flag2)) {
-                this.ay = true;
+                this.aB = true;
             }
         } else {
             super.c_();
@@ -178,6 +180,8 @@ public class EntityCreature extends EntityLiving {
 
     protected void a(Entity entity, float f) {}
 
+    protected void b(Entity entity, float f) {}
+
     protected float a(int i, int j, int k) {
         return 0.0F;
     }
diff --git a/src/main/java/net/minecraft/server/EntityCreeper.java b/src/main/java/net/minecraft/server/EntityCreeper.java
index d42c4599e5..f3d9f1c60e 100644
--- a/src/main/java/net/minecraft/server/EntityCreeper.java
+++ b/src/main/java/net/minecraft/server/EntityCreeper.java
@@ -35,6 +35,16 @@ public class EntityCreeper extends EntityMonster {
         this.datawatcher.b(17, Byte.valueOf((byte) (nbttagcompound.m("powered") ? 1 : 0)));
     }
 
+    protected void b(Entity entity, float f) {
+        if (this.fuseTicks > 0) {
+            this.e(-1);
+            --this.fuseTicks;
+            if (this.fuseTicks < 0) {
+                this.fuseTicks = 0;
+            }
+        }
+    }
+
     public void p_() {
         this.b = this.fuseTicks;
         if (this.world.isStatic) {
@@ -55,6 +65,13 @@ public class EntityCreeper extends EntityMonster {
         }
 
         super.p_();
+        if (this.target == null && this.fuseTicks > 0) {
+            this.e(-1);
+            --this.fuseTicks;
+            if (this.fuseTicks < 0) {
+                this.fuseTicks = 0;
+            }
+        }
     }
 
     protected String h() {
@@ -92,7 +109,8 @@ public class EntityCreeper extends EntityMonster {
                 // CraftBukkit start
                 CraftServer server = ((WorldServer) this.world).getServer();
 
-                ExplosionPrimeEvent event = new ExplosionPrimeEvent(CraftEntity.getEntity(server, this), 3.0F, false);
+                float radius = this.t() ? 6.0F : 3.0F;
+                ExplosionPrimeEvent event = new ExplosionPrimeEvent(CraftEntity.getEntity(server, this), radius, false);
                 server.getPluginManager().callEvent(event);
 
                 if (!event.isCancelled()) {
@@ -126,6 +144,7 @@ public class EntityCreeper extends EntityMonster {
 
     public void a(EntityWeatherStorm entityweatherstorm) {
         super.a(entityweatherstorm);
+
         // CraftBukkit start
         CraftServer server = ((WorldServer) this.world).getServer();
         org.bukkit.entity.Entity entity = this.getBukkitEntity();
@@ -133,9 +152,11 @@ public class EntityCreeper extends EntityMonster {
         CreeperPowerEvent event = new CreeperPowerEvent(entity, entityweatherstorm.getBukkitEntity(), CreeperPowerEvent.PowerCause.LIGHTNING);
         server.getPluginManager().callEvent(event);
 
-        if (!event.isCancelled()) {
-            this.datawatcher.b(17, Byte.valueOf((byte) 1));
+        if (event.isCancelled()) {
+            return;
         }
         // CraftBukkit end
+
+        this.datawatcher.b(17, Byte.valueOf((byte) 1));
     }
 }
diff --git a/src/main/java/net/minecraft/server/EntityEgg.java b/src/main/java/net/minecraft/server/EntityEgg.java
index 97f61996d9..0ea46f0631 100644
--- a/src/main/java/net/minecraft/server/EntityEgg.java
+++ b/src/main/java/net/minecraft/server/EntityEgg.java
@@ -81,9 +81,9 @@ public class EntityEgg extends Entity {
     }
 
     public void p_() {
-        this.bk = this.locX;
-        this.bl = this.locY;
-        this.bm = this.locZ;
+        this.bn = this.locX;
+        this.bo = this.locY;
+        this.bp = this.locZ;
         super.p_();
         if (this.a > 0) {
             --this.a;
@@ -301,7 +301,7 @@ public class EntityEgg extends Entity {
         float f2 = 0.99F;
         float f3 = 0.03F;
 
-        if (this.Z()) {
+        if (this.aa()) {
             for (int i1 = 0; i1 < 4; ++i1) {
                 float f4 = 0.25F;
 
diff --git a/src/main/java/net/minecraft/server/EntityFireball.java b/src/main/java/net/minecraft/server/EntityFireball.java
index 108a177cc0..b2d4b52230 100644
--- a/src/main/java/net/minecraft/server/EntityFireball.java
+++ b/src/main/java/net/minecraft/server/EntityFireball.java
@@ -13,18 +13,18 @@ import org.bukkit.event.entity.ExplosionPrimeEvent;
 
 public class EntityFireball extends Entity {
 
-    private int e = -1;
     private int f = -1;
     private int g = -1;
-    private int h = 0;
-    private boolean i = false;
+    private int h = -1;
+    private int i = 0;
+    private boolean j = false;
     public int a = 0;
-    private EntityLiving shooter;
+    public EntityLiving shooter;
     private int k;
     private int l = 0;
-    public double b;
     public double c;
     public double d;
+    public double e;
 
     public EntityFireball(World world) {
         super(world);
@@ -46,9 +46,9 @@ public class EntityFireball extends Entity {
         d2 += this.random.nextGaussian() * 0.4D;
         double d3 = (double) MathHelper.a(d0 * d0 + d1 * d1 + d2 * d2);
 
-        this.b = d0 / d3 * 0.1D;
-        this.c = d1 / d3 * 0.1D;
-        this.d = d2 / d3 * 0.1D;
+        this.c = d0 / d3 * 0.1D;
+        this.d = d1 / d3 * 0.1D;
+        this.e = d2 / d3 * 0.1D;
     }
 
     public void p_() {
@@ -58,10 +58,10 @@ public class EntityFireball extends Entity {
             --this.a;
         }
 
-        if (this.i) {
-            int i = this.world.getTypeId(this.e, this.f, this.g);
+        if (this.j) {
+            int i = this.world.getTypeId(this.f, this.g, this.h);
 
-            if (i == this.h) {
+            if (i == this.i) {
                 ++this.k;
                 if (this.k == 1200) {
                     this.die();
@@ -70,7 +70,7 @@ public class EntityFireball extends Entity {
                 return;
             }
 
-            this.i = false;
+            this.j = false;
             this.motX *= (double) (this.random.nextFloat() * 0.2F);
             this.motY *= (double) (this.random.nextFloat() * 0.2F);
             this.motZ *= (double) (this.random.nextFloat() * 0.2F);
@@ -118,35 +118,36 @@ public class EntityFireball extends Entity {
         }
 
         if (movingobjectposition != null) {
-            // CraftBukkit start
-            if (movingobjectposition.entity != null) {
-                boolean stick;
-                if (movingobjectposition.entity instanceof EntityLiving) {
-                    CraftServer server = ((WorldServer) this.world).getServer();
-                    org.bukkit.entity.Entity shooter = (this.shooter == null) ? null : this.shooter.getBukkitEntity();
-                    org.bukkit.entity.Entity damagee = movingobjectposition.entity.getBukkitEntity();
-                    org.bukkit.entity.Entity projectile = this.getBukkitEntity();
-                    DamageCause damageCause = EntityDamageEvent.DamageCause.ENTITY_ATTACK;
-                    int damage = 0;
+            if (!this.world.isStatic) {
+                // CraftBukkit start
+                if (movingobjectposition.entity != null) {
+                    boolean stick;
+                    if (movingobjectposition.entity instanceof EntityLiving) {
+                        CraftServer server = ((WorldServer) this.world).getServer();
+                        org.bukkit.entity.Entity shooter = (this.shooter == null) ? null : this.shooter.getBukkitEntity();
+                        org.bukkit.entity.Entity damagee = movingobjectposition.entity.getBukkitEntity();
+                        org.bukkit.entity.Entity projectile = this.getBukkitEntity();
+                        DamageCause damageCause = EntityDamageEvent.DamageCause.ENTITY_ATTACK;
+                        int damage = 0;
 
-                    // TODO @see EntityArrow#162
-                    EntityDamageByProjectileEvent event = new EntityDamageByProjectileEvent(shooter, damagee, projectile, damageCause, damage);
-                    server.getPluginManager().callEvent(event);
+                        // TODO @see EntityArrow#162
+                        EntityDamageByProjectileEvent event = new EntityDamageByProjectileEvent(shooter, damagee, projectile, damageCause, damage);
+                        server.getPluginManager().callEvent(event);
 
-                    if (!event.isCancelled()) {
-                        // this function returns if the fireball should stick or not, i.e. !bounce
-                        stick = movingobjectposition.entity.damageEntity(this.shooter, event.getDamage());
+                        if (!event.isCancelled()) {
+                            // this function returns if the fireball should stick or not, i.e. !bounce
+                            stick = movingobjectposition.entity.damageEntity(this.shooter, event.getDamage());
+                        } else {
+                            // event was cancelled, get if the fireball should bounce or not
+                            stick = !event.getBounce();
+                        }
                     } else {
-                        // event was cancelled, get if the fireball should bounce or not
-                        stick = !event.getBounce();
+                        stick = movingobjectposition.entity.damageEntity(this.shooter, 0);
+                    }
+                    if (stick) {
+                        ;
                     }
-                } else {
-                    stick = movingobjectposition.entity.damageEntity(this.shooter, 0);
                 }
-                if (stick) {
-                    ;
-                }
-            }
 
             CraftServer server = ((WorldServer) this.world).getServer();
 
@@ -158,6 +159,9 @@ public class EntityFireball extends Entity {
                 this.die();
             }
             // CraftBukkit end
+            }
+
+            // this.die() // # CraftBukkit
         }
 
         this.locX += this.motX;
@@ -187,7 +191,7 @@ public class EntityFireball extends Entity {
         this.yaw = this.lastYaw + (this.yaw - this.lastYaw) * 0.2F;
         float f2 = 0.95F;
 
-        if (this.Z()) {
+        if (this.aa()) {
             for (int k = 0; k < 4; ++k) {
                 float f3 = 0.25F;
 
@@ -197,9 +201,9 @@ public class EntityFireball extends Entity {
             f2 = 0.8F;
         }
 
-        this.motX += this.b;
-        this.motY += this.c;
-        this.motZ += this.d;
+        this.motX += this.c;
+        this.motY += this.d;
+        this.motZ += this.e;
         this.motX *= (double) f2;
         this.motY *= (double) f2;
         this.motZ *= (double) f2;
@@ -208,21 +212,21 @@ public class EntityFireball extends Entity {
     }
 
     public void b(NBTTagCompound nbttagcompound) {
-        nbttagcompound.a("xTile", (short) this.e);
-        nbttagcompound.a("yTile", (short) this.f);
-        nbttagcompound.a("zTile", (short) this.g);
-        nbttagcompound.a("inTile", (byte) this.h);
+        nbttagcompound.a("xTile", (short) this.f);
+        nbttagcompound.a("yTile", (short) this.g);
+        nbttagcompound.a("zTile", (short) this.h);
+        nbttagcompound.a("inTile", (byte) this.i);
         nbttagcompound.a("shake", (byte) this.a);
-        nbttagcompound.a("inGround", (byte) (this.i ? 1 : 0));
+        nbttagcompound.a("inGround", (byte) (this.j ? 1 : 0));
     }
 
     public void a(NBTTagCompound nbttagcompound) {
-        this.e = nbttagcompound.d("xTile");
-        this.f = nbttagcompound.d("yTile");
-        this.g = nbttagcompound.d("zTile");
-        this.h = nbttagcompound.c("inTile") & 255;
+        this.f = nbttagcompound.d("xTile");
+        this.g = nbttagcompound.d("yTile");
+        this.h = nbttagcompound.d("zTile");
+        this.i = nbttagcompound.c("inTile") & 255;
         this.a = nbttagcompound.c("shake") & 255;
-        this.i = nbttagcompound.c("inGround") == 1;
+        this.j = nbttagcompound.c("inGround") == 1;
     }
 
     public boolean o_() {
@@ -230,17 +234,17 @@ public class EntityFireball extends Entity {
     }
 
     public boolean damageEntity(Entity entity, int i) {
-        this.ab();
+        this.ac();
         if (entity != null) {
-            Vec3D vec3d = entity.V();
+            Vec3D vec3d = entity.W();
 
             if (vec3d != null) {
                 this.motX = vec3d.a;
                 this.motY = vec3d.b;
                 this.motZ = vec3d.c;
-                this.b = this.motX * 0.1D;
-                this.c = this.motY * 0.1D;
-                this.d = this.motZ * 0.1D;
+                this.c = this.motX * 0.1D;
+                this.d = this.motY * 0.1D;
+                this.e = this.motZ * 0.1D;
             }
 
             return true;
diff --git a/src/main/java/net/minecraft/server/EntityFish.java b/src/main/java/net/minecraft/server/EntityFish.java
index 76ac38bf67..49467eaf7d 100644
--- a/src/main/java/net/minecraft/server/EntityFish.java
+++ b/src/main/java/net/minecraft/server/EntityFish.java
@@ -32,12 +32,12 @@ public class EntityFish extends Entity {
     public EntityFish(World world) {
         super(world);
         this.b(0.25F, 0.25F);
+        this.bI = true;
     }
 
-    protected void b() {}
-
     public EntityFish(World world, EntityHuman entityhuman) {
         super(world);
+        this.bI = true;
         this.owner = entityhuman;
         this.owner.hookedFish = this;
         this.b(0.25F, 0.25F);
@@ -55,6 +55,8 @@ public class EntityFish extends Entity {
         this.a(this.motX, this.motY, this.motZ, 1.5F, 1.0F);
     }
 
+    protected void b() {}
+
     public void a(double d0, double d1, double d2, float f, float f1) {
         float f2 = MathHelper.a(d0 * d0 + d1 * d1 + d2 * d2);
 
@@ -103,7 +105,7 @@ public class EntityFish extends Entity {
             if (!this.world.isStatic) {
                 ItemStack itemstack = this.owner.D();
 
-                if (this.owner.dead || !this.owner.P() || itemstack == null || itemstack.getItem() != Item.FISHING_ROD || this.g(this.owner) > 1024.0D) {
+                if (this.owner.dead || !this.owner.Q() || itemstack == null || itemstack.getItem() != Item.FISHING_ROD || this.g(this.owner) > 1024.0D) {
                     this.die();
                     this.owner.hookedFish = null;
                     return;
@@ -270,7 +272,7 @@ public class EntityFish extends Entity {
                     } else {
                         short short1 = 500;
 
-                        if (this.world.q(MathHelper.floor(this.locX), MathHelper.floor(this.locY) + 1, MathHelper.floor(this.locZ))) {
+                        if (this.world.s(MathHelper.floor(this.locX), MathHelper.floor(this.locY) + 1, MathHelper.floor(this.locZ))) {
                             short1 = 300;
                         }
 
diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java
index af4d72c496..825c165b1a 100644
--- a/src/main/java/net/minecraft/server/EntityHuman.java
+++ b/src/main/java/net/minecraft/server/EntityHuman.java
@@ -45,6 +45,9 @@ public abstract class EntityHuman extends EntityLiving {
     public float B;
     private ChunkCoordinates c;
     private ChunkCoordinates d;
+    public int C = 20;
+    protected boolean D = false;
+    public float E;
     private int e = 0;
     public EntityFish hookedFish = null;
 
@@ -57,8 +60,8 @@ public abstract class EntityHuman extends EntityLiving {
 
         this.setPositionRotation((double) chunkcoordinates.x + 0.5D, (double) (chunkcoordinates.y + 1), (double) chunkcoordinates.z + 0.5D, 0.0F, 0.0F);
         this.health = 20;
-        this.Q = "humanoid";
-        this.P = 180.0F;
+        this.T = "humanoid";
+        this.S = 180.0F;
         this.maxFireTicks = 20;
         this.texture = "/mob/char.png";
     }
@@ -150,13 +153,13 @@ public abstract class EntityHuman extends EntityLiving {
         super.B();
         this.n = this.o;
         this.o = 0.0F;
-        this.h(this.locX - d0, this.locY - d1, this.locZ - d2);
+        this.i(this.locX - d0, this.locY - d1, this.locZ - d2);
     }
 
     protected void c_() {
         if (this.p) {
             ++this.q;
-            if (this.q == 8) {
+            if (this.q >= 8) {
                 this.q = 0;
                 this.p = false;
             }
@@ -164,7 +167,7 @@ public abstract class EntityHuman extends EntityLiving {
             this.q = 0;
         }
 
-        this.W = (float) this.q / 8.0F;
+        this.Z = (float) this.q / 8.0F;
     }
 
     public void u() {
@@ -192,7 +195,7 @@ public abstract class EntityHuman extends EntityLiving {
         }
 
         this.o += (f - this.o) * 0.4F;
-        this.af += (f1 - this.af) * 0.8F;
+        this.ai += (f1 - this.ai) * 0.8F;
         if (this.health > 0) {
             List list = this.world.b((Entity) this, this.boundingBox.b(1.0D, 0.0D, 1.0D));
 
@@ -223,8 +226,8 @@ public abstract class EntityHuman extends EntityLiving {
 
         this.inventory.h();
         if (entity != null) {
-            this.motX = (double) (-MathHelper.cos((this.ab + this.yaw) * 3.1415927F / 180.0F) * 0.1F);
-            this.motZ = (double) (-MathHelper.sin((this.ab + this.yaw) * 3.1415927F / 180.0F) * 0.1F);
+            this.motX = (double) (-MathHelper.cos((this.ae + this.yaw) * 3.1415927F / 180.0F) * 0.1F);
+            this.motZ = (double) (-MathHelper.sin((this.ae + this.yaw) * 3.1415927F / 180.0F) * 0.1F);
         } else {
             this.motX = this.motZ = 0.0D;
         }
@@ -368,7 +371,7 @@ public abstract class EntityHuman extends EntityLiving {
     }
 
     public boolean damageEntity(Entity entity, int i) {
-        this.au = 0;
+        this.ax = 0;
         if (this.health <= 0) {
             return false;
         } else {
@@ -395,9 +398,13 @@ public abstract class EntityHuman extends EntityLiving {
             } else {
                 Object object = entity;
 
-                // CraftBukkit start - this is here instead of EntityMonster because EntityLiving(s) that aren't monsters
-                // also damage the player in this way. For example, EntitySlime.
+                if (entity instanceof EntityArrow && ((EntityArrow) entity).shooter != null) {
+                    object = ((EntityArrow) entity).shooter;
+                }
+
                 if (object instanceof EntityLiving) {
+                    // CraftBukkit start - this is here instead of EntityMonster because EntityLiving(s) that aren't monsters
+                    // also damage the player in this way. For example, EntitySlime.
                     CraftServer server = ((WorldServer) this.world).getServer();
                     org.bukkit.entity.Entity damager = ((Entity) object).getBukkitEntity();
                     org.bukkit.entity.Entity damagee = this.getBukkitEntity();
@@ -537,7 +544,7 @@ public abstract class EntityHuman extends EntityLiving {
             }
 
             if (entity instanceof EntityLiving) {
-                if (entity.P()) {
+                if (entity.Q()) {
                     this.a((EntityLiving) entity, true);
                 }
 
@@ -561,7 +568,7 @@ public abstract class EntityHuman extends EntityLiving {
     }
 
     public EnumBedError a(int i, int j, int k) {
-        if (!this.isSleeping() && this.P()) {
+        if (!this.isSleeping() && this.Q()) {
             if (this.world.worldProvider.c) {
                 return EnumBedError.NOT_POSSIBLE_HERE;
             } else if (this.world.d()) {
@@ -658,7 +665,7 @@ public abstract class EntityHuman extends EntityLiving {
 
         if (chunkcoordinates != null && this.world.getTypeId(chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z) == Block.BED.id) {
             BlockBed.a(this.world, chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z, false);
-            chunkcoordinates1 = BlockBed.f(this.world, chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z, 0);
+            chunkcoordinates1 = BlockBed.g(this.world, chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z, 0);
             if (chunkcoordinates1 == null) {
                 chunkcoordinates1 = new ChunkCoordinates(chunkcoordinates.x, chunkcoordinates.y + 1, chunkcoordinates.z);
             }
@@ -713,7 +720,7 @@ public abstract class EntityHuman extends EntityLiving {
         if (world.getTypeId(chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z) != Block.BED.id) {
             return null;
         } else {
-            ChunkCoordinates chunkcoordinates1 = BlockBed.f(world, chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z, 0);
+            ChunkCoordinates chunkcoordinates1 = BlockBed.g(world, chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z, 0);
 
             return chunkcoordinates1;
         }
@@ -758,10 +765,10 @@ public abstract class EntityHuman extends EntityLiving {
         double d2 = this.locZ;
 
         super.a(f, f1);
-        this.g(this.locX - d0, this.locY - d1, this.locZ - d2);
+        this.h(this.locX - d0, this.locY - d1, this.locZ - d2);
     }
 
-    private void g(double d0, double d1, double d2) {
+    private void h(double d0, double d1, double d2) {
         if (this.vehicle == null) {
             int i;
 
@@ -770,7 +777,7 @@ public abstract class EntityHuman extends EntityLiving {
                 if (i > 0) {
                     this.a(StatisticList.q, i);
                 }
-            } else if (this.Z()) {
+            } else if (this.aa()) {
                 i = Math.round(MathHelper.a(d0 * d0 + d2 * d2) * 100.0F);
                 if (i > 0) {
                     this.a(StatisticList.m, i);
@@ -793,7 +800,7 @@ public abstract class EntityHuman extends EntityLiving {
         }
     }
 
-    private void h(double d0, double d1, double d2) {
+    private void i(double d0, double d1, double d2) {
         if (this.vehicle != null) {
             int i = Math.round(MathHelper.a(d0 * d0 + d1 * d1 + d2 * d2) * 100.0F);
 
@@ -827,4 +834,12 @@ public abstract class EntityHuman extends EntityLiving {
             this.a((Statistic) AchievementList.s);
         }
     }
+
+    public void M() {
+        if (this.C > 0) {
+            this.C = 10;
+        } else {
+            this.D = true;
+        }
+    }
 }
diff --git a/src/main/java/net/minecraft/server/EntityItem.java b/src/main/java/net/minecraft/server/EntityItem.java
index e61127df7f..7472436bc3 100644
--- a/src/main/java/net/minecraft/server/EntityItem.java
+++ b/src/main/java/net/minecraft/server/EntityItem.java
@@ -86,90 +86,12 @@ public class EntityItem extends Entity {
         return this.world.a(this.boundingBox, Material.WATER, this);
     }
 
-    private boolean g(double d0, double d1, double d2) {
-        int i = MathHelper.floor(d0);
-        int j = MathHelper.floor(d1);
-        int k = MathHelper.floor(d2);
-        double d3 = d0 - (double) i;
-        double d4 = d1 - (double) j;
-        double d5 = d2 - (double) k;
-
-        if (Block.o[this.world.getTypeId(i, j, k)]) {
-            boolean flag = !Block.o[this.world.getTypeId(i - 1, j, k)];
-            boolean flag1 = !Block.o[this.world.getTypeId(i + 1, j, k)];
-            boolean flag2 = !Block.o[this.world.getTypeId(i, j - 1, k)];
-            boolean flag3 = !Block.o[this.world.getTypeId(i, j + 1, k)];
-            boolean flag4 = !Block.o[this.world.getTypeId(i, j, k - 1)];
-            boolean flag5 = !Block.o[this.world.getTypeId(i, j, k + 1)];
-            byte b0 = -1;
-            double d6 = 9999.0D;
-
-            if (flag && d3 < d6) {
-                d6 = d3;
-                b0 = 0;
-            }
-
-            if (flag1 && 1.0D - d3 < d6) {
-                d6 = 1.0D - d3;
-                b0 = 1;
-            }
-
-            if (flag2 && d4 < d6) {
-                d6 = d4;
-                b0 = 2;
-            }
-
-            if (flag3 && 1.0D - d4 < d6) {
-                d6 = 1.0D - d4;
-                b0 = 3;
-            }
-
-            if (flag4 && d5 < d6) {
-                d6 = d5;
-                b0 = 4;
-            }
-
-            if (flag5 && 1.0D - d5 < d6) {
-                d6 = 1.0D - d5;
-                b0 = 5;
-            }
-
-            float f = this.random.nextFloat() * 0.2F + 0.1F;
-
-            if (b0 == 0) {
-                this.motX = (double) (-f);
-            }
-
-            if (b0 == 1) {
-                this.motX = (double) f;
-            }
-
-            if (b0 == 2) {
-                this.motY = (double) (-f);
-            }
-
-            if (b0 == 3) {
-                this.motY = (double) f;
-            }
-
-            if (b0 == 4) {
-                this.motZ = (double) (-f);
-            }
-
-            if (b0 == 5) {
-                this.motZ = (double) f;
-            }
-        }
-
-        return false;
-    }
-
     protected void a(int i) {
         this.damageEntity((Entity) null, i);
     }
 
     public boolean damageEntity(Entity entity, int i) {
-        this.ab();
+        this.ac();
         this.f -= i;
         if (this.f <= 0) {
             this.die();
@@ -217,7 +139,9 @@ public class EntityItem extends Entity {
 
                 this.world.makeSound(this, "random.pop", 0.2F, ((this.random.nextFloat() - this.random.nextFloat()) * 0.7F + 1.0F) * 2.0F);
                 entityhuman.receive(this, i);
-                this.die();
+                if (this.itemStack.count <= 0) {
+                    this.die();
+                }
             }
         }
     }
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index ba97a4c4f8..4c5a8c0553 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -18,67 +18,67 @@ import org.bukkit.event.entity.EntityDeathEvent;
 public abstract class EntityLiving extends Entity {
 
     public int maxNoDamageTicks = 20;
-    public float E;
-    public float F;
-    public float G = 0.0F;
-    public float H = 0.0F;
-    protected float I;
-    protected float J;
-    protected float K;
+    public float H;
+    public float I;
+    public float J = 0.0F;
+    public float K = 0.0F;
     protected float L;
-    protected boolean M = true;
+    protected float M;
+    protected float N;
+    protected float O;
+    protected boolean P = true;
     protected String texture = "/mob/char.png";
-    protected boolean O = true;
-    protected float P = 0.0F;
-    protected String Q = null;
-    protected float R = 1.0F;
-    protected int S = 0;
-    protected float T = 0.0F;
-    public boolean U = false;
-    public float V;
-    public float W;
+    protected boolean R = true;
+    protected float S = 0.0F;
+    protected String T = null;
+    protected float U = 1.0F;
+    protected int V = 0;
+    protected float W = 0.0F;
+    public boolean X = false;
+    public float Y;
+    public float Z;
     public int health = 10;
-    public int Y;
+    public int ab;
     private int a;
     public int hurtTicks;
-    public int aa;
-    public float ab = 0.0F;
+    public int ad;
+    public float ae = 0.0F;
     public int deathTicks = 0;
     public int attackTicks = 0;
-    public float ae;
-    public float af;
-    protected boolean ag = false;
-    public int ah = -1;
-    public float ai = (float) (Math.random() * 0.8999999761581421D + 0.10000000149011612D);
-    public float aj;
-    public float ak;
-    public float al;
-    protected int am;
-    protected double an;
-    protected double ao;
-    protected double ap;
+    public float ah;
+    public float ai;
+    protected boolean aj = false;
+    public int ak = -1;
+    public float al = (float) (Math.random() * 0.8999999761581421D + 0.10000000149011612D);
+    public float am;
+    public float an;
+    public float ao;
+    protected int ap;
     protected double aq;
     protected double ar;
-    float as = 0.0F;
+    protected double as;
+    protected double at;
+    protected double au;
+    float av = 0.0F;
     public int lastDamage = 0; // CraftBukkit - protected -> public
-    protected int au = 0;
-    protected float av;
-    protected float aw;
-    protected float ax;
-    protected boolean ay = false;
-    protected float az = 0.0F;
-    protected float aA = 0.7F;
+    protected int ax = 0;
+    protected float ay;
+    protected float az;
+    protected float aA;
+    protected boolean aB = false;
+    protected float aC = 0.0F;
+    protected float aD = 0.7F;
     private Entity b;
-    protected int aB = 0;
+    protected int aE = 0;
 
     public EntityLiving(World world) {
         super(world);
-        this.aE = true;
-        this.F = (float) (Math.random() + 1.0D) * 0.01F;
+        this.aH = true;
+        this.I = (float) (Math.random() + 1.0D) * 0.01F;
         this.setPosition(this.locX, this.locY, this.locZ);
-        this.E = (float) Math.random() * 12398.0F;
+        this.H = (float) Math.random() * 12398.0F;
         this.yaw = (float) (Math.random() * 3.1415927410125732D * 2.0D);
-        this.bo = 0.5F;
+        this.br = 0.5F;
     }
 
     protected void b() {}
@@ -103,7 +103,7 @@ public abstract class EntityLiving extends Entity {
         return 80;
     }
 
-    public void M() {
+    public void N() {
         String s = this.g();
 
         if (s != null) {
@@ -111,15 +111,15 @@ public abstract class EntityLiving extends Entity {
         }
     }
 
-    public void N() {
-        this.V = this.W;
-        super.N();
+    public void O() {
+        this.Y = this.Z;
+        super.O();
         if (this.random.nextInt(1000) < this.a++) {
             this.a = -this.e();
-            this.M();
+            this.N();
         }
 
-        if (this.P() && this.H()) {
+        if (this.Q() && this.H()) {
             // CraftBukkit start
             CraftServer server = ((WorldServer) this.world).getServer();
             org.bukkit.entity.Entity victim = this.getBukkitEntity();
@@ -135,13 +135,13 @@ public abstract class EntityLiving extends Entity {
             // CraftBukkit end
         }
 
-        if (this.bz || this.world.isStatic) {
+        if (this.bC || this.world.isStatic) {
             this.fireTicks = 0;
         }
 
         int i;
 
-        if (this.P() && this.a(Material.WATER) && !this.b_()) {
+        if (this.Q() && this.a(Material.WATER) && !this.b_()) {
             --this.airTicks;
             if (this.airTicks == -20) {
                 this.airTicks = 0;
@@ -174,7 +174,7 @@ public abstract class EntityLiving extends Entity {
             this.airTicks = this.maxAirTicks;
         }
 
-        this.ae = this.af;
+        this.ah = this.ai;
         if (this.attackTicks > 0) {
             --this.attackTicks;
         }
@@ -190,7 +190,7 @@ public abstract class EntityLiving extends Entity {
         if (this.health <= 0) {
             ++this.deathTicks;
             if (this.deathTicks > 20) {
-                this.T();
+                this.U();
                 this.die();
 
                 for (i = 0; i < 20; ++i) {
@@ -203,13 +203,13 @@ public abstract class EntityLiving extends Entity {
             }
         }
 
-        this.L = this.K;
-        this.H = this.G;
+        this.O = this.N;
+        this.K = this.J;
         this.lastYaw = this.yaw;
         this.lastPitch = this.pitch;
     }
 
-    public void O() {
+    public void P() {
         for (int i = 0; i < 20; ++i) {
             double d0 = this.random.nextGaussian() * 0.02D;
             double d1 = this.random.nextGaussian() * 0.02D;
@@ -222,8 +222,8 @@ public abstract class EntityLiving extends Entity {
 
     public void B() {
         super.B();
-        this.I = this.J;
-        this.J = 0.0F;
+        this.L = this.M;
+        this.M = 0.0F;
     }
 
     public void p_() {
@@ -232,10 +232,10 @@ public abstract class EntityLiving extends Entity {
         double d0 = this.locX - this.lastX;
         double d1 = this.locZ - this.lastZ;
         float f = MathHelper.a(d0 * d0 + d1 * d1);
-        float f1 = this.G;
+        float f1 = this.J;
         float f2 = 0.0F;
 
-        this.I = this.J;
+        this.L = this.M;
         float f3 = 0.0F;
 
         if (f > 0.05F) {
@@ -245,7 +245,7 @@ public abstract class EntityLiving extends Entity {
             f1 = (float) TrigMath.atan2(d1, d0) * 180.0F / 3.1415927F - 90.0F;
         }
 
-        if (this.W > 0.0F) {
+        if (this.Z > 0.0F) {
             f1 = this.yaw;
         }
 
@@ -253,11 +253,11 @@ public abstract class EntityLiving extends Entity {
             f3 = 0.0F;
         }
 
-        this.J += (f3 - this.J) * 0.3F;
+        this.M += (f3 - this.M) * 0.3F;
 
         float f4;
 
-        for (f4 = f1 - this.G; f4 < -180.0F; f4 += 360.0F) {
+        for (f4 = f1 - this.J; f4 < -180.0F; f4 += 360.0F) {
             ;
         }
 
@@ -265,11 +265,11 @@ public abstract class EntityLiving extends Entity {
             f4 -= 360.0F;
         }
 
-        this.G += f4 * 0.3F;
+        this.J += f4 * 0.3F;
 
         float f5;
 
-        for (f5 = this.yaw - this.G; f5 < -180.0F; f5 += 360.0F) {
+        for (f5 = this.yaw - this.J; f5 < -180.0F; f5 += 360.0F) {
             ;
         }
 
@@ -287,9 +287,9 @@ public abstract class EntityLiving extends Entity {
             f5 = 75.0F;
         }
 
-        this.G = this.yaw - f5;
+        this.J = this.yaw - f5;
         if (f5 * f5 > 2500.0F) {
-            this.G += f5 * 0.2F;
+            this.J += f5 * 0.2F;
         }
 
         if (flag) {
@@ -304,12 +304,12 @@ public abstract class EntityLiving extends Entity {
             this.lastYaw += 360.0F;
         }
 
-        while (this.G - this.H < -180.0F) {
-            this.H -= 360.0F;
+        while (this.J - this.K < -180.0F) {
+            this.K -= 360.0F;
         }
 
-        while (this.G - this.H >= 180.0F) {
-            this.H += 360.0F;
+        while (this.J - this.K >= 180.0F) {
+            this.K += 360.0F;
         }
 
         while (this.pitch - this.lastPitch < -180.0F) {
@@ -320,7 +320,7 @@ public abstract class EntityLiving extends Entity {
             this.lastPitch += 360.0F;
         }
 
-        this.K += f2;
+        this.N += f2;
     }
 
     protected void b(float f, float f1) {
@@ -342,11 +342,11 @@ public abstract class EntityLiving extends Entity {
         if (this.world.isStatic) {
             return false;
         } else {
-            this.au = 0;
+            this.ax = 0;
             if (this.health <= 0) {
                 return false;
             } else {
-                this.ak = 1.5F;
+                this.an = 1.5F;
                 boolean flag = true;
 
                 if ((float) this.noDamageTicks > (float) this.maxNoDamageTicks / 2.0F) {
@@ -359,16 +359,16 @@ public abstract class EntityLiving extends Entity {
                     flag = false;
                 } else {
                     this.lastDamage = i;
-                    this.Y = this.health;
+                    this.ab = this.health;
                     this.noDamageTicks = this.maxNoDamageTicks;
                     this.c(i);
-                    this.hurtTicks = this.aa = 10;
+                    this.hurtTicks = this.ad = 10;
                 }
 
-                this.ab = 0.0F;
+                this.ae = 0.0F;
                 if (flag) {
                     this.world.a(this, (byte) 2);
-                    this.ab();
+                    this.ac();
                     if (entity != null) {
                         double d0 = entity.locX - this.locX;
 
@@ -378,10 +378,10 @@ public abstract class EntityLiving extends Entity {
                             d0 = (Math.random() - Math.random()) * 0.01D;
                         }
 
-                        this.ab = (float) (Math.atan2(d1, d0) * 180.0D / 3.1415927410125732D) - this.yaw;
+                        this.ae = (float) (Math.atan2(d1, d0) * 180.0D / 3.1415927410125732D) - this.yaw;
                         this.a(entity, i, d0, d1);
                     } else {
-                        this.ab = (float) ((int) (Math.random() * 2.0D) * 180);
+                        this.ae = (float) ((int) (Math.random() * 2.0D) * 180);
                     }
                 }
 
@@ -436,15 +436,15 @@ public abstract class EntityLiving extends Entity {
     }
 
     public void a(Entity entity) {
-        if (this.S >= 0 && entity != null) {
-            entity.c(this, this.S);
+        if (this.V >= 0 && entity != null) {
+            entity.c(this, this.V);
         }
 
         if (entity != null) {
             entity.a(this);
         }
 
-        this.ag = true;
+        this.aj = true;
         if (!this.world.isStatic) {
             this.r();
         }
@@ -480,6 +480,7 @@ public abstract class EntityLiving extends Entity {
     }
 
     protected void a(float f) {
+        super.a(f);
         int i = (int) Math.ceil((double) (f - 3.0F));
 
         if (i > 0) {
@@ -509,7 +510,7 @@ public abstract class EntityLiving extends Entity {
     public void a(float f, float f1) {
         double d0;
 
-        if (this.Z()) {
+        if (this.aa()) {
             d0 = this.locY;
             this.a(f, f1, 0.02F);
             this.move(this.motX, this.motY, this.motZ);
@@ -520,7 +521,7 @@ public abstract class EntityLiving extends Entity {
             if (this.positionChanged && this.b(this.motX, this.motY + 0.6000000238418579D - this.locY + d0, this.motZ)) {
                 this.motY = 0.30000001192092896D;
             }
-        } else if (this.aa()) {
+        } else if (this.ab()) {
             d0 = this.locY;
             this.a(f, f1, 0.02F);
             this.move(this.motX, this.motY, this.motZ);
@@ -557,6 +558,24 @@ public abstract class EntityLiving extends Entity {
             }
 
             if (this.p()) {
+                float f4 = 0.15F;
+
+                if (this.motX < (double) (-f4)) {
+                    this.motX = (double) (-f4);
+                }
+
+                if (this.motX > (double) f4) {
+                    this.motX = (double) f4;
+                }
+
+                if (this.motZ < (double) (-f4)) {
+                    this.motZ = (double) (-f4);
+                }
+
+                if (this.motZ > (double) f4) {
+                    this.motZ = (double) f4;
+                }
+
                 this.fallDistance = 0.0F;
                 if (this.motY < -0.15D) {
                     this.motY = -0.15D;
@@ -578,17 +597,17 @@ public abstract class EntityLiving extends Entity {
             this.motZ *= (double) f2;
         }
 
-        this.aj = this.ak;
+        this.am = this.an;
         d0 = this.locX - this.lastX;
         double d1 = this.locZ - this.lastZ;
-        float f4 = MathHelper.a(d0 * d0 + d1 * d1) * 4.0F;
+        float f5 = MathHelper.a(d0 * d0 + d1 * d1) * 4.0F;
 
-        if (f4 > 1.0F) {
-            f4 = 1.0F;
+        if (f5 > 1.0F) {
+            f5 = 1.0F;
         }
 
-        this.ak += (f4 - this.ak) * 0.4F;
-        this.al += this.ak;
+        this.an += (f5 - this.an) * 0.4F;
+        this.ao += this.an;
     }
 
     public boolean p() {
@@ -617,7 +636,7 @@ public abstract class EntityLiving extends Entity {
         this.attackTicks = nbttagcompound.d("AttackTime");
     }
 
-    public boolean P() {
+    public boolean Q() {
         return !this.dead && this.health > 0;
     }
 
@@ -626,14 +645,14 @@ public abstract class EntityLiving extends Entity {
     }
 
     public void u() {
-        if (this.am > 0) {
-            double d0 = this.locX + (this.an - this.locX) / (double) this.am;
-            double d1 = this.locY + (this.ao - this.locY) / (double) this.am;
-            double d2 = this.locZ + (this.ap - this.locZ) / (double) this.am;
+        if (this.ap > 0) {
+            double d0 = this.locX + (this.aq - this.locX) / (double) this.ap;
+            double d1 = this.locY + (this.ar - this.locY) / (double) this.ap;
+            double d2 = this.locZ + (this.as - this.locZ) / (double) this.ap;
 
             double d3;
 
-            for (d3 = this.aq - (double) this.yaw; d3 < -180.0D; d3 += 360.0D) {
+            for (d3 = this.at - (double) this.yaw; d3 < -180.0D; d3 += 360.0D) {
                 ;
             }
 
@@ -641,26 +660,26 @@ public abstract class EntityLiving extends Entity {
                 d3 -= 360.0D;
             }
 
-            this.yaw = (float) ((double) this.yaw + d3 / (double) this.am);
-            this.pitch = (float) ((double) this.pitch + (this.ar - (double) this.pitch) / (double) this.am);
-            --this.am;
+            this.yaw = (float) ((double) this.yaw + d3 / (double) this.ap);
+            this.pitch = (float) ((double) this.pitch + (this.au - (double) this.pitch) / (double) this.ap);
+            --this.ap;
             this.setPosition(d0, d1, d2);
             this.c(this.yaw, this.pitch);
         }
 
         if (this.A()) {
-            this.ay = false;
-            this.av = 0.0F;
-            this.aw = 0.0F;
-            this.ax = 0.0F;
-        } else if (!this.U) {
+            this.aB = false;
+            this.ay = 0.0F;
+            this.az = 0.0F;
+            this.aA = 0.0F;
+        } else if (!this.X) {
             this.c_();
         }
 
-        boolean flag = this.Z();
-        boolean flag1 = this.aa();
+        boolean flag = this.aa();
+        boolean flag1 = this.ab();
 
-        if (this.ay) {
+        if (this.aB) {
             if (flag) {
                 this.motY += 0.03999999910593033D;
             } else if (flag1) {
@@ -670,10 +689,10 @@ public abstract class EntityLiving extends Entity {
             }
         }
 
-        this.av *= 0.98F;
-        this.aw *= 0.98F;
-        this.ax *= 0.9F;
-        this.a(this.av, this.aw);
+        this.ay *= 0.98F;
+        this.az *= 0.98F;
+        this.aA *= 0.9F;
+        this.a(this.ay, this.az);
         List list = this.world.b((Entity) this, this.boundingBox.b(0.20000000298023224D, 0.0D, 0.20000000298023224D));
 
         if (list != null && list.size() > 0) {
@@ -699,7 +718,7 @@ public abstract class EntityLiving extends Entity {
         return true;
     }
 
-    protected void Q() {
+    protected void R() {
         EntityHuman entityhuman = this.world.a(this, -1.0D);
 
         if (this.l_() && entityhuman != null) {
@@ -712,9 +731,9 @@ public abstract class EntityLiving extends Entity {
                 this.die();
             }
 
-            if (this.au > 600 && this.random.nextInt(800) == 0) {
+            if (this.ax > 600 && this.random.nextInt(800) == 0) {
                 if (d3 < 1024.0D) {
-                    this.au = 0;
+                    this.ax = 0;
                 } else {
                     this.die();
                 }
@@ -723,43 +742,43 @@ public abstract class EntityLiving extends Entity {
     }
 
     protected void c_() {
-        ++this.au;
+        ++this.ax;
         EntityHuman entityhuman = this.world.a(this, -1.0D);
 
-        this.Q();
-        this.av = 0.0F;
-        this.aw = 0.0F;
+        this.R();
+        this.ay = 0.0F;
+        this.az = 0.0F;
         float f = 8.0F;
 
         if (this.random.nextFloat() < 0.02F) {
             entityhuman = this.world.a(this, (double) f);
             if (entityhuman != null) {
                 this.b = entityhuman;
-                this.aB = 10 + this.random.nextInt(20);
+                this.aE = 10 + this.random.nextInt(20);
             } else {
-                this.ax = (this.random.nextFloat() - 0.5F) * 20.0F;
+                this.aA = (this.random.nextFloat() - 0.5F) * 20.0F;
             }
         }
 
         if (this.b != null) {
             this.a(this.b, 10.0F, (float) this.v());
-            if (this.aB-- <= 0 || this.b.dead || this.b.g(this) > (double) (f * f)) {
+            if (this.aE-- <= 0 || this.b.dead || this.b.g(this) > (double) (f * f)) {
                 this.b = null;
             }
         } else {
             if (this.random.nextFloat() < 0.05F) {
-                this.ax = (this.random.nextFloat() - 0.5F) * 20.0F;
+                this.aA = (this.random.nextFloat() - 0.5F) * 20.0F;
             }
 
-            this.yaw += this.ax;
-            this.pitch = this.az;
+            this.yaw += this.aA;
+            this.pitch = this.aC;
         }
 
-        boolean flag = this.Z();
-        boolean flag1 = this.aa();
+        boolean flag = this.aa();
+        boolean flag1 = this.ab();
 
         if (flag || flag1) {
-            this.ay = this.random.nextFloat() < 0.8F;
+            this.aB = this.random.nextFloat() < 0.8F;
         }
     }
 
@@ -788,11 +807,11 @@ public abstract class EntityLiving extends Entity {
         this.yaw = this.b(this.yaw, f2, f);
     }
 
-    public boolean R() {
+    public boolean S() {
         return this.b != null;
     }
 
-    public Entity S() {
+    public Entity T() {
         return this.b;
     }
 
@@ -818,13 +837,13 @@ public abstract class EntityLiving extends Entity {
         return f + f3;
     }
 
-    public void T() {}
+    public void U() {}
 
     public boolean d() {
         return this.world.containsEntity(this.boundingBox) && this.world.getEntities(this, this.boundingBox).size() == 0 && !this.world.c(this.boundingBox);
     }
 
-    protected void U() {
+    protected void V() {
         // CraftBukkit start
         CraftServer server = ((WorldServer) this.world).getServer();
         DamageCause damageType = EntityDamageEvent.DamageCause.VOID;
@@ -843,7 +862,7 @@ public abstract class EntityLiving extends Entity {
         // CraftBukkit end
     }
 
-    public Vec3D V() {
+    public Vec3D W() {
         return this.b(1.0F);
     }
 
diff --git a/src/main/java/net/minecraft/server/EntityMinecart.java b/src/main/java/net/minecraft/server/EntityMinecart.java
index 1c689f72b8..4c8af9b74f 100644
--- a/src/main/java/net/minecraft/server/EntityMinecart.java
+++ b/src/main/java/net/minecraft/server/EntityMinecart.java
@@ -51,7 +51,7 @@ public class EntityMinecart extends Entity implements IInventory {
         this.b = 0;
         this.c = 1;
         this.i = false;
-        this.aE = true;
+        this.aH = true;
         this.b(0.98F, 0.7F);
         this.height = this.width / 2.0F;
     }
@@ -117,9 +117,12 @@ public class EntityMinecart extends Entity implements IInventory {
 
             this.c = -this.c;
             this.b = 10;
-            this.ab();
+            this.ac();
             this.damage += i * 10;
             if (this.damage > 40) {
+                if (this.passenger != null) {
+                    this.passenger.mount(this);
+                }
 
                 // CraftBukkit start
                 VehicleDestroyEvent destroyEvent = new VehicleDestroyEvent(vehicle, passenger);
@@ -131,14 +134,42 @@ public class EntityMinecart extends Entity implements IInventory {
                 }
                 // CraftBukkit end
 
+                this.die();
                 this.a(Item.MINECART.id, 1, 0.0F);
                 if (this.type == 1) {
+                    EntityMinecart entityminecart = this;
+
+                    for (int j = 0; j < entityminecart.getSize(); ++j) {
+                        ItemStack itemstack = entityminecart.getItem(j);
+
+                        if (itemstack != null) {
+                            float f = this.random.nextFloat() * 0.8F + 0.1F;
+                            float f1 = this.random.nextFloat() * 0.8F + 0.1F;
+                            float f2 = this.random.nextFloat() * 0.8F + 0.1F;
+
+                            while (itemstack.count > 0) {
+                                int k = this.random.nextInt(21) + 10;
+
+                                if (k > itemstack.count) {
+                                    k = itemstack.count;
+                                }
+
+                                itemstack.count -= k;
+                                EntityItem entityitem = new EntityItem(this.world, this.locX + (double) f, this.locY + (double) f1, this.locZ + (double) f2, new ItemStack(itemstack.id, k, itemstack.getData()));
+                                float f3 = 0.05F;
+
+                                entityitem.motX = (double) ((float) this.random.nextGaussian() * f3);
+                                entityitem.motY = (double) ((float) this.random.nextGaussian() * f3 + 0.2F);
+                                entityitem.motZ = (double) ((float) this.random.nextGaussian() * f3);
+                                this.world.addEntity(entityitem);
+                            }
+                        }
+                    }
+
                     this.a(Block.CHEST.id, 1, 0.0F);
                 } else if (this.type == 2) {
                     this.a(Block.FURNACE.id, 1, 0.0F);
                 }
-
-                this.die();
             }
 
             return true;
@@ -245,7 +276,7 @@ public class EntityMinecart extends Entity implements IInventory {
             int l = this.world.getTypeId(i, j, k);
 
             if (BlockMinecartTrack.c(l)) {
-                Vec3D vec3d = this.g(this.locX, this.locY, this.locZ);
+                Vec3D vec3d = this.h(this.locX, this.locY, this.locZ);
                 int i1 = this.world.getData(i, j, k);
 
                 this.locY = (double) j;
@@ -257,7 +288,7 @@ public class EntityMinecart extends Entity implements IInventory {
                     flag2 = !flag1;
                 }
 
-                if (((BlockMinecartTrack) Block.byId[l]).d()) {
+                if (((BlockMinecartTrack) Block.byId[l]).e()) {
                     i1 &= 7;
                 }
 
@@ -400,7 +431,7 @@ public class EntityMinecart extends Entity implements IInventory {
                     this.motZ *= 0.9599999785423279D;
                 }
 
-                Vec3D vec3d1 = this.g(this.locX, this.locY, this.locZ);
+                Vec3D vec3d1 = this.h(this.locX, this.locY, this.locZ);
 
                 if (vec3d1 != null && vec3d != null) {
                     double d19 = (vec3d.b - vec3d1.b) * 0.05D;
@@ -443,7 +474,7 @@ public class EntityMinecart extends Entity implements IInventory {
                 if (flag1) {
                     d20 = Math.sqrt(this.motX * this.motX + this.motZ * this.motZ);
                     if (d20 > 0.01D) {
-                        double d21 = 0.04D;
+                        double d21 = 0.06D;
 
                         this.motX += this.motX / d20 * d21;
                         this.motZ += this.motZ / d20 * d21;
@@ -566,7 +597,7 @@ public class EntityMinecart extends Entity implements IInventory {
         }
     }
 
-    public Vec3D g(double d0, double d1, double d2) {
+    public Vec3D h(double d0, double d1, double d2) {
         int i = MathHelper.floor(d0);
         int j = MathHelper.floor(d1);
         int k = MathHelper.floor(d2);
@@ -581,7 +612,7 @@ public class EntityMinecart extends Entity implements IInventory {
             int i1 = this.world.getData(i, j, k);
 
             d1 = (double) j;
-            if (((BlockMinecartTrack) Block.byId[l]).d()) {
+            if (((BlockMinecartTrack) Block.byId[l]).e()) {
                 i1 &= 7;
             }
 
@@ -685,15 +716,15 @@ public class EntityMinecart extends Entity implements IInventory {
                 Vehicle vehicle = (Vehicle) this.getBukkitEntity();
                 org.bukkit.entity.Entity hitEntity = (entity == null) ? null : entity.getBukkitEntity();
 
-                VehicleEntityCollisionEvent collsionEvent = new VehicleEntityCollisionEvent(vehicle, hitEntity);
-                server.getPluginManager().callEvent(collsionEvent);
+                VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, hitEntity);
+                server.getPluginManager().callEvent(collisionEvent);
 
-                if (collsionEvent.isCancelled()) {
+                if (collisionEvent.isCancelled()) {
                     return;
                 }
 
                 if (entity instanceof EntityLiving && !(entity instanceof EntityHuman) && this.type == 0 && this.motX * this.motX + this.motZ * this.motZ > 0.01D && this.passenger == null && entity.vehicle == null) {
-                    if (!collsionEvent.isPickupCancelled()) {
+                    if (!collisionEvent.isPickupCancelled()) {
 
                         VehicleEnterEvent enterEvent = new VehicleEnterEvent(vehicle, hitEntity);
                         server.getPluginManager().callEvent(enterEvent);
@@ -710,7 +741,7 @@ public class EntityMinecart extends Entity implements IInventory {
                 double d2 = d0 * d0 + d1 * d1;
 
                 // CraftBukkit - Collision
-                if (d2 >= 9.9999997473787516E-005D && !collsionEvent.isCollisionCancelled()) {
+                if (d2 >= 9.9999997473787516E-005D && !collisionEvent.isCollisionCancelled()) {
                     d2 = (double) MathHelper.a(d2);
                     d0 /= d2;
                     d1 /= d2;
@@ -724,13 +755,22 @@ public class EntityMinecart extends Entity implements IInventory {
                     d1 *= d3;
                     d0 *= 0.10000000149011612D;
                     d1 *= 0.10000000149011612D;
-                    d0 *= (double) (1.0F - this.bq);
-                    d1 *= (double) (1.0F - this.bq);
+                    d0 *= (double) (1.0F - this.bt);
+                    d1 *= (double) (1.0F - this.bt);
                     d0 *= 0.5D;
                     d1 *= 0.5D;
                     if (entity instanceof EntityMinecart) {
-                        double d4 = entity.motX + this.motX;
-                        double d5 = entity.motZ + this.motZ;
+                        double d4 = entity.locX - this.locX;
+                        double d5 = entity.locZ - this.locZ;
+                        double d6 = d4 * entity.motZ + d5 * entity.lastX;
+
+                        d6 *= d6;
+                        if (d6 > 5.0D) {
+                            return;
+                        }
+
+                        double d7 = entity.motX + this.motX;
+                        double d8 = entity.motZ + this.motZ;
 
                         if (((EntityMinecart) entity).type == 2 && this.type != 2) {
                             this.motX *= 0.20000000298023224D;
@@ -745,14 +785,14 @@ public class EntityMinecart extends Entity implements IInventory {
                             this.motX *= 0.699999988079071D;
                             this.motZ *= 0.699999988079071D;
                         } else {
-                            d4 /= 2.0D;
-                            d5 /= 2.0D;
+                            d7 /= 2.0D;
+                            d8 /= 2.0D;
                             this.motX *= 0.20000000298023224D;
                             this.motZ *= 0.20000000298023224D;
-                            this.f(d4 - d0, 0.0D, d5 - d1);
+                            this.f(d7 - d0, 0.0D, d8 - d1);
                             entity.motX *= 0.20000000298023224D;
                             entity.motZ *= 0.20000000298023224D;
-                            entity.f(d4 + d0, 0.0D, d5 + d1);
+                            entity.f(d7 + d0, 0.0D, d8 + d1);
                         }
                     } else {
                         this.f(-d0, 0.0D, -d1);
diff --git a/src/main/java/net/minecraft/server/EntityMonster.java b/src/main/java/net/minecraft/server/EntityMonster.java
index bc8be4d24a..a4ac63d39d 100644
--- a/src/main/java/net/minecraft/server/EntityMonster.java
+++ b/src/main/java/net/minecraft/server/EntityMonster.java
@@ -24,7 +24,7 @@ public class EntityMonster extends EntityCreature implements IMonster {
         float f = this.c(1.0F);
 
         if (f > 0.5F) {
-            this.au += 2;
+            this.ax += 2;
         }
 
         super.u();
@@ -32,7 +32,7 @@ public class EntityMonster extends EntityCreature implements IMonster {
 
     public void p_() {
         super.p_();
-        if (this.world.spawnMonsters == 0) {
+        if (!this.world.isStatic && this.world.spawnMonsters == 0) {
             this.die();
         }
     }
@@ -79,9 +79,9 @@ public class EntityMonster extends EntityCreature implements IMonster {
     protected void a(Entity entity, float f) {
         if (this.attackTicks <= 0 && f < 2.0F && entity.boundingBox.e > this.boundingBox.b && entity.boundingBox.b < this.boundingBox.e) {
             this.attackTicks = 20;
-            // CraftBukkit start - this is still duplicated here and EntityHuman because it's possible for an EntityMonster
+            // CraftBukkit start - this is still duplicated here and EntityHuman because it's possible for lastDamage EntityMonster
             // to damage another EntityMonster, and we want to catch those events.
-            // This does not fire events for slime attacks, as they're not an EntityMonster.
+            // This does not fire events for slime attacks, av they're not lastDamage EntityMonster.
             if (entity instanceof EntityLiving && !(entity instanceof EntityHuman)) {
                 CraftServer server = ((WorldServer) this.world).getServer();
                 org.bukkit.entity.Entity damager = this.getBukkitEntity();
@@ -103,7 +103,7 @@ public class EntityMonster extends EntityCreature implements IMonster {
     }
 
     protected float a(int i, int j, int k) {
-        return 0.5F - this.world.l(i, j, k);
+        return 0.5F - this.world.m(i, j, k);
     }
 
     public void b(NBTTagCompound nbttagcompound) {
diff --git a/src/main/java/net/minecraft/server/EntityPainting.java b/src/main/java/net/minecraft/server/EntityPainting.java
index 517c58bf0a..f06b3db915 100644
--- a/src/main/java/net/minecraft/server/EntityPainting.java
+++ b/src/main/java/net/minecraft/server/EntityPainting.java
@@ -214,7 +214,7 @@ public class EntityPainting extends Entity {
             // CraftBukkit end
 
             this.die();
-            this.ab();
+            this.ac();
             this.world.addEntity(new EntityItem(this.world, this.locX, this.locY, this.locZ, new ItemStack(Item.PAINTING)));
         }
 
diff --git a/src/main/java/net/minecraft/server/EntityPig.java b/src/main/java/net/minecraft/server/EntityPig.java
index 7deabe94bd..62853e3a5b 100644
--- a/src/main/java/net/minecraft/server/EntityPig.java
+++ b/src/main/java/net/minecraft/server/EntityPig.java
@@ -67,23 +67,25 @@ public class EntityPig extends EntityAnimal {
     }
 
     public void a(EntityWeatherStorm entityweatherstorm) {
-        EntityPigZombie entitypigzombie = new EntityPigZombie(this.world);
+        if (!this.world.isStatic) {
+            EntityPigZombie entitypigzombie = new EntityPigZombie(this.world);
 
-        // CraftBukkit start
-        CraftServer server = ((WorldServer) this.world).getServer();
-        org.bukkit.entity.Entity entity = this.getBukkitEntity();
+            // CraftBukkit start
+            CraftServer server = ((WorldServer) this.world).getServer();
+            org.bukkit.entity.Entity entity = this.getBukkitEntity();
 
-        PigZapEvent event = new PigZapEvent(entity, entityweatherstorm.getBukkitEntity(), entitypigzombie.getBukkitEntity());
-        server.getPluginManager().callEvent(event);
+            PigZapEvent event = new PigZapEvent(entity, entityweatherstorm.getBukkitEntity(), entitypigzombie.getBukkitEntity());
+            server.getPluginManager().callEvent(event);
 
-        if (event.isCancelled()) {
-            return;
+            if (event.isCancelled()) {
+                return;
+            }
+            // CraftBukkit end
+
+            entitypigzombie.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, this.pitch);
+            this.world.addEntity(entitypigzombie);
+            this.die();
         }
-        // CraftBukkit end
-
-        entitypigzombie.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, this.pitch);
-        this.world.addEntity(entitypigzombie);
-        this.die();
     }
 
     protected void a(float f) {
diff --git a/src/main/java/net/minecraft/server/EntityPigZombie.java b/src/main/java/net/minecraft/server/EntityPigZombie.java
index 87a6b0227b..dea61b03d2 100644
--- a/src/main/java/net/minecraft/server/EntityPigZombie.java
+++ b/src/main/java/net/minecraft/server/EntityPigZombie.java
@@ -18,13 +18,13 @@ public class EntityPigZombie extends EntityZombie {
     public EntityPigZombie(World world) {
         super(world);
         this.texture = "/mob/pigzombie.png";
-        this.aA = 0.5F;
+        this.aD = 0.5F;
         this.damage = 5;
-        this.bz = true;
+        this.bC = true;
     }
 
     public void p_() {
-        this.aA = this.target != null ? 0.95F : 0.5F;
+        this.aD = this.target != null ? 0.95F : 0.5F;
         if (this.soundDelay > 0 && --this.soundDelay == 0) {
             this.world.makeSound(this, "mob.zombiepig.zpigangry", this.k() * 2.0F, ((this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F) * 1.8F);
         }
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 7a03283afd..68169076ad 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -25,14 +25,16 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
     public double e;
     public List f = new LinkedList();
     public Set g = new HashSet();
-    private int bF = -99999999;
-    private int bG = 60;
-    private ItemStack[] bH = new ItemStack[] { null, null, null, null, null};
-    private int bI = 0;
+    private int bJ = -99999999;
+    private int bK = 60;
+    private ItemStack[] bL = new ItemStack[] { null, null, null, null, null};
+    private int bM = 0;
     public boolean h;
 
     public EntityPlayer(MinecraftServer minecraftserver, World world, String s, ItemInWorldManager iteminworldmanager) {
         super(world);
+        iteminworldmanager.player = this;
+        this.itemInWorldManager = iteminworldmanager;
         ChunkCoordinates chunkcoordinates = world.getSpawn();
         int i = chunkcoordinates.x;
         int j = chunkcoordinates.z;
@@ -40,17 +42,20 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
 
         if (!world.worldProvider.e) {
             i += this.random.nextInt(20) - 10;
-            k = world.e(i, j);
+            k = world.f(i, j);
             j += this.random.nextInt(20) - 10;
         }
 
         this.setPositionRotation((double) i + 0.5D, (double) k, (double) j + 0.5D, 0.0F, 0.0F);
         this.b = minecraftserver;
-        this.bo = 0.0F;
-        iteminworldmanager.player = this;
+        this.br = 0.0F;
         this.name = s;
-        this.itemInWorldManager = iteminworldmanager;
         this.height = 0.0F;
+        this.inventory.canHold(new ItemStack(Item.PAPER, 64));
+        this.inventory.canHold(new ItemStack(Block.WORKBENCH, 64));
+        this.inventory.canHold(new ItemStack(Item.COMPASS, 64));
+        this.inventory.canHold(new ItemStack(Block.OBSIDIAN, 64));
+        this.inventory.canHold(new ItemStack(Item.FLINT_AND_STEEL));
 
         // CraftBukkit start
         this.displayName = this.name;
@@ -60,12 +65,18 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
     public Location compassTarget;
     // CraftBukkit end
 
+    public void a(World world) {
+        super.a(world);
+        this.itemInWorldManager = new ItemInWorldManager((WorldServer) world);
+        this.itemInWorldManager.player = this;
+    }
+
     public void syncInventory() {
         this.activeContainer.a((ICrafting) this);
     }
 
     public ItemStack[] getEquipment() {
-        return this.bH;
+        return this.bL;
     }
 
     protected void j_() {
@@ -78,15 +89,15 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
 
     public void p_() {
         this.itemInWorldManager.a();
-        --this.bG;
+        --this.bK;
         this.activeContainer.a();
 
         for (int i = 0; i < 5; ++i) {
             ItemStack itemstack = this.b_(i);
 
-            if (itemstack != this.bH[i]) {
-                this.b.tracker.a(this, new Packet5EntityEquipment(this.id, i, itemstack));
-                this.bH[i] = itemstack;
+            if (itemstack != this.bL[i]) {
+                this.b.b(this.dimension).a(this, new Packet5EntityEquipment(this.id, i, itemstack));
+                this.bL[i] = itemstack;
             }
         }
     }
@@ -136,10 +147,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
     }
 
     public boolean damageEntity(Entity entity, int i) {
-        if (this.bG > 0) {
+        if (this.bK > 0) {
             return false;
         } else {
-            if (!this.world.pvpMode) { // CraftBukkit
+            if (!this.b.pvpMode) {
                 if (entity instanceof EntityHuman) {
                     return false;
                 }
@@ -167,34 +178,75 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
 
     public void a(boolean flag) {
         super.p_();
+
+        for (int i = 0; i < this.inventory.getSize(); ++i) {
+            ItemStack itemstack = this.inventory.getItem(i);
+
+            if (itemstack != null && Item.byId[itemstack.id].b() && this.netServerHandler.b() <= 2) {
+                Packet packet = ((ItemWorldMapBase) Item.byId[itemstack.id]).b(itemstack, this.world, this);
+
+                if (packet != null) {
+                    this.netServerHandler.sendPacket(packet);
+                }
+            }
+        }
+
         if (flag && !this.f.isEmpty()) {
             ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) this.f.get(0);
 
             if (chunkcoordintpair != null) {
                 boolean flag1 = false;
 
-                if (this.netServerHandler.b() < 2) {
+                if (this.netServerHandler.b() < 4) {
                     flag1 = true;
                 }
 
                 if (flag1) {
+                    WorldServer worldserver = this.b.a(this.dimension);
+
                     this.f.remove(chunkcoordintpair);
+                    this.netServerHandler.sendPacket(new Packet51MapChunk(chunkcoordintpair.x * 16, 0, chunkcoordintpair.z * 16, 16, 128, 16, worldserver));
+                    List list = worldserver.getTileEntities(chunkcoordintpair.x * 16, 0, chunkcoordintpair.z * 16, chunkcoordintpair.x * 16 + 16, 128, chunkcoordintpair.z * 16 + 16);
 
-                    // CraftBukkit start
-                    this.netServerHandler.sendPacket(new Packet51MapChunk(chunkcoordintpair.x * 16, 0, chunkcoordintpair.z * 16, 16, 128, 16, this.world));
-                    List list = ((WorldServer) world).getTileEntities(chunkcoordintpair.x * 16, 0, chunkcoordintpair.z * 16, chunkcoordintpair.x * 16 + 16, 128, chunkcoordintpair.z * 16 + 16);
-                    // CraftBukkit end
-
-                    for (int i = 0; i < list.size(); ++i) {
-                        this.a((TileEntity) list.get(i));
+                    for (int j = 0; j < list.size(); ++j) {
+                        this.a((TileEntity) list.get(j));
                     }
                 }
             }
         }
 
-        if (this.health != this.bF) {
+        if (this.D) {
+            if (this.b.propertyManager.getBoolean("allow-nether", true)) {
+                if (this.vehicle != null) {
+                    this.mount(this.vehicle);
+                } else {
+                    this.E += 0.0125F;
+                    if (this.E >= 1.0F) {
+                        this.E = 1.0F;
+                        this.C = 10;
+                        this.b.serverConfigurationManager.f(this);
+                    }
+                }
+
+                this.D = false;
+            }
+        } else {
+            if (this.E > 0.0F) {
+                this.E -= 0.05F;
+            }
+
+            if (this.E < 0.0F) {
+                this.E = 0.0F;
+            }
+        }
+
+        if (this.C > 0) {
+            --this.C;
+        }
+
+        if (this.health != this.bJ) {
             this.netServerHandler.sendPacket(new Packet8UpdateHealth(this.health));
-            this.bF = this.health;
+            this.bJ = this.health;
         }
     }
 
@@ -214,12 +266,14 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
 
     public void receive(Entity entity, int i) {
         if (!entity.dead) {
+            EntityTracker entitytracker = this.b.b(this.dimension);
+
             if (entity instanceof EntityItem) {
-                this.b.tracker.a(entity, new Packet22Collect(entity.id, this.id));
+                entitytracker.a(entity, new Packet22Collect(entity.id, this.id));
             }
 
             if (entity instanceof EntityArrow) {
-                this.b.tracker.a(entity, new Packet22Collect(entity.id, this.id));
+                entitytracker.a(entity, new Packet22Collect(entity.id, this.id));
             }
         }
 
@@ -231,7 +285,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
         if (!this.p) {
             this.q = -1;
             this.p = true;
-            this.b.tracker.a(this, new Packet18ArmAnimation(this, 1));
+            EntityTracker entitytracker = this.b.b(this.dimension);
+
+            entitytracker.a(this, new Packet18ArmAnimation(this, 1));
         }
     }
 
@@ -241,7 +297,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
         EnumBedError enumbederror = super.a(i, j, k);
 
         if (enumbederror == EnumBedError.OK) {
-            this.b.tracker.a(this, new Packet17(this, 0, i, j, k));
+            EntityTracker entitytracker = this.b.b(this.dimension);
+
+            entitytracker.a(this, new Packet17(this, 0, i, j, k));
         }
 
         return enumbederror;
@@ -249,7 +307,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
 
     public void a(boolean flag, boolean flag1, boolean flag2) {
         if (this.isSleeping()) {
-            this.b.tracker.b(this, new Packet18ArmAnimation(this, 3));
+            EntityTracker entitytracker = this.b.b(this.dimension);
+
+            entitytracker.b(this, new Packet18ArmAnimation(this, 3));
         }
 
         super.a(flag, flag1, flag2);
@@ -279,38 +339,38 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
     }
 
     private void af() {
-        this.bI = this.bI % 100 + 1;
+        this.bM = this.bM % 100 + 1;
     }
 
     public void b(int i, int j, int k) {
         this.af();
-        this.netServerHandler.sendPacket(new Packet100OpenWindow(this.bI, 1, "Crafting", 9));
+        this.netServerHandler.sendPacket(new Packet100OpenWindow(this.bM, 1, "Crafting", 9));
         this.activeContainer = new ContainerWorkbench(this.inventory, this.world, i, j, k);
-        this.activeContainer.f = this.bI;
+        this.activeContainer.f = this.bM;
         this.activeContainer.a((ICrafting) this);
     }
 
     public void a(IInventory iinventory) {
         this.af();
-        this.netServerHandler.sendPacket(new Packet100OpenWindow(this.bI, 0, iinventory.getName(), iinventory.getSize()));
+        this.netServerHandler.sendPacket(new Packet100OpenWindow(this.bM, 0, iinventory.getName(), iinventory.getSize()));
         this.activeContainer = new ContainerChest(this.inventory, iinventory);
-        this.activeContainer.f = this.bI;
+        this.activeContainer.f = this.bM;
         this.activeContainer.a((ICrafting) this);
     }
 
     public void a(TileEntityFurnace tileentityfurnace) {
         this.af();
-        this.netServerHandler.sendPacket(new Packet100OpenWindow(this.bI, 2, tileentityfurnace.getName(), tileentityfurnace.getSize()));
+        this.netServerHandler.sendPacket(new Packet100OpenWindow(this.bM, 2, tileentityfurnace.getName(), tileentityfurnace.getSize()));
         this.activeContainer = new ContainerFurnace(this.inventory, tileentityfurnace);
-        this.activeContainer.f = this.bI;
+        this.activeContainer.f = this.bM;
         this.activeContainer.a((ICrafting) this);
     }
 
     public void a(TileEntityDispenser tileentitydispenser) {
         this.af();
-        this.netServerHandler.sendPacket(new Packet100OpenWindow(this.bI, 3, tileentitydispenser.getName(), tileentitydispenser.getSize()));
+        this.netServerHandler.sendPacket(new Packet100OpenWindow(this.bM, 3, tileentitydispenser.getName(), tileentitydispenser.getSize()));
         this.activeContainer = new ContainerDispenser(this.inventory, tileentitydispenser);
-        this.activeContainer.f = this.bI;
+        this.activeContainer.f = this.bM;
         this.activeContainer.a((ICrafting) this);
     }
 
@@ -322,6 +382,10 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
         }
     }
 
+    public void a(Container container) {
+        this.a(container, container.b());
+    }
+
     public void a(Container container, List list) {
         this.netServerHandler.sendPacket(new Packet104WindowItems(container.f, list));
         this.netServerHandler.sendPacket(new Packet103SetSlot(-1, -1, this.inventory.j()));
@@ -350,9 +414,9 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
     }
 
     public void a(float f, float f1, boolean flag, boolean flag1, float f2, float f3) {
-        this.av = f;
-        this.aw = f1;
-        this.ay = flag;
+        this.ay = f;
+        this.az = f1;
+        this.aB = flag;
         this.setSneak(flag1);
         this.pitch = f2;
         this.yaw = f3;
diff --git a/src/main/java/net/minecraft/server/EntitySkeleton.java b/src/main/java/net/minecraft/server/EntitySkeleton.java
index 753e561987..4776eb5162 100644
--- a/src/main/java/net/minecraft/server/EntitySkeleton.java
+++ b/src/main/java/net/minecraft/server/EntitySkeleton.java
@@ -63,7 +63,7 @@ public class EntitySkeleton extends EntityMonster {
                 EntityArrow entityarrow = new EntityArrow(this.world, this);
 
                 ++entityarrow.locY;
-                double d2 = entity.locY - 0.20000000298023224D - entityarrow.locY;
+                double d2 = entity.locY + (double) entity.s() - 0.20000000298023224D - entityarrow.locY;
                 float f1 = MathHelper.a(d0 * d0 + d1 * d1) * 0.2F;
 
                 this.world.makeSound(this, "random.bow", 1.0F, 1.0F / (this.random.nextFloat() * 0.4F + 0.8F));
diff --git a/src/main/java/net/minecraft/server/EntitySnowball.java b/src/main/java/net/minecraft/server/EntitySnowball.java
index 60d442e043..4d5cb8e4cc 100644
--- a/src/main/java/net/minecraft/server/EntitySnowball.java
+++ b/src/main/java/net/minecraft/server/EntitySnowball.java
@@ -77,9 +77,9 @@ public class EntitySnowball extends Entity {
     }
 
     public void p_() {
-        this.bk = this.locX;
-        this.bl = this.locY;
-        this.bm = this.locZ;
+        this.bn = this.locX;
+        this.bo = this.locY;
+        this.bp = this.locZ;
         super.p_();
         if (this.a > 0) {
             --this.a;
@@ -213,7 +213,7 @@ public class EntitySnowball extends Entity {
         float f2 = 0.99F;
         float f3 = 0.03F;
 
-        if (this.Z()) {
+        if (this.aa()) {
             for (int l = 0; l < 4; ++l) {
                 float f4 = 0.25F;
 
diff --git a/src/main/java/net/minecraft/server/EntitySpider.java b/src/main/java/net/minecraft/server/EntitySpider.java
index 6736efe139..a5104f260b 100644
--- a/src/main/java/net/minecraft/server/EntitySpider.java
+++ b/src/main/java/net/minecraft/server/EntitySpider.java
@@ -13,7 +13,7 @@ public class EntitySpider extends EntityMonster {
         super(world);
         this.texture = "/mob/spider.png";
         this.b(1.4F, 0.9F);
-        this.aA = 0.8F;
+        this.aD = 0.8F;
     }
 
     public double m() {
diff --git a/src/main/java/net/minecraft/server/EntityTNTPrimed.java b/src/main/java/net/minecraft/server/EntityTNTPrimed.java
index b54f9a77ed..cd023a8dc3 100644
--- a/src/main/java/net/minecraft/server/EntityTNTPrimed.java
+++ b/src/main/java/net/minecraft/server/EntityTNTPrimed.java
@@ -13,7 +13,7 @@ public class EntityTNTPrimed extends Entity {
     public EntityTNTPrimed(World world) {
         super(world);
         this.a = 0;
-        this.aE = true;
+        this.aH = true;
         this.b(0.98F, 0.98F);
         this.height = this.width / 2.0F;
     }
@@ -58,10 +58,12 @@ public class EntityTNTPrimed extends Entity {
         }
 
         if (this.a-- <= 0) {
-            // CraftBukkit start - Need to reverse the order of the explosion and the entity death so we have a location for the event.
-            this.explode();
-            this.die();
-            // CraftBukkit end
+            if (!this.world.isStatic) {
+                // CraftBukkit start - Need to reverse the order of the explosion and the entity death so we have a location for the event.
+                this.explode();
+                this.die();
+                // CraftBukkit end
+            }
         } else {
             this.world.a("smoke", this.locX, this.locY + 0.5D, this.locZ, 0.0D, 0.0D, 0.0D);
         }
diff --git a/src/main/java/net/minecraft/server/EntityTracker.java b/src/main/java/net/minecraft/server/EntityTracker.java
index a1011b1bc0..99bfddecee 100644
--- a/src/main/java/net/minecraft/server/EntityTracker.java
+++ b/src/main/java/net/minecraft/server/EntityTracker.java
@@ -11,9 +11,11 @@ public class EntityTracker {
     private EntityList b = new EntityList();
     private MinecraftServer c;
     private int d;
+    private int e;
 
-    public EntityTracker(MinecraftServer minecraftserver) {
+    public EntityTracker(MinecraftServer minecraftserver, int i) {
         this.c = minecraftserver;
+        this.e = i;
         this.d = minecraftserver.serverConfigurationManager.a();
     }
 
@@ -34,11 +36,13 @@ public class EntityTracker {
         } else if (entity instanceof EntityFish) {
             this.a(entity, 64, 5, true);
         } else if (entity instanceof EntityArrow) {
-            this.a(entity, 64, 5, true);
+            this.a(entity, 64, 20, false);
+        } else if (entity instanceof EntityFireball) {
+            this.a(entity, 64, 10, false);
         } else if (entity instanceof EntitySnowball) {
-            this.a(entity, 64, 5, true);
+            this.a(entity, 64, 10, true);
         } else if (entity instanceof EntityEgg) {
-            this.a(entity, 64, 5, true);
+            this.a(entity, 64, 10, true);
         } else if (entity instanceof EntityItem) {
             this.a(entity, 64, 20, true);
         } else if (entity instanceof EntityMinecart) {
@@ -76,8 +80,7 @@ public class EntityTracker {
 
             this.a.add(entitytrackerentry);
             this.b.a(entity.id, entitytrackerentry);
-            // CraftBukkit
-            entitytrackerentry.scanPlayers(entity.world.players);
+            entitytrackerentry.scanPlayers(this.c.a(this.e).players);
         }
     }
 
@@ -110,8 +113,7 @@ public class EntityTracker {
         while (iterator.hasNext()) {
             EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next();
 
-            // CraftBukkit
-            entitytrackerentry.track(entitytrackerentry.tracker.world.players);
+            entitytrackerentry.track(this.c.a(this.e).players);
             if (entitytrackerentry.m && entitytrackerentry.tracker instanceof EntityPlayer) {
                 arraylist.add((EntityPlayer) entitytrackerentry.tracker);
             }
diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
index e1ba68f932..66db0eeb4a 100644
--- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java
+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
@@ -24,6 +24,7 @@ public class EntityTrackerEntry {
     private double q;
     private boolean r = false;
     private boolean isMoving;
+    private int t = 0;
     public boolean m = false;
     public Set trackedPlayers = new HashSet();
 
@@ -58,6 +59,7 @@ public class EntityTrackerEntry {
             this.scanPlayers(list);
         }
 
+        ++this.t;
         if (++this.l % this.c == 0) {
             int i = MathHelper.floor(this.tracker.locX * 32.0D);
             int j = MathHelper.floor(this.tracker.locY * 32.0D);
@@ -71,7 +73,7 @@ public class EntityTrackerEntry {
             boolean flag = Math.abs(i) >= 8 || Math.abs(j) >= 8 || Math.abs(k) >= 8;
             boolean flag1 = Math.abs(l - this.g) >= 8 || Math.abs(i1 - this.h) >= 8;
 
-            if (j1 >= -128 && j1 < 128 && k1 >= -128 && k1 < 128 && l1 >= -128 && l1 < 128) {
+            if (j1 >= -128 && j1 < 128 && k1 >= -128 && k1 < 128 && l1 >= -128 && l1 < 128 && this.t <= 400) {
                 if (flag && flag1) {
                     object = new Packet33RelEntityMoveLook(this.tracker.id, (byte) j1, (byte) k1, (byte) l1, (byte) l, (byte) i1);
                 } else if (flag) {
@@ -80,6 +82,10 @@ public class EntityTrackerEntry {
                     object = new Packet32EntityLook(this.tracker.id, (byte) l, (byte) i1);
                 }
             } else {
+                this.t = 0;
+                this.tracker.locX = (double) i / 32.0D;
+                this.tracker.locY = (double) j / 32.0D;
+                this.tracker.locZ = (double) k / 32.0D;
                 object = new Packet34EntityTeleport(this.tracker.id, i, j, k, (byte) l, (byte) i1);
             }
 
@@ -102,7 +108,7 @@ public class EntityTrackerEntry {
                 this.a((Packet) object);
             }
 
-            DataWatcher datawatcher = this.tracker.W();
+            DataWatcher datawatcher = this.tracker.X();
 
             if (datawatcher.a()) {
                 this.b((Packet) (new Packet40EntityMetadata(this.tracker.id, datawatcher)));
@@ -159,8 +165,7 @@ public class EntityTrackerEntry {
             double d1 = entityplayer.locZ - (double) (this.f / 32);
 
             if (d0 >= (double) (-this.b) && d0 <= (double) this.b && d1 >= (double) (-this.b) && d1 <= (double) this.b) {
-                // CraftBukkit
-                if ((!this.trackedPlayers.contains(entityplayer)) && (this.tracker.world == entityplayer.world)) {
+                if (!this.trackedPlayers.contains(entityplayer)) {
                     this.trackedPlayers.add(entityplayer);
                     entityplayer.netServerHandler.sendPacket(this.b());
                     if (this.isMoving) {
@@ -228,9 +233,19 @@ public class EntityTrackerEntry {
             } else if (this.tracker instanceof EntityFish) {
                 return new Packet23VehicleSpawn(this.tracker, 90);
             } else if (this.tracker instanceof EntityArrow) {
-                return new Packet23VehicleSpawn(this.tracker, 60);
+                EntityLiving entityliving = ((EntityArrow) this.tracker).shooter;
+
+                return new Packet23VehicleSpawn(this.tracker, 60, entityliving != null ? entityliving.id : this.tracker.id);
             } else if (this.tracker instanceof EntitySnowball) {
                 return new Packet23VehicleSpawn(this.tracker, 61);
+            } else if (this.tracker instanceof EntityFireball) {
+                EntityFireball entityfireball = (EntityFireball) this.tracker;
+                Packet23VehicleSpawn packet23vehiclespawn = new Packet23VehicleSpawn(this.tracker, 63, ((EntityFireball) this.tracker).shooter.id);
+
+                packet23vehiclespawn.e = (int) (entityfireball.c * 8000.0D);
+                packet23vehiclespawn.f = (int) (entityfireball.d * 8000.0D);
+                packet23vehiclespawn.g = (int) (entityfireball.e * 8000.0D);
+                return packet23vehiclespawn;
             } else if (this.tracker instanceof EntityEgg) {
                 return new Packet23VehicleSpawn(this.tracker, 62);
             } else if (this.tracker instanceof EntityTNTPrimed) {
diff --git a/src/main/java/net/minecraft/server/EntityWeatherStorm.java b/src/main/java/net/minecraft/server/EntityWeatherStorm.java
index b92fd4ac58..7173f424f3 100644
--- a/src/main/java/net/minecraft/server/EntityWeatherStorm.java
+++ b/src/main/java/net/minecraft/server/EntityWeatherStorm.java
@@ -91,9 +91,8 @@ public class EntityWeatherStorm extends EntityWeather {
                 --this.c;
                 this.b = 1;
                 this.a = this.random.nextLong();
-                // CraftBukkit start
+                // CraftBukkit
                 if (!isEffect && this.world.a(MathHelper.floor(this.locX), MathHelper.floor(this.locY), MathHelper.floor(this.locZ), 10)) {
-                // CraftBukkit end
                     int i = MathHelper.floor(this.locX);
                     int j = MathHelper.floor(this.locY);
                     int k = MathHelper.floor(this.locZ);
@@ -122,7 +121,7 @@ public class EntityWeatherStorm extends EntityWeather {
                 entity.a(this);
             }
 
-            this.world.i = 2;
+            this.world.n = 2;
         }
     }
 
diff --git a/src/main/java/net/minecraft/server/EntityZombie.java b/src/main/java/net/minecraft/server/EntityZombie.java
index 4651e052b7..0ed75a27cb 100644
--- a/src/main/java/net/minecraft/server/EntityZombie.java
+++ b/src/main/java/net/minecraft/server/EntityZombie.java
@@ -10,7 +10,7 @@ public class EntityZombie extends EntityMonster {
     public EntityZombie(World world) {
         super(world);
         this.texture = "/mob/zombie.png";
-        this.aA = 0.5F;
+        this.aD = 0.5F;
         this.damage = 5;
     }
 
diff --git a/src/main/java/net/minecraft/server/InventoryPlayer.java b/src/main/java/net/minecraft/server/InventoryPlayer.java
index 3ae8427cbf..78a26bee1c 100644
--- a/src/main/java/net/minecraft/server/InventoryPlayer.java
+++ b/src/main/java/net/minecraft/server/InventoryPlayer.java
@@ -41,7 +41,7 @@ public class InventoryPlayer implements IInventory {
         return -1;
     }
 
-    private int c(ItemStack itemstack) {
+    private int d(ItemStack itemstack) {
         for (int i = 0; i < this.items.length; ++i) {
             if (this.items[i] != null && this.items[i].id == itemstack.id && this.items[i].c() && this.items[i].count < this.items[i].b() && this.items[i].count < this.getMaxStackSize() && (!this.items[i].e() || this.items[i].getData() == itemstack.getData())) {
                 return i;
@@ -61,10 +61,10 @@ public class InventoryPlayer implements IInventory {
         return -1;
     }
 
-    private int d(ItemStack itemstack) {
+    private int e(ItemStack itemstack) {
         int i = itemstack.id;
         int j = itemstack.count;
-        int k = this.c(itemstack);
+        int k = this.d(itemstack);
 
         if (k < 0) {
             k = this.k();
@@ -100,8 +100,8 @@ public class InventoryPlayer implements IInventory {
 
     public void f() {
         for (int i = 0; i < this.items.length; ++i) {
-            if (this.items[i] != null && this.items[i].b > 0) {
-                --this.items[i].b;
+            if (this.items[i] != null) {
+                this.items[i].a(this.d.world, this.d, i, this.itemInHandIndex == i);
             }
         }
     }
@@ -121,21 +121,25 @@ public class InventoryPlayer implements IInventory {
     }
 
     public boolean canHold(ItemStack itemstack) {
-        if (!itemstack.f()) {
-            itemstack.count = this.d(itemstack);
-            if (itemstack.count == 0) {
+        int i;
+
+        if (itemstack.f()) {
+            i = this.k();
+            if (i >= 0) {
+                this.items[i] = itemstack;
+                this.items[i].b = 5;
+                itemstack.count = 0;
                 return true;
+            } else {
+                return false;
             }
-        }
-
-        int i = this.k();
-
-        if (i >= 0) {
-            this.items[i] = itemstack;
-            this.items[i].b = 5;
-            return true;
         } else {
-            return false;
+            do {
+                i = itemstack.count;
+                itemstack.count = this.e(itemstack);
+            } while (itemstack.count > 0 && itemstack.count < i);
+
+            return itemstack.count < i;
         }
     }
 
@@ -286,7 +290,7 @@ public class InventoryPlayer implements IInventory {
 
                 j += k1;
                 k += i1;
-                int l1 = ((ItemArmor) this.armor[l].getItem()).bj;
+                int l1 = ((ItemArmor) this.armor[l].getItem()).bk;
 
                 i += l1;
             }
@@ -345,4 +349,22 @@ public class InventoryPlayer implements IInventory {
     public boolean a_(EntityHuman entityhuman) {
         return this.d.dead ? false : entityhuman.g(this.d) <= 64.0D;
     }
+
+    public boolean c(ItemStack itemstack) {
+        int i;
+
+        for (i = 0; i < this.armor.length; ++i) {
+            if (this.armor[i] != null && this.armor[i].c(itemstack)) {
+                return true;
+            }
+        }
+
+        for (i = 0; i < this.items.length; ++i) {
+            if (this.items[i] != null && this.items[i].c(itemstack)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
 }
diff --git a/src/main/java/net/minecraft/server/ItemBlock.java b/src/main/java/net/minecraft/server/ItemBlock.java
index 7273672041..b123fdf270 100644
--- a/src/main/java/net/minecraft/server/ItemBlock.java
+++ b/src/main/java/net/minecraft/server/ItemBlock.java
@@ -50,7 +50,9 @@ public class ItemBlock extends Item {
 
         if (itemstack.count == 0) {
             return false;
-        } else if (world.a(this.id, i, j, k, false)) {
+        } else if (j == 127 && Block.byId[this.id].material.isBuildable()) {
+            return false;
+        } else if (world.a(this.id, i, j, k, false, l)) {
             Block block = Block.byId[this.id];
 
             // CraftBukkit start - This executes the placement of the block
@@ -87,16 +89,17 @@ public class ItemBlock extends Item {
 
                         world.setTypeIdAndData(i, j, k, replacedBlockState.getTypeId(), replacedBlockState.getRawData());
                     }
+                    return true;
 
-                } else {
-                    world.update(i, j, k, this.id); // <-- world.setTypeIdAndData does this on success (tell the world)
-
-                    Block.byId[this.id].postPlace(world, i, j, k, l);
-                    Block.byId[this.id].postPlace(world, i, j, k, entityhuman);
-                    world.makeSound((double) ((float) i + 0.5F), (double) ((float) j + 0.5F), (double) ((float) k + 0.5F), block.stepSound.getName(), (block.stepSound.getVolume1() + 1.0F) / 2.0F, block.stepSound.getVolume2() * 0.8F);
-                    --itemstack.count;
                 }
+                world.update(i, j, k, this.id); // <-- world.setTypeIdAndData does this on success (tell the world)
+
                 // CraftBukkit end
+
+                Block.byId[this.id].postPlace(world, i, j, k, l);
+                Block.byId[this.id].postPlace(world, i, j, k, entityhuman);
+                world.makeSound((double) ((float) i + 0.5F), (double) ((float) j + 0.5F), (double) ((float) k + 0.5F), block.stepSound.getName(), (block.stepSound.getVolume1() + 1.0F) / 2.0F, block.stepSound.getVolume2() * 0.8F);
+                --itemstack.count;
             }
 
             return true;
@@ -106,6 +109,6 @@ public class ItemBlock extends Item {
     }
 
     public String a() {
-        return Block.byId[this.id].f();
+        return Block.byId[this.id].h();
     }
 }
diff --git a/src/main/java/net/minecraft/server/ItemBoat.java b/src/main/java/net/minecraft/server/ItemBoat.java
index a628a64327..b84d6656d8 100644
--- a/src/main/java/net/minecraft/server/ItemBoat.java
+++ b/src/main/java/net/minecraft/server/ItemBoat.java
@@ -48,7 +48,11 @@ public class ItemBoat extends Item {
                     }
                     // CraftBukkit end
 
-                    world.addEntity(new EntityBoat(world, (double) ((float) i + 0.5F), (double) ((float) j + 1.5F), (double) ((float) k + 0.5F)));
+                    if (world.getTypeId(i, j, k) == Block.SNOW.id) {
+                        --j;
+                    }
+
+                    world.addEntity(new EntityBoat(world, (double) ((float) i + 0.5F), (double) ((float) j + 1.0F), (double) ((float) k + 0.5F)));
                 }
 
                 --itemstack.count;
diff --git a/src/main/java/net/minecraft/server/ItemDoor.java b/src/main/java/net/minecraft/server/ItemDoor.java
index 26ade7b88b..c66555c07f 100644
--- a/src/main/java/net/minecraft/server/ItemDoor.java
+++ b/src/main/java/net/minecraft/server/ItemDoor.java
@@ -74,20 +74,25 @@ public class ItemDoor extends Item {
 
                 BlockState blockState = CraftBlockState.getBlockState(world, i, j, k); // CraftBukkit
 
-                world.setTypeId(i, j, k, block.id);
-                world.setData(i, j, k, i1);
+                world.o = true;
+                world.setTypeIdAndData(i, j, k, block.id, i1);
 
                 // CraftBukkit start - bed
+                world.o = false;
+                world.applyPhysics(i, j, k, block.id);
                 BlockPlaceEvent event = CraftEventFactory.callBlockPlaceEvent(world, entityhuman, blockState, clickedX, clickedY, clickedZ, block);
 
                 if (event.isCancelled() || !event.canBuild()) {
                     event.getBlockPlaced().setTypeIdAndData(blockState.getTypeId(), blockState.getRawData(), false);
                     return false;
                 }
-                // CraftBukkit end
 
-                world.setTypeId(i, j + 1, k, block.id);
-                world.setData(i, j + 1, k, i1 + 8);
+                world.o = true;
+                // CraftBukkit end
+                world.setTypeIdAndData(i, j + 1, k, block.id, i1 + 8);
+                world.o = false;
+                // world.applyPhysics(i, j, k, block.id); // CraftBukkit -- moved up
+                world.applyPhysics(i, j + 1, k, block.id);
                 --itemstack.count;
                 return true;
             }
diff --git a/src/main/java/net/minecraft/server/ItemHoe.java b/src/main/java/net/minecraft/server/ItemHoe.java
index e05efd2828..3c4de82b36 100644
--- a/src/main/java/net/minecraft/server/ItemHoe.java
+++ b/src/main/java/net/minecraft/server/ItemHoe.java
@@ -17,9 +17,9 @@ public class ItemHoe extends Item {
 
     public boolean a(ItemStack itemstack, EntityHuman entityhuman, World world, int i, int j, int k, int l) {
         int i1 = world.getTypeId(i, j, k);
-        Material material = world.getMaterial(i, j + 1, k);
+        int j1 = world.getTypeId(i, j + 1, k);
 
-        if ((material.isBuildable() || i1 != Block.GRASS.id) && i1 != Block.DIRT.id) {
+        if ((l == 0 || j1 != 0 || i1 != Block.GRASS.id) && i1 != Block.DIRT.id) {
             return false;
         } else {
             Block block = Block.SOIL;
@@ -42,21 +42,6 @@ public class ItemHoe extends Item {
                 // CraftBukkit end
 
                 itemstack.damage(1, entityhuman);
-                if (world.random.nextInt(8) == 0 && i1 == Block.GRASS.id) {
-                    byte b0 = 1;
-
-                    for (int j1 = 0; j1 < b0; ++j1) {
-                        float f = 0.7F;
-                        float f1 = world.random.nextFloat() * f + (1.0F - f) * 0.5F;
-                        float f2 = 1.2F;
-                        float f3 = world.random.nextFloat() * f + (1.0F - f) * 0.5F;
-                        EntityItem entityitem = new EntityItem(world, (double) ((float) i + f1), (double) ((float) j + f2), (double) ((float) k + f3), new ItemStack(Item.SEEDS));
-
-                        entityitem.pickupDelay = 10;
-                        world.addEntity(entityitem);
-                    }
-                }
-
                 return true;
             }
         }
diff --git a/src/main/java/net/minecraft/server/ItemInWorldManager.java b/src/main/java/net/minecraft/server/ItemInWorldManager.java
index 47c959d5c2..2f4a83c2fa 100644
--- a/src/main/java/net/minecraft/server/ItemInWorldManager.java
+++ b/src/main/java/net/minecraft/server/ItemInWorldManager.java
@@ -12,7 +12,7 @@ import org.bukkit.event.player.PlayerInteractEvent;
 
 public class ItemInWorldManager {
 
-    private World world;
+    private WorldServer world;
     public EntityHuman player;
     private float c = 0.0F;
     private int d;
@@ -26,8 +26,8 @@ public class ItemInWorldManager {
     private int l;
     private int m;
 
-    public ItemInWorldManager(World world) {
-        this.world = world;
+    public ItemInWorldManager(WorldServer worldserver) {
+        this.world = worldserver;
     }
 
     public void a() {
@@ -42,7 +42,7 @@ public class ItemInWorldManager {
 
                 if (f >= 1.0F) {
                     this.i = false;
-                    this.d(this.j, this.k, this.l);
+                    this.c(this.j, this.k, this.l);
                 }
             } else {
                 this.i = false;
@@ -50,33 +50,33 @@ public class ItemInWorldManager {
         }
     }
 
-    // CraftBukkit - added face
-    public void dig(int i, int j, int k, int face) {
+    public void dig(int i, int j, int k, int l) {
+        this.world.a((EntityHuman) null, i, j, k, l);
         this.d = (int) (System.currentTimeMillis() / 50); // CraftBukkit
-        int l = this.world.getTypeId(i, j, k);
+        int i1 = this.world.getTypeId(i, j, k);
 
         // CraftBukkit start
         // Swings at air do *NOT* exist.
-        if (l <= 0) {
+        if (i1 <= 0) {
             return;
         }
 
-        PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK , i, j, k, face, this.player.inventory.getItemInHand());
+        PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.LEFT_CLICK_BLOCK , i, j, k, l, this.player.inventory.getItemInHand());
 
         if (event.useInteractedBlock() == Event.Result.DENY) {
             // If we denied a door from opening, we need to send a correcting update to the client, as it already opened the door.
-            if (l == Block.WOODEN_DOOR.id) {
+            if (i1 == Block.WOODEN_DOOR.id) {
                 // For some reason *BOTH* the bottom/top part have to be marked updated.
                 boolean bottom = (this.world.getData(i, j, k) & 8) == 0;
                 ((EntityPlayer) this.player).netServerHandler.sendPacket(new Packet53BlockChange(i, j, k, this.world));
                 ((EntityPlayer) this.player).netServerHandler.sendPacket(new Packet53BlockChange(i, j + (bottom ? 1 : -1), k, this.world));
             }
         } else {
-            Block.byId[l].b(this.world, i, j, k, this.player);
+            Block.byId[i1].b(this.world, i, j, k, this.player);
         }
 
         // Handle hitting a block
-        float toolDamage = Block.byId[l].getDamage(this.player);
+        float toolDamage = Block.byId[i1].getDamage(this.player);
         if (event.useItemInHand() == Event.Result.DENY) {
             // If we 'insta destroyed' then the client needs to be informed.
             if (toolDamage > 1.0f) {
@@ -96,7 +96,7 @@ public class ItemInWorldManager {
 
         if (toolDamage >= 1.0F) {
             // CraftBukkit end
-            this.d(i, j, k);
+            this.c(i, j, k);
         } else {
             this.e = i;
             this.f = j;
@@ -104,7 +104,7 @@ public class ItemInWorldManager {
         }
     }
 
-    public void b(int i, int j, int k) {
+    public void a(int i, int j, int k) {
         if (i == this.e && j == this.f && k == this.g) {
             this.currentTick = (int) (System.currentTimeMillis() / 50); // CraftBukkit
             int l = this.currentTick - this.d;
@@ -115,7 +115,7 @@ public class ItemInWorldManager {
                 float f = block.getDamage(this.player) * (float) (l + 1);
 
                 if (f >= 0.7F) {
-                    this.d(i, j, k);
+                    this.c(i, j, k);
                 } else if (!this.i) {
                     this.i = true;
                     this.j = i;
@@ -133,7 +133,7 @@ public class ItemInWorldManager {
         this.c = 0.0F;
     }
 
-    public boolean c(int i, int j, int k) {
+    public boolean b(int i, int j, int k) {
         Block block = Block.byId[this.world.getTypeId(i, j, k)];
         int l = this.world.getData(i, j, k);
         boolean flag = this.world.setTypeId(i, j, k, 0);
@@ -145,7 +145,7 @@ public class ItemInWorldManager {
         return flag;
     }
 
-    public boolean d(int i, int j, int k) {
+    public boolean c(int i, int j, int k) {
         // CraftBukkit start
         if (this.player instanceof EntityPlayer) {
             CraftServer server = ((WorldServer) this.world).getServer();
@@ -163,7 +163,9 @@ public class ItemInWorldManager {
 
         int l = this.world.getTypeId(i, j, k);
         int i1 = this.world.getData(i, j, k);
-        boolean flag = this.c(i, j, k);
+
+        this.world.a(this.player, 2001, i, j, k, l + this.world.getData(i, j, k) * 256);
+        boolean flag = this.b(i, j, k);
         ItemStack itemstack = this.player.D();
 
         if (itemstack != null) {
diff --git a/src/main/java/net/minecraft/server/ItemReed.java b/src/main/java/net/minecraft/server/ItemReed.java
index ec4ddb63c3..2b55185e3d 100644
--- a/src/main/java/net/minecraft/server/ItemReed.java
+++ b/src/main/java/net/minecraft/server/ItemReed.java
@@ -50,7 +50,7 @@ public class ItemReed extends Item {
         if (itemstack.count == 0) {
             return false;
         } else {
-            if (world.a(this.id, i, j, k, false)) {
+            if (world.a(this.id, i, j, k, false, l)) {
                 Block block = Block.byId[this.id];
 
                 // CraftBukkit start - This executes the placement of the block
@@ -71,15 +71,17 @@ public class ItemReed extends Item {
                     if (event.isCancelled() || !event.canBuild()) {
                         // CraftBukkit - undo; this only has reed, repeater and pie blocks
                         world.setTypeIdAndData(i, j, k, replacedBlockState.getTypeId(), replacedBlockState.getRawData());
-                    } else {
-                        world.update(i, j, k, this.id); // <-- world.setTypeId does this on success (tell the world)
 
-                        Block.byId[this.id].postPlace(world, i, j, k, l);
-                        Block.byId[this.id].postPlace(world, i, j, k, entityhuman);
-                        world.makeSound((double) ((float) i + 0.5F), (double) ((float) j + 0.5F), (double) ((float) k + 0.5F), block.stepSound.getName(), (block.stepSound.getVolume1() + 1.0F) / 2.0F, block.stepSound.getVolume2() * 0.8F);
-                        --itemstack.count;
+                        return true;
                     }
+
+                    world.update(i, j, k, this.id); // <-- world.setTypeId does this on success (tell the world)
                     // CraftBukkit end
+
+                    Block.byId[this.id].postPlace(world, i, j, k, l);
+                    Block.byId[this.id].postPlace(world, i, j, k, entityhuman);
+                    world.makeSound((double) ((float) i + 0.5F), (double) ((float) j + 0.5F), (double) ((float) k + 0.5F), block.stepSound.getName(), (block.stepSound.getVolume1() + 1.0F) / 2.0F, block.stepSound.getVolume2() * 0.8F);
+                    --itemstack.count;
                 }
             }
 
diff --git a/src/main/java/net/minecraft/server/ItemStack.java b/src/main/java/net/minecraft/server/ItemStack.java
index 39f980c4d0..9d33763190 100644
--- a/src/main/java/net/minecraft/server/ItemStack.java
+++ b/src/main/java/net/minecraft/server/ItemStack.java
@@ -92,11 +92,11 @@ public final class ItemStack {
     }
 
     public boolean d() {
-        return Item.byId[this.id].d() > 0;
+        return Item.byId[this.id].e() > 0;
     }
 
     public boolean e() {
-        return Item.byId[this.id].c();
+        return Item.byId[this.id].d();
     }
 
     public boolean f() {
@@ -111,8 +111,12 @@ public final class ItemStack {
         return this.damage;
     }
 
+    public void b(int i) {
+        this.damage = i;
+    }
+
     public int i() {
-        return Item.byId[this.id].d();
+        return Item.byId[this.id].e();
     }
 
     public void damage(int i, Entity entity) {
@@ -168,10 +172,10 @@ public final class ItemStack {
     }
 
     public static boolean equals(ItemStack itemstack, ItemStack itemstack1) {
-        return itemstack == null && itemstack1 == null ? true : (itemstack != null && itemstack1 != null ? itemstack.c(itemstack1) : false);
+        return itemstack == null && itemstack1 == null ? true : (itemstack != null && itemstack1 != null ? itemstack.d(itemstack1) : false);
     }
 
-    private boolean c(ItemStack itemstack) {
+    private boolean d(ItemStack itemstack) {
         return this.count != itemstack.count ? false : (this.id != itemstack.id ? false : this.damage == itemstack.damage);
     }
 
@@ -186,4 +190,21 @@ public final class ItemStack {
     public String toString() {
         return this.count + "x" + Item.byId[this.id].a() + "@" + this.damage;
     }
+
+    public void a(World world, Entity entity, int i, boolean flag) {
+        if (this.b > 0) {
+            --this.b;
+        }
+
+        Item.byId[this.id].a(this, world, entity, i, flag);
+    }
+
+    public void b(World world, EntityHuman entityhuman) {
+        entityhuman.a(StatisticList.D[this.id], this.count);
+        Item.byId[this.id].c(this, world, entityhuman);
+    }
+
+    public boolean c(ItemStack itemstack) {
+        return this.id == itemstack.id && this.count == itemstack.count && this.damage == itemstack.damage;
+    }
 }
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 97fe250504..5223328f52 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -18,6 +18,7 @@ import java.io.PrintStream;
 import java.net.UnknownHostException;
 import jline.ConsoleReader;
 import joptsimple.OptionSet;
+import org.bukkit.World.Environment;
 import org.bukkit.craftbukkit.CraftServer;
 import org.bukkit.craftbukkit.LoggerOutputStream;
 import org.bukkit.craftbukkit.command.ColouredConsoleSender;
@@ -32,7 +33,7 @@ public class MinecraftServer implements Runnable, ICommandListener {
     public static HashMap b = new HashMap();
     public NetworkListenThread networkListenThread;
     public PropertyManager propertyManager;
-    // public WorldServer worldServer; // CraftBukkit - removed
+    // public WorldServer[] worldServer; // Craftbukkit - removed!
     public ServerConfigurationManager serverConfigurationManager;
     public ConsoleCommandHandler consoleCommandHandler; // CraftBukkit - made public
     private boolean isRunning = true;
@@ -42,7 +43,7 @@ public class MinecraftServer implements Runnable, ICommandListener {
     public int j;
     private List r = new ArrayList();
     private List s = Collections.synchronizedList(new ArrayList());
-    public EntityTracker tracker;
+    // public EntityTracker[] tracker = new EntityTracker[2]; // Craftbukkit - removed!
     public boolean onlineMode;
     public boolean spawnAnimals;
     public boolean pvpMode;
@@ -50,7 +51,7 @@ public class MinecraftServer implements Runnable, ICommandListener {
 
     // CraftBukkit start
     public int spawnProtection;
-    public List<WorldServer> worlds = new ArrayList<WorldServer>();
+    public List<WorldServer> worlds = new ArrayList<WorldServer>(); // TODO - REPLACE ABOVE
     public CraftServer server;
     public OptionSet options;
     public ColouredConsoleSender console;
@@ -85,7 +86,7 @@ public class MinecraftServer implements Runnable, ICommandListener {
         System.setErr(new PrintStream(new LoggerOutputStream(log, Level.SEVERE), true));
         // CraftBukkit end
 
-        log.info("Starting minecraft server version Beta 1.5_02");
+        log.info("Starting minecraft server version Beta 1.6.2");
         if (Runtime.getRuntime().maxMemory() / 1024L / 1024L < 512L) {
             log.warning("**** NOT ENOUGH RAM!");
             log.warning("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\"");
@@ -127,7 +128,7 @@ public class MinecraftServer implements Runnable, ICommandListener {
         }
 
         this.serverConfigurationManager = new ServerConfigurationManager(this);
-        this.tracker = new EntityTracker(this);
+        // Craftbukkit - removed trackers
         long j = System.nanoTime();
         String s1 = this.propertyManager.getString("level-name", "world");
         String s2 = this.propertyManager.getString("level-seed", "");
@@ -159,46 +160,56 @@ public class MinecraftServer implements Runnable, ICommandListener {
             convertable.convert(s, new ConvertProgressUpdater(this));
         }
 
-        log.info("Preparing start region");
+        // Craftbukkit start
+        for (int j = 0; j < (this.propertyManager.getBoolean("allow-nether", true) ? 2 : 1); ++j) {
+            WorldServer world;
+            int dimension = j == 0 ? 0 : -1;
 
-        // CraftBukkit start
-        WorldServer world = new WorldServer(this, new ServerNBTManager(new File("."), s, true), s, this.propertyManager.getBoolean("hellworld", false) ? -1 : 0, i);
-        world.addIWorldAccess((IWorldAccess)new WorldManager(this, world));
-        world.spawnMonsters = this.propertyManager.getBoolean("spawn-monsters", true) ? 1 : 0;
-        world.setSpawnFlags(this.propertyManager.getBoolean("spawn-monsters", true), this.spawnAnimals);
-        this.serverConfigurationManager.setPlayerFileData(world);
-        worlds.add(world);
-        // CraftBukkit end
+            if (j == 0) {
+                world = new WorldServer(this, new ServerNBTManager(new File("."), s, true), s, dimension, i);
+            } else {
+                String name = s + "_" + Environment.getEnvironment(dimension).toString().toLowerCase();
+                world = new SecondaryWorldServer(this, new ServerNBTManager(new File("."), name, true), name, dimension, i, worlds.get(0));
+            }
+
+            world.tracker = new EntityTracker(this, dimension);
+            world.addIWorldAccess(new WorldManager(this, world));
+            world.spawnMonsters = this.propertyManager.getBoolean("spawn-monsters", true) ? 1 : 0;
+            world.setSpawnFlags(this.propertyManager.getBoolean("spawn-monsters", true), this.spawnAnimals);
+            worlds.add(world);
+            this.serverConfigurationManager.setPlayerFileData(worlds.toArray(new WorldServer[0]));
+        }
 
         short short1 = 196;
-        long j = System.currentTimeMillis();
-        ChunkCoordinates chunkcoordinates = world.getSpawn(); // CraftBukkit
+        long k = System.currentTimeMillis();
 
-        for (int k = -short1; k <= short1 && this.isRunning; k += 16) {
-            for (int l = -short1; l <= short1 && this.isRunning; l += 16) {
-                long i1 = System.currentTimeMillis();
+        for (int l = 0; l < this.worlds.size(); ++l) { // Craftbukkit
+            log.info("Preparing start region for level " + l);
+            WorldServer worldserver = this.worlds.get(l); // Craftbukkit
+            ChunkCoordinates chunkcoordinates = worldserver.getSpawn();
 
-                if (i1 < j) {
-                    j = i1;
-                }
+            for (int i1 = -short1; i1 <= short1 && this.isRunning; i1 += 16) {
+                for (int j1 = -short1; j1 <= short1 && this.isRunning; j1 += 16) {
+                    long k1 = System.currentTimeMillis();
 
-                if (i1 > j + 1000L) {
-                    int j1 = (short1 * 2 + 1) * (short1 * 2 + 1);
-                    int k1 = (k + short1) * (short1 * 2 + 1) + l + 1;
+                    if (k1 < k) {
+                        k = k1;
+                    }
 
-                    this.a("Preparing spawn area", k1 * 100 / j1);
-                    j = i1;
-                }
+                    if (k1 > k + 1000L) {
+                        int l1 = (short1 * 2 + 1) * (short1 * 2 + 1);
+                        int i2 = (i1 + short1) * (short1 * 2 + 1) + j1 + 1;
 
-                // CraftBukkit start
-                for (WorldServer worldserver: worlds) {
-                    world.chunkProviderServer.getChunkAt(chunkcoordinates.x + k >> 4, chunkcoordinates.z + l >> 4);
+                        this.a("Preparing spawn area", i2 * 100 / l1);
+                        k = k1;
+                    }
 
-                    while (world.doLighting() && this.isRunning) {
+                    worldserver.chunkProviderServer.getChunkAt(chunkcoordinates.x + i1 >> 4, chunkcoordinates.z + j1 >> 4);
+
+                    while (worldserver.doLighting() && this.isRunning) {
                         ;
                     }
                 }
-                // CraftBukkit end
             }
         }
 
@@ -221,19 +232,19 @@ public class MinecraftServer implements Runnable, ICommandListener {
     void saveChunks() { // CraftBukkit - private -> default
         log.info("Saving chunks");
 
-        // CraftBukkit start
-        for (WorldServer world: worlds) {
-            world.save(true, (IProgressUpdate) null);
-            world.saveLevel();
+        // Craftbukkit start
+        for (int i = 0; i < this.worlds.size(); ++i) {
+            WorldServer worldserver = this.worlds.get(i);
 
-            WorldSaveEvent event = new WorldSaveEvent(world.getWorld());
+            worldserver.save(true, (IProgressUpdate) null);
+            worldserver.saveLevel();
+
+            WorldSaveEvent event = new WorldSaveEvent(worldserver.getWorld());
             server.getPluginManager().callEvent(event);
         }
-        // CraftBukkit end
-
-        // CraftBukkit start - player data should be saved whenever a save happens and ONLY if saving is enabled.
-        WorldServer wserver = this.worlds.get(0);
-        if (!wserver.y) {
+        
+        WorldServer world = this.worlds.get(0);
+        if (!world.E) {
             this.serverConfigurationManager.savePlayers();
         }
         // CraftBukkit end
@@ -251,9 +262,15 @@ public class MinecraftServer implements Runnable, ICommandListener {
             this.serverConfigurationManager.savePlayers();
         }
 
-        if (this.worlds.size() > 0) { // CraftBukkit
-            this.saveChunks();
+        // CraftBukkit start
+        for (int i = 0; i < this.worlds.size(); ++i) {
+            WorldServer worldserver = this.worlds.get(i);
+
+            if (worldserver != null) {
+                this.saveChunks();
+            }
         }
+        // CraftBukkit end
     }
 
     public void a() {
@@ -281,8 +298,7 @@ public class MinecraftServer implements Runnable, ICommandListener {
 
                     j += l;
                     i = k;
-                    // CraftBukkit - TODO - Replace with loop?
-                    if (this.worlds.size() > 0 && this.worlds.get(0).everyoneDeeplySleeping()) {
+                    if (this.worlds.get(0).everyoneDeeplySleeping()) { // Craftbukkit
                         this.h();
                         j = 0L;
                     } else {
@@ -354,29 +370,35 @@ public class MinecraftServer implements Runnable, ICommandListener {
         Vec3D.a();
         ++this.ticks;
 
-        // CraftBukkit start
-        if (this.ticks % 20 == 0) {
-            for (int i = 0; i < this.serverConfigurationManager.players.size(); ++i) {
-                EntityPlayer entityplayer = (EntityPlayer) this.serverConfigurationManager.players.get(i);
-                entityplayer.netServerHandler.sendPacket(new Packet4UpdateTime(entityplayer.world.getTime()));
+        for (j = 0; j < this.worlds.size(); ++j) { // Craftbukkit
+            WorldServer worldserver = this.worlds.get(j); // Craftbukkit
+
+            if (this.ticks % 20 == 0) {
+                // Craftbukkit start
+                for (int i = 0; i < this.serverConfigurationManager.players.size(); ++i) {
+                    EntityPlayer entityplayer = (EntityPlayer) this.serverConfigurationManager.players.get(i);
+                    entityplayer.netServerHandler.sendPacket(new Packet4UpdateTime(entityplayer.world.getTime()));
+                }
+                // Craftbukkit end
             }
-        }
 
-        ((CraftScheduler) server.getScheduler()).mainThreadHeartbeat(this.ticks);
+            worldserver.doTick();
 
-        for (WorldServer world: worlds) {
-            world.doTick();
-
-            while (world.doLighting()) {
+            while (worldserver.doLighting()) {
                 ;
             }
 
-            world.cleanUp();
+            worldserver.cleanUp();
         }
-        // CraftBukkit end
+
         this.networkListenThread.a();
         this.serverConfigurationManager.b();
-        this.tracker.a();
+
+        // Craftbukkit start
+        for (j = 0; j < this.worlds.size(); ++j) {
+            this.worlds.get(j).tracker.a();
+        }
+        // Craftbukkit end
 
         for (j = 0; j < this.r.size(); ++j) {
             ((IUpdatePlayerListBox) this.r.get(j)).a();
@@ -410,7 +432,7 @@ public class MinecraftServer implements Runnable, ICommandListener {
         StatisticList.a();
 
         try {
-            MinecraftServer minecraftserver = new MinecraftServer(options);
+            MinecraftServer minecraftserver = new MinecraftServer(options); // CraftBukkit pass in the options
 
             // CraftBukkit - remove gui
 
@@ -436,6 +458,14 @@ public class MinecraftServer implements Runnable, ICommandListener {
         return "CONSOLE";
     }
 
+    public WorldServer a(int i) {
+        return i == -1 ? this.worlds.get(1) : this.worlds.get(0); // Craftbukkit
+    }
+
+    public EntityTracker b(int i) {
+        return a(i).tracker; // Craftbukkit
+    }
+
     public static boolean isRunning(MinecraftServer minecraftserver) {
         return minecraftserver.isRunning;
     }
diff --git a/src/main/java/net/minecraft/server/NetLoginHandler.java b/src/main/java/net/minecraft/server/NetLoginHandler.java
index 2b5f86eb73..aa2637eedd 100644
--- a/src/main/java/net/minecraft/server/NetLoginHandler.java
+++ b/src/main/java/net/minecraft/server/NetLoginHandler.java
@@ -19,7 +19,7 @@ public class NetLoginHandler extends NetHandler {
     public NetLoginHandler(MinecraftServer minecraftserver, Socket socket, String s) {
         this.server = minecraftserver;
         this.networkManager = new NetworkManager(socket, s, this);
-        this.networkManager.d = 0;
+        this.networkManager.f = 0;
     }
 
     // CraftBukkit start
@@ -37,7 +37,7 @@ public class NetLoginHandler extends NetHandler {
         if (this.f++ == 600) {
             this.disconnect("Took too long to log in");
         } else {
-            this.networkManager.a();
+            this.networkManager.b();
         }
     }
 
@@ -45,7 +45,7 @@ public class NetLoginHandler extends NetHandler {
         try {
             a.info("Disconnecting " + this.b() + ": " + s);
             this.networkManager.a((Packet) (new Packet255KickDisconnect(s)));
-            this.networkManager.c();
+            this.networkManager.d();
             this.c = true;
         } catch (Exception exception) {
             exception.printStackTrace();
@@ -63,8 +63,8 @@ public class NetLoginHandler extends NetHandler {
 
     public void a(Packet1Login packet1login) {
         this.g = packet1login.name;
-        if (packet1login.a != 11) {
-            if (packet1login.a > 11) {
+        if (packet1login.a != 13) {
+            if (packet1login.a > 13) {
                 this.disconnect("Outdated server!");
             } else {
                 this.disconnect("Outdated client!");
@@ -82,21 +82,21 @@ public class NetLoginHandler extends NetHandler {
         EntityPlayer entityplayer = this.server.serverConfigurationManager.a(this, packet1login.name);
 
         if (entityplayer != null) {
+            this.server.serverConfigurationManager.b(entityplayer);
+            entityplayer.a((World) this.server.a(entityplayer.dimension));
             a.info(this.b() + " logged in with entity id " + entityplayer.id + " at (" + entityplayer.locX + ", " + entityplayer.locY + ", " + entityplayer.locZ + ")");
-            ChunkCoordinates chunkcoordinates = entityplayer.world.getSpawn(); // CraftBukkit
+            WorldServer worldserver = this.server.a(entityplayer.dimension);
+            ChunkCoordinates chunkcoordinates = worldserver.getSpawn();
             NetServerHandler netserverhandler = new NetServerHandler(this.server, this.networkManager, entityplayer);
 
-            netserverhandler.sendPacket(new Packet1Login("", entityplayer.id, entityplayer.world.getSeed(), (byte) entityplayer.world.worldProvider.dimension)); // CraftBukkit
+            netserverhandler.sendPacket(new Packet1Login("", entityplayer.id, worldserver.getSeed(), (byte) worldserver.worldProvider.dimension));
             netserverhandler.sendPacket(new Packet6SpawnPosition(chunkcoordinates.x, chunkcoordinates.y, chunkcoordinates.z));
-            if (((WorldServer) entityplayer.world).v()) { // CraftBukkit
-                netserverhandler.sendPacket(new Packet70Bed(1));
-            }
-
+            this.server.serverConfigurationManager.a(entityplayer, worldserver);
             // this.server.serverConfigurationManager.sendAll(new Packet3Chat("\u00A7e" + entityplayer.name + " joined the game."));  // CraftBukkit - message moved to join event
-            this.server.serverConfigurationManager.a(entityplayer);
+            this.server.serverConfigurationManager.c(entityplayer);
             netserverhandler.a(entityplayer.locX, entityplayer.locY, entityplayer.locZ, entityplayer.yaw, entityplayer.pitch);
             this.server.networkListenThread.a(netserverhandler);
-            netserverhandler.sendPacket(new Packet4UpdateTime(entityplayer.world.getTime())); // CraftBukkit
+            netserverhandler.sendPacket(new Packet4UpdateTime(worldserver.getTime()));
             entityplayer.syncInventory();
         }
 
diff --git a/src/main/java/net/minecraft/server/NetServerHandler.java b/src/main/java/net/minecraft/server/NetServerHandler.java
index b6fa2d15df..8ad7bd4492 100644
--- a/src/main/java/net/minecraft/server/NetServerHandler.java
+++ b/src/main/java/net/minecraft/server/NetServerHandler.java
@@ -72,7 +72,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
 
     public void a() {
         this.i = false;
-        this.networkManager.a();
+        this.networkManager.b();
         if (this.f - this.g > 20) {
             this.sendPacket(new Packet0KeepAlive());
         }
@@ -88,8 +88,9 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
             return;
         }
         // Send the possibly modified leave message
-        this.sendPacket(new Packet255KickDisconnect(event.getReason()));
-        this.networkManager.c();
+        s = event.getReason();
+        this.sendPacket(new Packet255KickDisconnect(s));
+        this.networkManager.d();
         leaveMessage = event.getLeaveMessage();
         if (leaveMessage != null) {
             this.minecraftServer.serverConfigurationManager.sendAll(new Packet3Chat(leaveMessage));
@@ -105,6 +106,8 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
     }
 
     public void a(Packet10Flying packet10flying) {
+        WorldServer worldserver = this.minecraftServer.a(this.player.dimension);
+
         this.i = true;
         double d0;
 
@@ -120,7 +123,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
         Location from = new Location(player.getWorld(), lastPosX, lastPosY, lastPosZ, lastYaw, lastPitch);
         Location to = player.getLocation();
 
-        // Prevent 40 event-calls for less than a single pixel of movement >.>
+        // Prevent 40 event-calls for less than b single pixel of movement >.>
         double delta = Math.pow(this.lastPosX - this.x, 2) + Math.pow(this.lastPosY - this.y, 2) + Math.pow(this.lastPosZ - this.z, 2);
         float deltaAngle = Math.abs(this.lastYaw - this.player.yaw) +  Math.abs(this.lastPitch - this.player.pitch);
 
@@ -217,20 +220,18 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
                 this.player.motX = d5;
                 this.player.motZ = d4;
                 if (this.player.vehicle != null) {
-                    // CraftBukkit
-                    ((WorldServer) this.player.world).vehicleEnteredWorld(this.player.vehicle, true);
+                    worldserver.vehicleEnteredWorld(this.player.vehicle, true);
                 }
 
                 if (this.player.vehicle != null) {
                     this.player.vehicle.f();
                 }
 
-                this.minecraftServer.serverConfigurationManager.b(this.player);
+                this.minecraftServer.serverConfigurationManager.d(this.player);
                 this.x = this.player.locX;
                 this.y = this.player.locY;
                 this.z = this.player.locZ;
-                // CraftBukkit
-                ((WorldServer) this.player.world).playerJoinedWorld(this.player);
+                worldserver.playerJoinedWorld(this.player);
                 return;
             }
 
@@ -271,8 +272,12 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
             }
 
             this.player.a(true);
-            this.player.bn = 0.0F;
+            this.player.bq = 0.0F;
             this.player.setLocation(this.x, this.y, this.z, f2, f3);
+            if (!this.m) {
+                return;
+            }
+
             d4 = d1 - this.player.locX;
             double d6 = d2 - this.player.locY;
             double d7 = d3 - this.player.locZ;
@@ -290,8 +295,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
             // CraftBukkit end
 
             float f4 = 0.0625F;
-            // CraftBukkit
-            boolean flag = ((WorldServer) this.player.world).getEntities(this.player, this.player.boundingBox.clone().shrink((double) f4, (double) f4, (double) f4)).size() == 0;
+            boolean flag = worldserver.getEntities(this.player, this.player.boundingBox.clone().shrink((double) f4, (double) f4, (double) f4)).size() == 0;
 
             this.player.move(d4, d6, d7);
             d4 = d1 - this.player.locX;
@@ -312,8 +316,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
             }
 
             this.player.setLocation(d1, d2, d3, f2, f3);
-            // CraftBukkit
-            boolean flag2 = ((WorldServer) this.player.world).getEntities(this.player, this.player.boundingBox.clone().shrink((double) f4, (double) f4, (double) f4)).size() == 0;
+            boolean flag2 = worldserver.getEntities(this.player, this.player.boundingBox.clone().shrink((double) f4, (double) f4, (double) f4)).size() == 0;
 
             if (flag && (flag1 || !flag2) && !this.player.isSleeping()) {
                 this.a(this.x, this.y, this.z, f2, f3);
@@ -322,8 +325,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
 
             AxisAlignedBB axisalignedbb = this.player.boundingBox.clone().b((double) f4, (double) f4, (double) f4).a(0.0D, -0.55D, 0.0D);
 
-            // CraftBukkit
-            if (!this.minecraftServer.o && !((WorldServer) this.player.world).b(axisalignedbb)) {
+            if (!this.minecraftServer.o && !worldserver.b(axisalignedbb)) {
                 if (d6 >= -0.03125D) {
                     ++this.h;
                     if (this.h > 80) {
@@ -337,9 +339,8 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
             }
 
             this.player.onGround = packet10flying.g;
-            this.minecraftServer.serverConfigurationManager.b(this.player);
+            this.minecraftServer.serverConfigurationManager.d(this.player);
             this.player.b(this.player.locY - d0, packet10flying.g);
-            // CraftBukkit end
         }
     }
 
@@ -398,11 +399,12 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
         }
         // CraftBukkit end
 
+        WorldServer worldserver = this.minecraftServer.a(this.player.dimension);
+
         if (packet14blockdig.e == 4) {
             this.player.C();
         } else {
-            // CraftBukkit
-            boolean flag = ((WorldServer) this.player.world).weirdIsOpCache = this.minecraftServer.serverConfigurationManager.isOp(this.player.name);
+            boolean flag = worldserver.weirdIsOpCache = worldserver.worldProvider.dimension != 0 || this.minecraftServer.serverConfigurationManager.isOp(this.player.name);
             boolean flag1 = false;
 
             if (packet14blockdig.e == 0) {
@@ -428,8 +430,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
                 }
             }
 
-            // CraftBukkit
-            ChunkCoordinates chunkcoordinates = ((WorldServer) this.player.world).getSpawn();
+            ChunkCoordinates chunkcoordinates = worldserver.getSpawn();
             int l = (int) MathHelper.abs((float) (i - chunkcoordinates.x));
             int i1 = (int) MathHelper.abs((float) (k - chunkcoordinates.z));
 
@@ -439,12 +440,17 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
 
             if (packet14blockdig.e == 0) {
                 // CraftBukkit
-                if (i1 > this.minecraftServer.spawnProtection || flag) {
+                if (i1 < this.minecraftServer.spawnProtection && !flag) {
+                    this.player.netServerHandler.sendPacket(new Packet53BlockChange(i, j, k, worldserver));
+                } else {
                     // CraftBukkit - add face argument
                     this.player.itemInWorldManager.dig(i, j, k, packet14blockdig.face);
                 }
             } else if (packet14blockdig.e == 2) {
-                this.player.itemInWorldManager.b(i, j, k);
+                this.player.itemInWorldManager.a(i, j, k);
+                if (worldserver.getTypeId(i, j, k) != 0) {
+                    this.player.netServerHandler.sendPacket(new Packet53BlockChange(i, j, k, worldserver));
+                }
             } else if (packet14blockdig.e == 3) {
                 double d4 = this.player.locX - ((double) i + 0.5D);
                 double d5 = this.player.locY - ((double) j + 0.5D);
@@ -452,24 +458,24 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
                 double d7 = d4 * d4 + d5 * d5 + d6 * d6;
 
                 if (d7 < 256.0D) {
-                    // CraftBukkit
-                    this.player.netServerHandler.sendPacket(new Packet53BlockChange(i, j, k, this.player.world));
+                    this.player.netServerHandler.sendPacket(new Packet53BlockChange(i, j, k, worldserver));
                 }
             }
 
-            // CraftBukkit
-            ((WorldServer) this.player.world).weirdIsOpCache = false;
+            worldserver.weirdIsOpCache = false;
         }
     }
 
     public void a(Packet15Place packet15place) {
+        WorldServer worldserver = this.minecraftServer.a(this.player.dimension);
+
         // CraftBukkit start
         if (this.player.dead) {
             return;
         }
 
-        // This is a horrible hack needed because the client sends 2 packets on 'right mouse click'
-        // aimed at a block. We shouldn't need to get the second packet if the data is handled
+        // This is b horrible hack needed because the client sends 2 packets on 'right mouse click'
+        // aimed at b block. We shouldn't need to get the second packet if the data is handled
         // but we cannot know what the client will do, so we might still get it
         //
         // If the time between packets is small enough, and the 'signature' similar, we discard the
@@ -488,13 +494,13 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
 
         // CraftBukkit - if rightclick decremented the item, always send the update packet.
         // this is not here for CraftBukkit's own functionality; rather it is to fix
-        // a notch bug where the item doesn't update correctly.
+        // b notch bug where the item doesn't update correctly.
         boolean always = false;
 
         // CraftBukkit end
 
         ItemStack itemstack = this.player.inventory.getItemInHand();
-        // boolean flag = this.minecraftServer.worldServer.weirdIsOpCache = this.minecraftServer.serverConfigurationManager.isOp(this.player.name);
+        boolean flag = worldserver.weirdIsOpCache = worldserver.worldProvider.dimension != 0 || this.minecraftServer.serverConfigurationManager.isOp(this.player.name);
 
         if (packet15place.face == 255) {
             if (itemstack == null) {
@@ -509,7 +515,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
             }
 
             // CraftBukkit - notch decrements the counter by 1 in the above method with food,
-            // snowballs and so forth, but he does it in a place that doesn't cause the
+            // snowballs and so forth, but he does it in b place that doesn't cause the
             // inventory update packet to get sent
             always = (itemstack.count != itemstackAmount);
             // CraftBukkit end
@@ -518,7 +524,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
             int j = packet15place.b;
             int k = packet15place.c;
             int l = packet15place.face;
-            ChunkCoordinates chunkcoordinates = ((WorldServer) this.player.world).getSpawn(); // CraftBukkit
+            ChunkCoordinates chunkcoordinates = worldserver.getSpawn();
             int i1 = (int) MathHelper.abs((float) (i - chunkcoordinates.x));
             int j1 = (int) MathHelper.abs((float) (k - chunkcoordinates.z));
 
@@ -526,17 +532,19 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
                 j1 = i1;
             }
 
-            // CraftBukkit start - spawn protection moved to ItemBlock!!!
-            // Check if we can actually do something over this large a distance
+            // CraftBukkit start - Check if we can actually do something over this large a distance
             Location eyeLoc = getPlayer().getEyeLocation();
             if (Math.pow(eyeLoc.getX() - i, 2) + Math.pow(eyeLoc.getY() - j, 2) + Math.pow(eyeLoc.getZ() - k, 2) > PLACE_DISTANCE_SQUARED) {
                 return;
             }
-
-            this.player.itemInWorldManager.interact(this.player, this.player.world, itemstack, i, j, k, l);
-            this.player.netServerHandler.sendPacket(new Packet53BlockChange(i, j, k, this.player.world));
+            flag = true; // spawn protection moved to ItemBlock!!!
             // CraftBukkit end
 
+            if (j1 > 16 || flag) {
+                this.player.itemInWorldManager.interact(this.player, worldserver, itemstack, i, j, k, l);
+            }
+
+            this.player.netServerHandler.sendPacket(new Packet53BlockChange(i, j, k, worldserver));
             if (l == 0) {
                 --j;
             }
@@ -561,10 +569,10 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
                 ++i;
             }
 
-            // CraftBukkit
-            this.player.netServerHandler.sendPacket(new Packet53BlockChange(i, j, k, this.player.world));
+            this.player.netServerHandler.sendPacket(new Packet53BlockChange(i, j, k, worldserver));
         }
 
+        itemstack = this.player.inventory.getItemInHand();
         if (itemstack != null && itemstack.count == 0) {
             this.player.inventory.items[this.player.inventory.itemInHandIndex] = null;
         }
@@ -580,12 +588,11 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
             this.sendPacket(new Packet103SetSlot(this.player.activeContainer.f, slot.a, this.player.inventory.getItemInHand()));
         }
 
-        // CraftBukkit
-        ((WorldServer) this.player.world).weirdIsOpCache = false;
+        worldserver.weirdIsOpCache = false;
     }
 
     public void a(String s, Object[] aobject) {
-        if (this.disconnected) return; // CraftBukkit - rarely it would send a disconnect line twice
+        if (this.disconnected) return; // CraftBukkit - rarely it would send b disconnect line twice
 
         a.info(this.player.name + " lost connection: " + s);
         // CraftBukkit start - we need to handle custom quit messages
@@ -655,30 +662,29 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
             }
 
             // CraftBukkit start
-            if (this.player.dead) {
-                return;
-            }
             chat(s);
         }
     }
 
-    public boolean chat(String msg) {
-        if (msg.startsWith("/")) {
-            this.handleCommand(msg);
-            return true;
-        } else {
-            Player player = getPlayer();
-            PlayerChatEvent event = new PlayerChatEvent(player, msg);
-            server.getPluginManager().callEvent(event);
-
-            if (event.isCancelled()) {
+    public boolean chat(String s) {
+        if (!this.player.dead) {
+            if (s.startsWith("/")) {
+                this.handleCommand(s);
                 return true;
-            }
+            } else {
+                Player player = getPlayer();
+                PlayerChatEvent event = new PlayerChatEvent(player, s);
+                server.getPluginManager().callEvent(event);
 
-            msg = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage());
-            a.info(msg);
-            for (Player recipient : event.getRecipients()) {
-                recipient.sendMessage(msg);
+                if (event.isCancelled()) {
+                    return true;
+                }
+
+                s = String.format(event.getFormat(), event.getPlayer().getDisplayName(), event.getMessage());
+                a.info(s);
+                for (Player recipient : event.getRecipients()) {
+                    recipient.sendMessage(s);
+                }
             }
         }
 
@@ -726,9 +732,10 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
                 }
             }
 
-        /* CraftBukkit start - No longer neaded as we have already handled it server.dispatchCommand above.
+        /* CraftBukkit start - No longer neaded av we have already handled it server.dispatchCommand above.
         } else {
             String s1;
+
             if (this.minecraftServer.serverConfigurationManager.isOp(this.player.name)) {
                 s1 = s.substring(1);
                 a.info(this.player.name + " issued server command: " + s1);
@@ -813,7 +820,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
     }
 
     public int b() {
-        return this.networkManager.d();
+        return this.networkManager.e();
     }
 
     public void sendMessage(String s) {
@@ -831,10 +838,10 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
         }
         // CraftBukkit end
 
-        // CraftBukkit
-        Entity entity = ((WorldServer) this.player.world).getEntity(packet7useentity.target);
+        WorldServer worldserver = this.minecraftServer.a(this.player.dimension);
+        Entity entity = worldserver.getEntity(packet7useentity.target);
 
-        if (entity != null && this.player.e(entity) && this.player.f(entity) < 4.0F) {
+        if (entity != null && this.player.e(entity) && this.player.g(entity) < 36.0D) {
             if (packet7useentity.c == 0) {
                 // CraftBukkit start
                 PlayerInteractEntityEvent piee = new PlayerInteractEntityEvent((Player) getPlayer(), entity.getBukkitEntity());
@@ -852,7 +859,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
 
     public void a(Packet9Respawn packet9respawn) {
         if (this.player.health <= 0) {
-            this.player = this.minecraftServer.serverConfigurationManager.d(this.player);
+            this.player = this.minecraftServer.serverConfigurationManager.a(this.player, 0);
 
             // CraftBukkit start
             CraftPlayer player = (CraftPlayer) getPlayer();
@@ -921,10 +928,12 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
         if (this.player.dead) {
             return;
         }
+        // CraftBukkit end
+        //
+        WorldServer worldserver = this.minecraftServer.a(this.player.dimension);
 
-        if (((WorldServer) this.player.world).isLoaded(packet130updatesign.x, packet130updatesign.y, packet130updatesign.z)) {
-            TileEntity tileentity = ((WorldServer) this.player.world).getTileEntity(packet130updatesign.x, packet130updatesign.y, packet130updatesign.z);
-            // CraftBukkit end
+        if (worldserver.isLoaded(packet130updatesign.x, packet130updatesign.y, packet130updatesign.z)) {
+            TileEntity tileentity = worldserver.getTileEntity(packet130updatesign.x, packet130updatesign.y, packet130updatesign.z);
 
             if (tileentity instanceof TileEntitySign) {
                 TileEntitySign tileentitysign = (TileEntitySign) tileentity;
@@ -979,9 +988,7 @@ public class NetServerHandler extends NetHandler implements ICommandListener {
                 // CraftBukkit end
 
                 tileentitysign1.update();
-
-                // CraftBukkit
-                ((WorldServer) this.player.world).notify(j, k, i);
+                worldserver.notify(j, k, i);
             }
         }
     }
diff --git a/src/main/java/net/minecraft/server/NetworkManager.java b/src/main/java/net/minecraft/server/NetworkManager.java
index 0c3b1d20a3..f463aa58bf 100644
--- a/src/main/java/net/minecraft/server/NetworkManager.java
+++ b/src/main/java/net/minecraft/server/NetworkManager.java
@@ -16,31 +16,34 @@ public class NetworkManager {
     public static final Object a = new Object();
     public static int b;
     public static int c;
-    private Object e = new Object();
+    private Object g = new Object();
     public Socket socket; // CraftBukkit - private -> public
-    private final SocketAddress g;
+    private final SocketAddress i;
     private DataInputStream input;
     private DataOutputStream output;
-    private boolean j = true;
-    private List k = Collections.synchronizedList(new ArrayList());
-    private List l = Collections.synchronizedList(new ArrayList());
+    private boolean l = true;
     private List m = Collections.synchronizedList(new ArrayList());
-    private NetHandler n;
-    private boolean o = false;
-    private Thread p;
-    private Thread q;
-    private boolean r = false;
-    private String s = "";
-    private Object[] t;
-    private int u = 0;
-    private int v = 0;
-    public int d = 0;
-    private int w = 50;
+    private List n = Collections.synchronizedList(new ArrayList());
+    private List o = Collections.synchronizedList(new ArrayList());
+    private NetHandler p;
+    private boolean q = false;
+    private Thread r;
+    private Thread s;
+    private boolean t = false;
+    private String u = "";
+    private Object[] v;
+    private int w = 0;
+    private int x = 0;
+    private transient boolean y = false;
+    public static int[] d = new int[256];
+    public static int[] e = new int[256];
+    public int f = 0;
+    private int z = 50;
 
     public NetworkManager(Socket socket, String s, NetHandler nethandler) {
         this.socket = socket;
-        this.g = socket.getRemoteSocketAddress();
-        this.n = nethandler;
+        this.i = socket.getRemoteSocketAddress();
+        this.p = nethandler;
 
         try {
             socket.setSoTimeout(30000);
@@ -54,86 +57,91 @@ public class NetworkManager {
             System.err.println(socketexception.getMessage());
         }
 
-        this.q = new NetworkReaderThread(this, s + " read thread");
-        this.p = new NetworkWriterThread(this, s + " write thread");
-        this.q.start();
-        this.p.start();
+        this.s = new NetworkReaderThread(this, s + " read thread");
+        this.r = new NetworkWriterThread(this, s + " write thread");
+        this.s.start();
+        this.r.start();
     }
 
     public void a(NetHandler nethandler) {
-        this.n = nethandler;
+        this.p = nethandler;
     }
 
     public void a(Packet packet) {
-        if (!this.o) {
-            Object object = this.e;
+        if (!this.q) {
+            Object object = this.g;
 
-            synchronized (this.e) {
-                this.v += packet.a() + 1;
+            synchronized (this.g) {
+                this.x += packet.a() + 1;
                 if (packet.k) {
-                    this.m.add(packet);
+                    this.o.add(packet);
                 } else {
-                    this.l.add(packet);
+                    this.n.add(packet);
                 }
             }
         }
     }
 
-    private void e() {
-        try {
-            boolean flag = true;
-            Object object;
-            Packet packet;
-
-            if (!this.l.isEmpty() && (this.d == 0 || System.currentTimeMillis() - ((Packet) this.l.get(0)).timestamp >= (long) this.d)) {
-                flag = false;
-                object = this.e;
-                synchronized (this.e) {
-                    packet = (Packet) this.l.remove(0);
-                    this.v -= packet.a() + 1;
-                }
-
-                Packet.a(packet, this.output);
-            }
-
-            // CraftBukkit - don't allow low priority packet to be sent unless it was placed in the queue before the first packet on the high priority queue
-            if ((flag || this.w-- <= 0) && !this.m.isEmpty() && (this.l.isEmpty() || ((Packet) this.l.get(0)).timestamp > ((Packet) this.m.get(0)).timestamp)) {
-                flag = false;
-                object = this.e;
-                synchronized (this.e) {
-                    packet = (Packet) this.m.remove(0);
-                    this.v -= packet.a() + 1;
-                }
-
-                Packet.a(packet, this.output);
-                this.w = 50;
-            }
-
-            if (flag) {
-                Thread.sleep(10L);
-            } else {
-                this.output.flush();
-            }
-        } catch (InterruptedException interruptedexception) {
-            ;
-        } catch (Exception exception) {
-            if (!this.r) {
-                this.a(exception);
-            }
-        }
-    }
-
     private void f() {
         try {
-            Packet packet = Packet.a(this.input, this.n.c());
+            Object object;
+            Packet packet;
+            int i;
+            int[] aint;
+
+            if (!this.n.isEmpty() && (this.f == 0 || System.currentTimeMillis() - ((Packet) this.n.get(0)).timestamp >= (long) this.f)) {
+                object = this.g;
+                synchronized (this.g) {
+                    packet = (Packet) this.n.remove(0);
+                    this.x -= packet.a() + 1;
+                }
+
+                Packet.a(packet, this.output);
+                aint = e;
+                i = packet.b();
+                aint[i] += packet.a();
+            }
+
+            // Craftbukkit - we used to enforce package priorities, we don't now. Do we need to redo this? - TODO
+            if (this.z-- <= 0 && !this.o.isEmpty() && (this.f == 0 || System.currentTimeMillis() - ((Packet) this.o.get(0)).timestamp >= (long) this.f)) {
+                object = this.g;
+                synchronized (this.g) {
+                    packet = (Packet) this.o.remove(0);
+                    this.x -= packet.a() + 1;
+                }
+
+                Packet.a(packet, this.output);
+                aint = e;
+                i = packet.b();
+                aint[i] += packet.a();
+                this.z = 50;
+            }
+        } catch (Exception exception) {
+            if (!this.t) {
+                this.a(exception);
+            }
+        }
+    }
+
+    public void a() {
+        this.y = true;
+    }
+
+    private void g() {
+        try {
+            Packet packet = Packet.a(this.input, this.p.c());
 
             if (packet != null) {
-                this.k.add(packet);
+                int[] aint = d;
+                int i = packet.b();
+
+                aint[i] += packet.a();
+                this.m.add(packet);
             } else {
                 this.a("disconnect.endOfStream", new Object[0]);
             }
         } catch (Exception exception) {
-            if (!this.r) {
+            if (!this.t) {
                 this.a(exception);
             }
         }
@@ -145,12 +153,12 @@ public class NetworkManager {
     }
 
     public void a(String s, Object... aobject) {
-        if (this.j) {
-            this.r = true;
-            this.s = s;
-            this.t = aobject;
+        if (this.l) {
+            this.t = true;
+            this.u = s;
+            this.v = aobject;
             (new NetworkMasterThread(this)).start();
-            this.j = false;
+            this.l = false;
 
             try {
                 this.input.close();
@@ -175,67 +183,80 @@ public class NetworkManager {
         }
     }
 
-    public void a() {
-        if (this.v > 1048576) {
+    public void b() {
+        if (this.x > 1048576) {
             this.a("disconnect.overflow", new Object[0]);
         }
 
-        if (this.k.isEmpty()) {
-            if (this.u++ == 1200) {
+        if (this.m.isEmpty()) {
+            if (this.w++ == 1200) {
                 this.a("disconnect.timeout", new Object[0]);
             }
         } else {
-            this.u = 0;
+            this.w = 0;
         }
 
         int i = 100;
 
-        while (!this.k.isEmpty() && i-- >= 0) {
-            Packet packet = (Packet) this.k.remove(0);
+        while (!this.m.isEmpty() && i-- >= 0) {
+            Packet packet = (Packet) this.m.remove(0);
 
-            packet.a(this.n);
+            packet.a(this.p);
         }
 
-        if (this.r && this.k.isEmpty()) {
-            this.n.a(this.s, this.t);
+        if (this.t && this.m.isEmpty()) {
+            this.p.a(this.u, this.v);
         }
     }
 
     public SocketAddress getSocketAddress() {
-        return this.g;
+        return this.i;
     }
 
-    public void c() {
-        this.o = true;
-        this.q.interrupt();
+    public void d() {
+        this.a();
+        this.q = true;
+        this.s.interrupt();
         (new ThreadMonitorConnection(this)).start();
     }
 
-    public int d() {
-        return this.m.size();
+    public int e() {
+        return this.o.size();
     }
 
     static boolean a(NetworkManager networkmanager) {
-        return networkmanager.j;
+        return networkmanager.l;
     }
 
     static boolean b(NetworkManager networkmanager) {
-        return networkmanager.o;
-    }
-
-    static void c(NetworkManager networkmanager) {
-        networkmanager.f();
-    }
-
-    static void d(NetworkManager networkmanager) {
-        networkmanager.e();
-    }
-
-    static Thread e(NetworkManager networkmanager) {
         return networkmanager.q;
     }
 
-    static Thread f(NetworkManager networkmanager) {
-        return networkmanager.p;
+    static void c(NetworkManager networkmanager) {
+        networkmanager.g();
+    }
+
+    static void d(NetworkManager networkmanager) {
+        networkmanager.f();
+    }
+
+    static boolean e(NetworkManager networkmanager) {
+        return networkmanager.y;
+    }
+
+    static boolean a(NetworkManager networkmanager, boolean flag) {
+        return networkmanager.y = flag;
+    }
+
+    static DataOutputStream f(NetworkManager networkmanager) {
+        return networkmanager.output;
+    }
+
+    static Thread g(NetworkManager networkmanager) {
+        return networkmanager.s;
+    }
+
+    static Thread h(NetworkManager networkmanager) {
+        return networkmanager.r;
     }
 }
diff --git a/src/main/java/net/minecraft/server/Packet.java b/src/main/java/net/minecraft/server/Packet.java
index 592d80d2ea..620017ebc3 100644
--- a/src/main/java/net/minecraft/server/Packet.java
+++ b/src/main/java/net/minecraft/server/Packet.java
@@ -185,7 +185,7 @@ public abstract class Packet {
         a(23, true, false, Packet23VehicleSpawn.class);
         a(24, true, false, Packet24MobSpawn.class);
         a(25, true, false, Packet25EntityPainting.class);
-        a(27, false, false, Packet27.class); // CraftBukkit - true -> false; disabled unused packet.
+        a(27, false, false, Packet27.class); // CraftBukkit - true -> false; disabled unused packet. TODO -- check if needed
         a(28, true, false, Packet28EntityVelocity.class);
         a(29, true, false, Packet29DestroyEntity.class);
         a(30, true, false, Packet30Entity.class);
@@ -202,6 +202,7 @@ public abstract class Packet {
         a(53, true, false, Packet53BlockChange.class);
         a(54, true, false, Packet54PlayNoteBlock.class);
         a(60, true, false, Packet60Explosion.class);
+        a(61, true, false, Packet61.class);
         a(70, true, false, Packet70Bed.class);
         a(71, true, false, Packet71Weather.class);
         a(100, true, false, Packet100OpenWindow.class);
@@ -212,6 +213,7 @@ public abstract class Packet {
         a(105, true, false, Packet105CraftProgressBar.class);
         a(106, true, true, Packet106Transaction.class);
         a(130, true, true, Packet130UpdateSign.class);
+        a(131, true, false, Packet131.class);
         a(200, true, false, Packet200Statistic.class);
         a(255, true, true, Packet255KickDisconnect.class);
         e = new HashMap();
diff --git a/src/main/java/net/minecraft/server/PlayerInstance.java b/src/main/java/net/minecraft/server/PlayerInstance.java
index 1f43e4b6ba..5f89809703 100644
--- a/src/main/java/net/minecraft/server/PlayerInstance.java
+++ b/src/main/java/net/minecraft/server/PlayerInstance.java
@@ -28,9 +28,7 @@ class PlayerInstance {
         this.chunkX = i;
         this.chunkZ = j;
         this.e = new ChunkCoordIntPair(i, j);
-
-        // CraftBukkit
-        playermanager.world.chunkProviderServer.getChunkAt(i, j);
+        playermanager.a().chunkProviderServer.getChunkAt(i, j);
     }
 
     public void a(EntityPlayer entityplayer) {
@@ -51,23 +49,22 @@ class PlayerInstance {
     public void b(EntityPlayer entityplayer) {
         if (!this.b.contains(entityplayer)) {
             // CraftBukkit - reduce console spam under certain conditions
-            // (new IllegalStateException("Failed to remove player. " + entityplayer + " isn\'t in chunk " + this.chunkX + ", " + this.chunkZ)).printStackTrace();
+            // (new IllegalStateException("Failed to remove player. " + entityplayer + " isn\'t in chunk " + this.bF + ", " + this.bH)).printStackTrace();
         } else {
             this.b.remove(entityplayer);
             if (this.b.size() == 0) {
                 long i = (long) this.chunkX + 2147483647L | (long) this.chunkZ + 2147483647L << 32;
 
-                PlayerManager.b(this.playerManager).b(i);
+                PlayerManager.a(this.playerManager).b(i);
                 if (this.dirtyCount > 0) {
-                    PlayerManager.c(this.playerManager).remove(this);
+                    PlayerManager.b(this.playerManager).remove(this);
                 }
 
-                // CraftBukkit
-                ((WorldServer) entityplayer.world).chunkProviderServer.queueUnload(this.chunkX, this.chunkZ);
+                this.playerManager.a().chunkProviderServer.queueUnload(this.chunkX, this.chunkZ);
             }
 
             entityplayer.f.remove(this.e);
-            // CraftBukkit - contains -> remove
+            // CraftBukkit - contains -> remove -- TODO  VERIFY!!!!
             if (entityplayer.g.remove(this.e)) {
                 entityplayer.netServerHandler.sendPacket(new Packet50PreChunk(this.chunkX, this.chunkZ, false));
             }
@@ -76,7 +73,7 @@ class PlayerInstance {
 
     public void a(int i, int j, int k) {
         if (this.dirtyCount == 0) {
-            PlayerManager.c(this.playerManager).add(this);
+            PlayerManager.b(this.playerManager).add(this);
             this.h = this.i = i;
             this.j = this.k = j;
             this.l = this.m = k;
@@ -130,6 +127,8 @@ class PlayerInstance {
     }
 
     public void a() {
+        WorldServer worldserver = this.playerManager.a();
+
         if (this.dirtyCount != 0) {
             int i;
             int j;
@@ -139,13 +138,10 @@ class PlayerInstance {
                 i = this.chunkX * 16 + this.h;
                 j = this.j;
                 k = this.chunkZ * 16 + this.l;
-
-                // CraftBukkit start
-                this.sendAll(new Packet53BlockChange(i, j, k, this.playerManager.world));
-                if (Block.isTileEntity[this.playerManager.world.getTypeId(i, j, k)]) {
-                    this.sendTileEntity(this.playerManager.world.getTileEntity(i, j, k));
+                this.sendAll(new Packet53BlockChange(i, j, k, worldserver));
+                if (Block.isTileEntity[worldserver.getTypeId(i, j, k)]) {
+                    this.sendTileEntity(worldserver.getTileEntity(i, j, k));
                 }
-                // CraftBukkit end
             } else {
                 int l;
 
@@ -159,17 +155,14 @@ class PlayerInstance {
                     int i1 = this.k - this.j + 2;
                     int j1 = this.m - this.l + 1;
 
-                    // CraftBukkit start
-                    this.sendAll(new Packet51MapChunk(i, j, k, l, i1, j1, this.playerManager.world));
-                    List list = this.playerManager.world.getTileEntities(i, j, k, i + l, j + i1, k + j1);
-                    // CraftBukkit end
+                    this.sendAll(new Packet51MapChunk(i, j, k, l, i1, j1, worldserver));
+                    List list = worldserver.getTileEntities(i, j, k, i + l, j + i1, k + j1);
 
                     for (int k1 = 0; k1 < list.size(); ++k1) {
                         this.sendTileEntity((TileEntity) list.get(k1));
                     }
                 } else {
-                    // CraftBukkit
-                    this.sendAll(new Packet52MultiBlockChange(this.chunkX, this.chunkZ, this.dirtyBlocks, this.dirtyCount, this.playerManager.world));
+                    this.sendAll(new Packet52MultiBlockChange(this.chunkX, this.chunkZ, this.dirtyBlocks, this.dirtyCount, worldserver));
 
                     for (i = 0; i < this.dirtyCount; ++i) {
                         // CraftBukkit start - Fixes TileEntity updates occurring upon a multi-block change; dirtyCount -> dirtyBlocks[i]
@@ -178,12 +171,10 @@ class PlayerInstance {
                         l = this.chunkZ * 16 + (this.dirtyBlocks[i] >> 8 & 15);
                         // CraftBukkit end
 
-                        // CraftBukkit start
-                        if (Block.isTileEntity[this.playerManager.world.getTypeId(j, k, l)]) {
+                        if (Block.isTileEntity[worldserver.getTypeId(j, k, l)]) {
                             // System.out.println("Sending!"); // CraftBukkit
-                            this.sendTileEntity(this.playerManager.world.getTileEntity(j, k, l));
+                            this.sendTileEntity(worldserver.getTileEntity(j, k, l));
                         }
-                        // CraftBukkit end
                     }
                 }
             }
diff --git a/src/main/java/net/minecraft/server/PlayerManager.java b/src/main/java/net/minecraft/server/PlayerManager.java
index 1195cedf83..fe17122274 100644
--- a/src/main/java/net/minecraft/server/PlayerManager.java
+++ b/src/main/java/net/minecraft/server/PlayerManager.java
@@ -5,20 +5,28 @@ import java.util.List;
 
 public class PlayerManager {
 
-    private List a = new ArrayList();
+    public List a = new ArrayList();
     private PlayerList b = new PlayerList();
     private List c = new ArrayList();
     private MinecraftServer server;
-    private final int[][] e = new int[][] { { 1, 0}, { 0, 1}, { -1, 0}, { 0, -1}};
+    private int e;
+    private int f;
+    private final int[][] g = new int[][] { { 1, 0}, { 0, 1}, { -1, 0}, { 0, -1}};
 
-    // CraftBukkit start
-    public WorldServer world;
+    public PlayerManager(MinecraftServer minecraftserver, int i, int j) {
+        if (j > 15) {
+            throw new IllegalArgumentException("Too big view radius!");
+        } else if (j < 3) {
+            throw new IllegalArgumentException("Too small view radius!");
+        } else {
+            this.f = j;
+            this.server = minecraftserver;
+            this.e = i;
+        }
+    }
 
-    // CraftBukkit - change of method signature
-    public PlayerManager(MinecraftServer minecraftserver, WorldServer world) {
-        this.world = world;
-        // CraftBukkit end
-        this.server = minecraftserver;
+    public WorldServer a() {
+        return this.server.a(this.e);
     }
 
     public void flush() {
@@ -58,32 +66,32 @@ public class PlayerManager {
         entityplayer.d = entityplayer.locX;
         entityplayer.e = entityplayer.locZ;
         int k = 0;
-        byte b0 = 10;
-        int l = 0;
+        int l = this.f;
         int i1 = 0;
+        int j1 = 0;
 
         this.a(i, j, true).a(entityplayer);
 
-        int j1;
+        int k1;
 
-        for (j1 = 1; j1 <= b0 * 2; ++j1) {
-            for (int k1 = 0; k1 < 2; ++k1) {
-                int[] aint = this.e[k++ % 4];
+        for (k1 = 1; k1 <= l * 2; ++k1) {
+            for (int l1 = 0; l1 < 2; ++l1) {
+                int[] aint = this.g[k++ % 4];
 
-                for (int l1 = 0; l1 < j1; ++l1) {
-                    l += aint[0];
-                    i1 += aint[1];
-                    this.a(i + l, j + i1, true).a(entityplayer);
+                for (int i2 = 0; i2 < k1; ++i2) {
+                    i1 += aint[0];
+                    j1 += aint[1];
+                    this.a(i + i1, j + j1, true).a(entityplayer);
                 }
             }
         }
 
         k %= 4;
 
-        for (j1 = 0; j1 < b0 * 2; ++j1) {
-            l += this.e[k][0];
-            i1 += this.e[k][1];
-            this.a(i + l, j + i1, true).a(entityplayer);
+        for (k1 = 0; k1 < l * 2; ++k1) {
+            i1 += this.g[k][0];
+            j1 += this.g[k][1];
+            this.a(i + i1, j + j1, true).a(entityplayer);
         }
 
         this.a.add(entityplayer);
@@ -93,8 +101,8 @@ public class PlayerManager {
         int i = (int) entityplayer.d >> 4;
         int j = (int) entityplayer.e >> 4;
 
-        for (int k = i - 10; k <= i + 10; ++k) {
-            for (int l = j - 10; l <= j + 10; ++l) {
+        for (int k = i - this.f; k <= i + this.f; ++k) {
+            for (int l = j - this.f; l <= j + this.f; ++l) {
                 PlayerInstance playerinstance = this.a(k, l, false);
 
                 if (playerinstance != null) {
@@ -110,7 +118,7 @@ public class PlayerManager {
         int i1 = i - k;
         int j1 = j - l;
 
-        return i1 >= -10 && i1 <= 10 ? j1 >= -10 && j1 <= 10 : false;
+        return i1 >= -this.f && i1 <= this.f ? j1 >= -this.f && j1 <= this.f : false;
     }
 
     public void movePlayer(EntityPlayer entityplayer) {
@@ -127,7 +135,7 @@ public class PlayerManager {
             int j1 = j - l;
 
             // CraftBukkit start
-            if (i1 > 10 || i1 < -10 || j1 > 10 || j1 < -10) {
+            if (i1 > this.f || i1 < -this.f || j1 > this.f || j1 < -this.f) {
                 this.removePlayer(entityplayer);
                 this.addPlayer(entityplayer);
                 return;
@@ -135,8 +143,8 @@ public class PlayerManager {
             // CraftBukkit end
 
             if (i1 != 0 || j1 != 0) {
-                for (int k1 = i - 10; k1 <= i + 10; ++k1) {
-                    for (int l1 = j - 10; l1 <= j + 10; ++l1) {
+                for (int k1 = i - this.f; k1 <= i + this.f; ++k1) {
+                    for (int l1 = j - this.f; l1 <= j + this.f; ++l1) {
                         if (!this.a(k1, l1, k, l)) {
                             this.a(k1, l1, true).a(entityplayer);
                         }
@@ -157,19 +165,15 @@ public class PlayerManager {
         }
     }
 
-    public int b() {
-        return 144;
+    public int c() {
+        return this.f * 16 - 16;
     }
 
-    static MinecraftServer a(PlayerManager playermanager) {
-        return playermanager.server;
-    }
-
-    static PlayerList b(PlayerManager playermanager) {
+    static PlayerList a(PlayerManager playermanager) {
         return playermanager.b;
     }
 
-    static List c(PlayerManager playermanager) {
+    static List b(PlayerManager playermanager) {
         return playermanager.c;
     }
 }
diff --git a/src/main/java/net/minecraft/server/ServerConfigurationManager.java b/src/main/java/net/minecraft/server/ServerConfigurationManager.java
index 8cc67376ea..4f433aa6e8 100644
--- a/src/main/java/net/minecraft/server/ServerConfigurationManager.java
+++ b/src/main/java/net/minecraft/server/ServerConfigurationManager.java
@@ -29,7 +29,7 @@ public class ServerConfigurationManager {
     public static Logger a = Logger.getLogger("Minecraft");
     public List players = new ArrayList();
     public MinecraftServer server; // CraftBukkit - private -> public
-    // public PlayerManager d; // CraftBukkit - removed!
+    private PlayerManager[] d = new PlayerManager[2];
     public int maxPlayers; // CraftBukkit - private -> public
     private Set banByName = new HashSet();
     private Set banByIP = new HashSet();
@@ -56,7 +56,10 @@ public class ServerConfigurationManager {
         this.k = minecraftserver.a("banned-ips.txt");
         this.l = minecraftserver.a("ops.txt");
         this.m = minecraftserver.a("white-list.txt");
-        // this.d = new PlayerManager(minecraftserver); // CraftBukkit - removed!
+        int i = minecraftserver.propertyManager.getInt("view-distance", 10);
+
+        this.d[0] = new PlayerManager(minecraftserver, 0, i);
+        this.d[1] = new PlayerManager(minecraftserver, -1, i);
         this.maxPlayers = minecraftserver.propertyManager.getInt("max-players", 20);
         this.o = minecraftserver.propertyManager.getBoolean("white-list", false);
         this.g();
@@ -69,27 +72,43 @@ public class ServerConfigurationManager {
         this.n();
     }
 
-    public void setPlayerFileData(WorldServer worldserver) {
+    public void setPlayerFileData(WorldServer[] aworldserver) {
         if (this.playerFileData != null) return; // CraftBukkit
-        this.playerFileData = worldserver.p().d();
-    }
-
-    public int a() {
-        return 144; // CraftBukkit - magic number from PlayerManager.b() (??)
+        this.playerFileData = aworldserver[0].p().d();
     }
 
     public void a(EntityPlayer entityplayer) {
-        this.players.add(entityplayer);
-        this.playerFileData.b(entityplayer);
-        // CraftBukkit start
-        ((WorldServer) entityplayer.world).chunkProviderServer.getChunkAt((int) entityplayer.locX >> 4, (int) entityplayer.locZ >> 4);
+        this.d[0].removePlayer(entityplayer);
+        this.d[1].removePlayer(entityplayer);
+        this.a(entityplayer.dimension).addPlayer(entityplayer);
+        WorldServer worldserver = this.server.a(entityplayer.dimension);
 
-        while (entityplayer.world.getEntities(entityplayer, entityplayer.boundingBox).size() != 0) {
+        worldserver.chunkProviderServer.getChunkAt((int) entityplayer.locX >> 4, (int) entityplayer.locZ >> 4);
+    }
+
+    public int a() {
+        return this.d[0].c();
+    }
+
+    private PlayerManager a(int i) {
+        return i == -1 ? this.d[1] : this.d[0];
+    }
+
+    public void b(EntityPlayer entityplayer) {
+        this.playerFileData.b(entityplayer);
+    }
+
+    public void c(EntityPlayer entityplayer) {
+        this.players.add(entityplayer);
+        WorldServer worldserver = this.server.a(entityplayer.dimension);
+
+        worldserver.chunkProviderServer.getChunkAt((int) entityplayer.locX >> 4, (int) entityplayer.locZ >> 4);
+
+        while (worldserver.getEntities(entityplayer, entityplayer.boundingBox).size() != 0) {
             entityplayer.setPosition(entityplayer.locX, entityplayer.locY + 1.0D, entityplayer.locZ);
         }
 
-        entityplayer.world.addEntity(entityplayer);
-
+        // CraftBukkit start
         PlayerJoinEvent playerJoinEvent = new PlayerJoinEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.name + " joined the game.");
         cserver.getPluginManager().callEvent(playerJoinEvent);
 
@@ -98,26 +117,28 @@ public class ServerConfigurationManager {
         if (joinMessage != null) {
             this.server.serverConfigurationManager.sendAll(new Packet3Chat(joinMessage));
         }
-
-        ((WorldServer) entityplayer.world).manager.addPlayer(entityplayer);
         // CraftBukkit end
+
+        worldserver.addEntity(entityplayer);
+        this.a(entityplayer.dimension).addPlayer(entityplayer);
     }
 
-    public void b(EntityPlayer entityplayer) {
-        ((WorldServer) entityplayer.world).manager.movePlayer(entityplayer); // CraftBukkit
+    public void d(EntityPlayer entityplayer) {
+        this.a(entityplayer.dimension).movePlayer(entityplayer);
     }
 
     public String disconnect(EntityPlayer entityplayer) { // CraftBukkit - changed return type
         // CraftBukkit start
         // Quitting must be before we do final save of data, in case plugins need to modify it
-        ((WorldServer) entityplayer.world).manager.removePlayer(entityplayer);
+        this.a(entityplayer.dimension).removePlayer(entityplayer);
         PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(entityplayer), "\u00A7e" + entityplayer.name + " left the game.");
         cserver.getPluginManager().callEvent(playerQuitEvent);
         // CraftBukkit end
 
         this.playerFileData.a(entityplayer);
-        entityplayer.world.kill(entityplayer); // CraftBukkit
+        this.server.a(entityplayer.dimension).kill(entityplayer);
         this.players.remove(entityplayer);
+        this.a(entityplayer.dimension).removePlayer(entityplayer);
 
         return playerQuitEvent.getQuitMessage(); // CraftBukkit
     }
@@ -127,26 +148,26 @@ public class ServerConfigurationManager {
         // Instead of kicking then returning, we need to store the kick reason
         // in the event, check with plugins to see if it's ok, and THEN kick
         // depending on the outcome. Also change any reference to this.e.c to entity.world
-        EntityPlayer entity = new EntityPlayer(this.server, this.server.worlds.get(0), s, new ItemInWorldManager(this.server.worlds.get(0)));
+        EntityPlayer entity = new EntityPlayer(this.server, this.server.a(0), s, new ItemInWorldManager(this.server.a(0)));
         Player player = (entity == null) ? null : (Player) entity.getBukkitEntity();
         PlayerLoginEvent event = new PlayerLoginEvent(player);
 
-        String s2 = netloginhandler.networkManager.getSocketAddress().toString();
+        String s1 = netloginhandler.networkManager.getSocketAddress().toString();
 
-        s2 = s2.substring(s2.indexOf("/") + 1);
-        s2 = s2.substring(0, s2.indexOf(":"));
+        s1 = s1.substring(s1.indexOf("/") + 1);
+        s1 = s1.substring(0, s1.indexOf(":"));
 
         if (this.banByName.contains(s.trim().toLowerCase())) {
             event.disallow(PlayerLoginEvent.Result.KICK_BANNED, "You are banned from this server!");
             // return null // CraftBukkit
         } else if (!this.isWhitelisted(s)) {
             event.disallow(PlayerLoginEvent.Result.KICK_WHITELIST, "You are not white-listed on this server!");
-        } else if (this.banByIP.contains(s2)) {
+        } else if (this.banByIP.contains(s1)) {
             event.disallow(PlayerLoginEvent.Result.KICK_BANNED, "Your IP address is banned from this server!");
         } else if (this.players.size() >= this.maxPlayers) {
             event.disallow(PlayerLoginEvent.Result.KICK_FULL, "The server is full!");
         } else {
-            event.disallow(PlayerLoginEvent.Result.ALLOWED, s2);
+            event.disallow(PlayerLoginEvent.Result.ALLOWED, s1);
         }
 
         cserver.getPluginManager().callEvent(event);
@@ -163,24 +184,24 @@ public class ServerConfigurationManager {
             }
         }
 
-        return new EntityPlayer(this.server, entity.world, s, new ItemInWorldManager(entity.world));
+        return new EntityPlayer(this.server, this.server.a(0), s, new ItemInWorldManager(this.server.a(0)));
         // CraftBukkit end
     }
 
-    public EntityPlayer d(EntityPlayer entityplayer) {
-        this.server.tracker.trackPlayer(entityplayer);
-        this.server.tracker.untrackEntity(entityplayer);
-        // CraftBukkit
-        ((WorldServer) entityplayer.world).manager.removePlayer(entityplayer);
+    public EntityPlayer a(EntityPlayer entityplayer, int i) {
+        this.server.b(entityplayer.dimension).trackPlayer(entityplayer);
+        this.server.b(entityplayer.dimension).untrackEntity(entityplayer);
+        this.a(entityplayer.dimension).removePlayer(entityplayer);
         this.players.remove(entityplayer);
-        // CraftBukkit
-        entityplayer.world.removeEntity(entityplayer);
+        this.server.a(entityplayer.dimension).removeEntity(entityplayer);
         ChunkCoordinates chunkcoordinates = entityplayer.K();
-        // CraftBukkit
-        EntityPlayer entityplayer1 = new EntityPlayer(this.server, entityplayer.world, entityplayer.name, new ItemInWorldManager(entityplayer.world));
+
+        entityplayer.dimension = i;
+        EntityPlayer entityplayer1 = new EntityPlayer(this.server, this.server.a(entityplayer.dimension), entityplayer.name, new ItemInWorldManager(this.server.a(entityplayer.dimension)));
 
         entityplayer1.id = entityplayer.id;
         entityplayer1.netServerHandler = entityplayer.netServerHandler;
+        WorldServer worldserver = this.server.a(entityplayer.dimension);
 
         // CraftBukkit start - transfer internal variables
         entityplayer1.displayName = entityplayer.displayName;
@@ -189,8 +210,7 @@ public class ServerConfigurationManager {
         // CraftBukkit end
 
         if (chunkcoordinates != null) {
-            // CraftBukkit
-            ChunkCoordinates chunkcoordinates1 = EntityHuman.getBed(entityplayer.world, chunkcoordinates);
+            ChunkCoordinates chunkcoordinates1 = EntityHuman.getBed(this.server.a(entityplayer.dimension), chunkcoordinates);
 
             if (chunkcoordinates1 != null) {
                 entityplayer1.setPositionRotation((double) ((float) chunkcoordinates1.x + 0.5F), (double) ((float) chunkcoordinates1.y + 0.1F), (double) ((float) chunkcoordinates1.z + 0.5F), 0.0F, 0.0F);
@@ -200,14 +220,6 @@ public class ServerConfigurationManager {
             }
         }
 
-        // CraftBukkit
-        ((WorldServer) entityplayer.world).chunkProviderServer.getChunkAt((int) entityplayer1.locX >> 4, (int) entityplayer1.locZ >> 4);
-
-        // CraftBukkit
-        while (entityplayer.world.getEntities(entityplayer1, entityplayer1.boundingBox).size() != 0) {
-            entityplayer1.setPosition(entityplayer1.locX, entityplayer1.locY + 1.0D, entityplayer1.locZ);
-        }
-
         // CraftBukkit start
         Player respawnPlayer = cserver.getPlayer(entityplayer);
         Location respawnLocation = new Location(respawnPlayer.getWorld(), entityplayer1.locX, entityplayer1.locY, entityplayer1.locZ, entityplayer1.yaw, entityplayer1.pitch);
@@ -215,42 +227,93 @@ public class ServerConfigurationManager {
         PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, respawnLocation);
         cserver.getPluginManager().callEvent(respawnEvent);
 
-        entityplayer1.world = ((CraftWorld) respawnEvent.getRespawnLocation().getWorld()).getHandle();
+        worldserver = ((CraftWorld)respawnEvent.getRespawnLocation().getWorld()).getHandle();
         entityplayer1.locX = respawnEvent.getRespawnLocation().getX();
         entityplayer1.locY = respawnEvent.getRespawnLocation().getY();
         entityplayer1.locZ = respawnEvent.getRespawnLocation().getZ();
         entityplayer1.yaw = respawnEvent.getRespawnLocation().getYaw();
         entityplayer1.pitch = respawnEvent.getRespawnLocation().getPitch();
-        entityplayer1.itemInWorldManager = new ItemInWorldManager(((CraftWorld) respawnEvent.getRespawnLocation().getWorld()).getHandle());
-        entityplayer1.itemInWorldManager.player = entityplayer1;
-        ((WorldServer) entityplayer1.world).chunkProviderServer.getChunkAt((int) entityplayer1.locX >> 4, (int) entityplayer1.locZ >> 4);
         // CraftBukkit end
 
-        entityplayer1.netServerHandler.sendPacket(new Packet9Respawn());
+        worldserver.chunkProviderServer.getChunkAt((int) entityplayer1.locX >> 4, (int) entityplayer1.locZ >> 4);
+
+        while (worldserver.getEntities(entityplayer1, entityplayer1.boundingBox).size() != 0) {
+            entityplayer1.setPosition(entityplayer1.locX, entityplayer1.locY + 1.0D, entityplayer1.locZ);
+        }
+
+        entityplayer1.netServerHandler.sendPacket(new Packet9Respawn((byte) entityplayer1.dimension));
         entityplayer1.netServerHandler.a(entityplayer1.locX, entityplayer1.locY, entityplayer1.locZ, entityplayer1.yaw, entityplayer1.pitch);
-        // CraftBukkit start
-        ((WorldServer) entityplayer1.world).manager.addPlayer(entityplayer1);
-        entityplayer.world.addEntity(entityplayer1);
-        // CraftBukkit end
+        this.a(entityplayer1, worldserver);
+        this.a(entityplayer1.dimension).addPlayer(entityplayer1);
+        worldserver.addEntity(entityplayer1);
         this.players.add(entityplayer1);
         entityplayer1.syncInventory();
         entityplayer1.w();
         return entityplayer1;
     }
 
-    public void b() {
-        // CraftBukkit start
-        for (WorldServer world: this.server.worlds) {
-            world.manager.flush();
+    public void f(EntityPlayer entityplayer) {
+        WorldServer worldserver = this.server.a(entityplayer.dimension);
+        boolean flag = false;
+        byte b0;
+
+        if (entityplayer.dimension == -1) {
+            b0 = 0;
+        } else {
+            b0 = -1;
         }
-        // CraftBukkit end
+
+        entityplayer.dimension = b0;
+        WorldServer worldserver1 = this.server.a(entityplayer.dimension);
+
+        entityplayer.netServerHandler.sendPacket(new Packet9Respawn((byte) entityplayer.dimension));
+        worldserver.removeEntity(entityplayer);
+        entityplayer.dead = false;
+        double d0 = entityplayer.locX;
+        double d1 = entityplayer.locZ;
+        double d2 = 8.0D;
+
+        if (entityplayer.dimension == -1) {
+            d0 /= d2;
+            d1 /= d2;
+            entityplayer.setPositionRotation(d0, entityplayer.locY, d1, entityplayer.yaw, entityplayer.pitch);
+            if (entityplayer.Q()) {
+                worldserver.entityJoinedWorld(entityplayer, false);
+            }
+        } else {
+            d0 *= d2;
+            d1 *= d2;
+            entityplayer.setPositionRotation(d0, entityplayer.locY, d1, entityplayer.yaw, entityplayer.pitch);
+            if (entityplayer.Q()) {
+                worldserver.entityJoinedWorld(entityplayer, false);
+            }
+        }
+
+        if (entityplayer.Q()) {
+            worldserver1.addEntity(entityplayer);
+            entityplayer.setPositionRotation(d0, entityplayer.locY, d1, entityplayer.yaw, entityplayer.pitch);
+            worldserver1.entityJoinedWorld(entityplayer, false);
+            worldserver1.chunkProviderServer.a = true;
+            (new PortalTravelAgent()).a(worldserver1, entityplayer);
+            worldserver1.chunkProviderServer.a = false;
+        }
+
+        this.a(entityplayer);
+        entityplayer.netServerHandler.a(entityplayer.locX, entityplayer.locY, entityplayer.locZ, entityplayer.yaw, entityplayer.pitch);
+        entityplayer.a((World) worldserver1);
+        this.a(entityplayer, worldserver1);
+        entityplayer.a(entityplayer.defaultContainer);
     }
 
-    // CraftBukkit start - changed signature
-    public void flagDirty(int i, int j, int k, WorldServer world) {
-        world.manager.flagDirty(i, j, k);
+    public void b() {
+        for (int i = 0; i < this.d.length; ++i) {
+            this.d[i].flush();
+        }
+    }
+
+    public void flagDirty(int i, int j, int k, int l) {
+        this.a(l).flagDirty(i, j, k);
     }
-    // CraftBukkit end
 
     public void sendAll(Packet packet) {
         for (int i = 0; i < this.players.size(); ++i) {
@@ -260,6 +323,16 @@ public class ServerConfigurationManager {
         }
     }
 
+    public void a(Packet packet, int i) {
+        for (int j = 0; j < this.players.size(); ++j) {
+            EntityPlayer entityplayer = (EntityPlayer) this.players.get(j);
+
+            if (entityplayer.dimension == i) {
+                entityplayer.netServerHandler.sendPacket(packet);
+            }
+        }
+    }
+
     public String c() {
         String s = "";
 
@@ -467,15 +540,22 @@ public class ServerConfigurationManager {
         }
     }
 
-    public void a(double d0, double d1, double d2, double d3, Packet packet) {
-        for (int i = 0; i < this.players.size(); ++i) {
-            EntityPlayer entityplayer = (EntityPlayer) this.players.get(i);
-            double d4 = d0 - entityplayer.locX;
-            double d5 = d1 - entityplayer.locY;
-            double d6 = d2 - entityplayer.locZ;
+    public void a(double d0, double d1, double d2, double d3, int i, Packet packet) {
+        this.a((EntityHuman) null, d0, d1, d2, d3, i, packet);
+    }
 
-            if (d4 * d4 + d5 * d5 + d6 * d6 < d3 * d3) {
-                entityplayer.netServerHandler.sendPacket(packet);
+    public void a(EntityHuman entityhuman, double d0, double d1, double d2, double d3, int i, Packet packet) {
+        for (int j = 0; j < this.players.size(); ++j) {
+            EntityPlayer entityplayer = (EntityPlayer) this.players.get(j);
+
+            if (entityplayer != entityhuman && entityplayer.dimension == i) {
+                double d4 = d0 - entityplayer.locX;
+                double d5 = d1 - entityplayer.locY;
+                double d6 = d2 - entityplayer.locZ;
+
+                if (d4 * d4 + d5 * d5 + d6 * d6 < d3 * d3) {
+                    entityplayer.netServerHandler.sendPacket(packet);
+                }
             }
         }
     }
@@ -528,4 +608,11 @@ public class ServerConfigurationManager {
     public void f() {
         this.m();
     }
+
+    public void a(EntityPlayer entityplayer, WorldServer worldserver) {
+        if (worldserver.v()) {
+            entityplayer.netServerHandler.sendPacket(new Packet4UpdateTime(worldserver.getTime()));
+            entityplayer.netServerHandler.sendPacket(new Packet70Bed(1));
+        }
+    }
 }
diff --git a/src/main/java/net/minecraft/server/Slot.java b/src/main/java/net/minecraft/server/Slot.java
index 94dba7b583..df1cfd7b15 100644
--- a/src/main/java/net/minecraft/server/Slot.java
+++ b/src/main/java/net/minecraft/server/Slot.java
@@ -51,8 +51,4 @@ public class Slot {
     public boolean a(IInventory iinventory, int i) {
         return iinventory == this.inventory && i == this.index;
     }
-
-    public boolean e() {
-        return false;
-    }
 }
diff --git a/src/main/java/net/minecraft/server/StatisticList.java b/src/main/java/net/minecraft/server/StatisticList.java
deleted file mode 100644
index 939f08f010..0000000000
--- a/src/main/java/net/minecraft/server/StatisticList.java
+++ /dev/null
@@ -1,186 +0,0 @@
-package net.minecraft.server;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-public class StatisticList {
-
-    protected static Map a = new HashMap();
-    public static List b = new ArrayList();
-    public static List c = new ArrayList();
-    public static List d = new ArrayList();
-    public static List e = new ArrayList();
-    public static Statistic f = (new CounterStatistic(1000, StatisticCollector.a("stat.startGame"))).e().d();
-    public static Statistic g = (new CounterStatistic(1001, StatisticCollector.a("stat.createWorld"))).e().d();
-    public static Statistic h = (new CounterStatistic(1002, StatisticCollector.a("stat.loadWorld"))).e().d();
-    public static Statistic i = (new CounterStatistic(1003, StatisticCollector.a("stat.joinMultiplayer"))).e().d();
-    public static Statistic j = (new CounterStatistic(1004, StatisticCollector.a("stat.leaveGame"))).e().d();
-    public static Statistic k = (new CounterStatistic(1100, StatisticCollector.a("stat.playOneMinute"), Statistic.j)).e().d();
-    public static Statistic l = (new CounterStatistic(2000, StatisticCollector.a("stat.walkOneCm"), Statistic.k)).e().d();
-    public static Statistic m = (new CounterStatistic(2001, StatisticCollector.a("stat.swimOneCm"), Statistic.k)).e().d();
-    public static Statistic n = (new CounterStatistic(2002, StatisticCollector.a("stat.fallOneCm"), Statistic.k)).e().d();
-    public static Statistic o = (new CounterStatistic(2003, StatisticCollector.a("stat.climbOneCm"), Statistic.k)).e().d();
-    public static Statistic p = (new CounterStatistic(2004, StatisticCollector.a("stat.flyOneCm"), Statistic.k)).e().d();
-    public static Statistic q = (new CounterStatistic(2005, StatisticCollector.a("stat.diveOneCm"), Statistic.k)).e().d();
-    public static Statistic r = (new CounterStatistic(2006, StatisticCollector.a("stat.minecartOneCm"), Statistic.k)).e().d();
-    public static Statistic s = (new CounterStatistic(2007, StatisticCollector.a("stat.boatOneCm"), Statistic.k)).e().d();
-    public static Statistic t = (new CounterStatistic(2008, StatisticCollector.a("stat.pigOneCm"), Statistic.k)).e().d();
-    public static Statistic u = (new CounterStatistic(2010, StatisticCollector.a("stat.jump"))).e().d();
-    public static Statistic v = (new CounterStatistic(2011, StatisticCollector.a("stat.drop"))).e().d();
-    public static Statistic w = (new CounterStatistic(2020, StatisticCollector.a("stat.damageDealt"))).d();
-    public static Statistic x = (new CounterStatistic(2021, StatisticCollector.a("stat.damageTaken"))).d();
-    public static Statistic y = (new CounterStatistic(2022, StatisticCollector.a("stat.deaths"))).d();
-    public static Statistic z = (new CounterStatistic(2023, StatisticCollector.a("stat.mobKills"))).d();
-    public static Statistic A = (new CounterStatistic(2024, StatisticCollector.a("stat.playerKills"))).d();
-    public static Statistic B = (new CounterStatistic(2025, StatisticCollector.a("stat.fishCaught"))).d();
-    public static Statistic[] C = a("stat.mineBlock", 16777216);
-    public static Statistic[] D;
-    public static Statistic[] E;
-    public static Statistic[] F;
-    private static boolean G;
-    private static boolean H;
-
-    public StatisticList() {}
-
-    public static void a() {}
-
-    public static void b() {
-        E = a(E, "stat.useItem", 16908288, 0, Block.byId.length);
-        F = b(F, "stat.breakItem", 16973824, 0, Block.byId.length);
-        G = true;
-        d();
-        // System.out.println(E); // CraftBukkit
-    }
-
-    public static void c() {
-        E = a(E, "stat.useItem", 16908288, Block.byId.length, 32000);
-        F = b(F, "stat.breakItem", 16973824, Block.byId.length, 32000);
-        H = true;
-        d();
-       // System.out.println(E); // CraftBukkit
-    }
-
-    public static void d() {
-        if (G && H) {
-            HashSet hashset = new HashSet();
-            Iterator iterator = CraftingManager.a().b().iterator();
-
-            while (iterator.hasNext()) {
-                CraftingRecipe craftingrecipe = (CraftingRecipe) iterator.next();
-
-                hashset.add(Integer.valueOf(craftingrecipe.b().id));
-            }
-
-            iterator = FurnaceRecipes.a().b().values().iterator();
-
-            while (iterator.hasNext()) {
-                ItemStack itemstack = (ItemStack) iterator.next();
-
-                hashset.add(Integer.valueOf(itemstack.id));
-            }
-
-            D = new Statistic[32000];
-            iterator = hashset.iterator();
-
-            while (iterator.hasNext()) {
-                Integer integer = (Integer) iterator.next();
-
-                if (Item.byId[integer.intValue()] != null) {
-                    String s = StatisticCollector.a("stat.craftItem", new Object[] { Item.byId[integer.intValue()].i()});
-
-                    D[integer.intValue()] = (new CraftingStatistic(16842752 + integer.intValue(), s, integer.intValue())).d();
-                }
-            }
-
-            a(D);
-        }
-    }
-
-    private static Statistic[] a(String s, int i) {
-        Statistic[] astatistic = new Statistic[256];
-
-        for (int j = 0; j < 256; ++j) {
-            if (Block.byId[j] != null && Block.byId[j].g()) {
-                String s1 = StatisticCollector.a(s, new Object[] { Block.byId[j].e()});
-
-                astatistic[j] = (new CraftingStatistic(i + j, s1, j)).d();
-                e.add((CraftingStatistic) astatistic[j]);
-            }
-        }
-
-        a(astatistic);
-        return astatistic;
-    }
-
-    private static Statistic[] a(Statistic[] astatistic, String s, int i, int j, int k) {
-        if (astatistic == null) {
-            astatistic = new Statistic[32000];
-        }
-
-        for (int l = j; l < k; ++l) {
-            if (Item.byId[l] != null) {
-                String s1 = StatisticCollector.a(s, new Object[] { Item.byId[l].i()});
-
-                astatistic[l] = (new CraftingStatistic(i + l, s1, l)).d();
-                if (l >= Block.byId.length) {
-                    d.add((CraftingStatistic) astatistic[l]);
-                }
-            }
-        }
-
-        a(astatistic);
-        return astatistic;
-    }
-
-    private static Statistic[] b(Statistic[] astatistic, String s, int i, int j, int k) {
-        if (astatistic == null) {
-            astatistic = new Statistic[32000];
-        }
-
-        for (int l = j; l < k; ++l) {
-            if (Item.byId[l] != null && Item.byId[l].e()) {
-                String s1 = StatisticCollector.a(s, new Object[] { Item.byId[l].i()});
-
-                astatistic[l] = (new CraftingStatistic(i + l, s1, l)).d();
-            }
-        }
-
-        a(astatistic);
-        return astatistic;
-    }
-
-    private static void a(Statistic[] astatistic) {
-        a(astatistic, Block.STATIONARY_WATER.id, Block.WATER.id);
-        a(astatistic, Block.STATIONARY_LAVA.id, Block.STATIONARY_LAVA.id);
-        a(astatistic, Block.JACK_O_LANTERN.id, Block.PUMPKIN.id);
-        a(astatistic, Block.BURNING_FURNACE.id, Block.FURNACE.id);
-        a(astatistic, Block.GLOWING_REDSTONE_ORE.id, Block.REDSTONE_ORE.id);
-        a(astatistic, Block.DIODE_ON.id, Block.DIODE_OFF.id);
-        a(astatistic, Block.REDSTONE_TORCH_ON.id, Block.REDSTONE_TORCH_OFF.id);
-        a(astatistic, Block.RED_MUSHROOM.id, Block.BROWN_MUSHROOM.id);
-        a(astatistic, Block.DOUBLE_STEP.id, Block.STEP.id);
-        a(astatistic, Block.GRASS.id, Block.DIRT.id);
-        a(astatistic, Block.SOIL.id, Block.DIRT.id);
-    }
-
-    private static void a(Statistic[] astatistic, int i, int j) {
-        if (astatistic[i] != null && astatistic[j] == null) {
-            astatistic[j] = astatistic[i];
-        } else {
-            b.remove(astatistic[i]);
-            e.remove(astatistic[i]);
-            c.remove(astatistic[i]);
-            astatistic[i] = astatistic[j];
-        }
-    }
-
-    static {
-        AchievementList.a();
-        G = false;
-        H = false;
-    }
-}
diff --git a/src/main/java/net/minecraft/server/ThreadLoginVerifier.java b/src/main/java/net/minecraft/server/ThreadLoginVerifier.java
index 16641aefde..8393f6234f 100644
--- a/src/main/java/net/minecraft/server/ThreadLoginVerifier.java
+++ b/src/main/java/net/minecraft/server/ThreadLoginVerifier.java
@@ -55,6 +55,7 @@ class ThreadLoginVerifier extends Thread {
                 this.netLoginHandler.disconnect("Failed to verify username!");
             }
         } catch (Exception exception) {
+            this.netLoginHandler.disconnect("Failed to verify username! [internal error " + exception + "]");
             exception.printStackTrace();
         }
     }
diff --git a/src/main/java/net/minecraft/server/TileEntityDispenser.java b/src/main/java/net/minecraft/server/TileEntityDispenser.java
index f5397d7c43..8cba5ac941 100644
--- a/src/main/java/net/minecraft/server/TileEntityDispenser.java
+++ b/src/main/java/net/minecraft/server/TileEntityDispenser.java
@@ -52,9 +52,9 @@ public class TileEntityDispenser extends TileEntity implements IInventory {
         int j = 1;
 
         for (int k = 0; k < this.items.length; ++k) {
-            if (this.items[k] != null && this.items[k].count != 0 && this.b.nextInt(j) == 0) { // CraftBukkit
+            if (this.items[k] != null && this.b.nextInt(j++) == 0) {
+                if (this.items[k].count == 0) continue; // CraftBukkit
                 i = k;
-                ++j;
             }
         }
 
diff --git a/src/main/java/net/minecraft/server/TileEntityMobSpawner.java b/src/main/java/net/minecraft/server/TileEntityMobSpawner.java
index af1d650a9b..4dcc867a3f 100644
--- a/src/main/java/net/minecraft/server/TileEntityMobSpawner.java
+++ b/src/main/java/net/minecraft/server/TileEntityMobSpawner.java
@@ -80,7 +80,7 @@ public class TileEntityMobSpawner extends TileEntity {
                                 this.world.a("flame", d0, d1, d2, 0.0D, 0.0D, 0.0D);
                             }
 
-                            entityliving.O();
+                            entityliving.P();
                             this.c();
                         }
                     }
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 777b1f52be..c5318ad1e9 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -23,46 +23,47 @@ import org.bukkit.event.weather.ThunderChangeEvent;
 public class World implements IBlockAccess {
 
     public boolean a = false;
-    private List w = new ArrayList();
+    private List C = new ArrayList();
     public List entityList = new ArrayList();
-    private List x = new ArrayList();
-    private TreeSet y = new TreeSet();
-    private Set z = new HashSet();
+    private List D = new ArrayList();
+    private TreeSet E = new TreeSet();
+    private Set F = new HashSet();
     public List c = new ArrayList();
     public List players = new ArrayList();
     public List e = new ArrayList();
-    private long A = 16777215L;
+    private long G = 16777215L;
     public int f = 0;
     protected int g = (new Random()).nextInt();
     protected int h = 1013904223;
-    private float B;
-    private float C;
-    private float D;
-    private float E;
-    private int F = 0;
-    public int i = 0;
-    public boolean j = false;
-    private long G = System.currentTimeMillis();
-    protected int k = 40;
+    protected float i;
+    protected float j;
+    protected float k;
+    protected float l;
+    protected int m = 0;
+    public int n = 0;
+    public boolean o = false;
+    private long H = System.currentTimeMillis();
+    protected int p = 40;
     public int spawnMonsters;
     public Random random = new Random();
-    public boolean n = false;
+    public boolean s = false;
     public final WorldProvider worldProvider;
-    protected List p = new ArrayList();
+    protected List u = new ArrayList();
     public IChunkProvider chunkProvider; // CraftBukkit - protected -> public
-    protected final IDataManager r;
+    protected final IDataManager w;
     public WorldData worldData; // CraftBukkit - protected -> public
     public boolean isLoading;
-    private boolean H;
-    private ArrayList I = new ArrayList();
-    private int J = 0;
+    private boolean I;
+    public WorldMapCollection z;
+    private ArrayList J = new ArrayList();
+    private int K = 0;
     public boolean allowMonsters = true; // CraftBukkit - private -> public
     public boolean allowAnimals = true; // CraftBukkit - private -> public
     public boolean pvpMode; // CraftBukkit
-    static int u = 0;
-    private Set M = new HashSet();
-    private int N;
-    private List O;
+    static int A = 0;
+    private Set N = new HashSet();
+    private int O;
+    private List P;
     public boolean isStatic;
 
     public WorldChunkManager getWorldChunkManager() {
@@ -70,18 +71,19 @@ public class World implements IBlockAccess {
     }
 
     public World(IDataManager idatamanager, String s, long i, WorldProvider worldprovider) {
-        this.N = this.random.nextInt(12000);
-        this.O = new ArrayList();
+        this.O = this.random.nextInt(12000);
+        this.P = new ArrayList();
         this.isStatic = false;
-        this.r = idatamanager;
+        this.w = idatamanager;
+        this.z = new WorldMapCollection(idatamanager);
         this.worldData = idatamanager.c();
-        this.n = this.worldData == null;
+        this.s = this.worldData == null;
         if (worldprovider != null) {
             this.worldProvider = worldprovider;
         } else if (this.worldData != null && this.worldData.h() == -1) {
-            this.worldProvider = new WorldProviderHell();
+            this.worldProvider = WorldProvider.a(-1);
         } else {
-            this.worldProvider = new WorldProvider();
+            this.worldProvider = WorldProvider.a(0);
         }
 
         boolean flag = false;
@@ -104,9 +106,9 @@ public class World implements IBlockAccess {
     }
 
     protected IChunkProvider b() {
-        IChunkLoader ichunkloader = this.r.a(this.worldProvider);
+        IChunkLoader ichunkloader = this.w.a(this.worldProvider);
 
-        return new ChunkProviderLoadOrGenerate(this, ichunkloader, this.worldProvider.c());
+        return new ChunkProviderLoadOrGenerate(this, ichunkloader, this.worldProvider.b());
     }
 
     protected void c() {
@@ -151,7 +153,8 @@ public class World implements IBlockAccess {
 
     private void w() {
         this.k();
-        this.r.a(this.worldData, this.players);
+        this.w.a(this.worldData, this.players);
+        this.z.a();
     }
 
     public int getTypeId(int i, int j, int k) {
@@ -278,7 +281,13 @@ public class World implements IBlockAccess {
 
     public void setData(int i, int j, int k, int l) {
         if (this.setRawData(i, j, k, l)) {
-            this.update(i, j, k, this.getTypeId(i, j, k));
+            int i1 = this.getTypeId(i, j, k);
+
+            if (Block.t[i1 & 255]) {
+                this.update(i, j, k, i1);
+            } else {
+                this.applyPhysics(i, j, k, i1);
+            }
         }
     }
 
@@ -326,8 +335,8 @@ public class World implements IBlockAccess {
     }
 
     public void notify(int i, int j, int k) {
-        for (int l = 0; l < this.p.size(); ++l) {
-            ((IWorldAccess) this.p.get(l)).a(i, j, k);
+        for (int l = 0; l < this.u.size(); ++l) {
+            ((IWorldAccess) this.u.get(l)).a(i, j, k);
         }
     }
 
@@ -348,14 +357,14 @@ public class World implements IBlockAccess {
     }
 
     public void h(int i, int j, int k) {
-        for (int l = 0; l < this.p.size(); ++l) {
-            ((IWorldAccess) this.p.get(l)).a(i, j, k, i, j, k);
+        for (int l = 0; l < this.u.size(); ++l) {
+            ((IWorldAccess) this.u.get(l)).a(i, j, k, i, j, k);
         }
     }
 
     public void b(int i, int j, int k, int l, int i1, int j1) {
-        for (int k1 = 0; k1 < this.p.size(); ++k1) {
-            ((IWorldAccess) this.p.get(k1)).a(i, j, k, l, i1, j1);
+        for (int k1 = 0; k1 < this.u.size(); ++k1) {
+            ((IWorldAccess) this.u.get(k1)).a(i, j, k, l, i1, j1);
         }
     }
 
@@ -369,7 +378,7 @@ public class World implements IBlockAccess {
     }
 
     private void k(int i, int j, int k, int l) {
-        if (!this.j && !this.isStatic) {
+        if (!this.o && !this.isStatic) {
             Block block = Block.byId[this.getTypeId(i, j, k)];
 
             if (block != null) {
@@ -394,17 +403,28 @@ public class World implements IBlockAccess {
         return this.getChunkAt(i >> 4, k >> 4).c(i & 15, j, k & 15);
     }
 
+    public int j(int i, int j, int k) {
+        if (j < 0) {
+            return 0;
+        } else {
+            if (j >= 128) {
+                j = 127;
+            }
+
+            return this.getChunkAt(i >> 4, k >> 4).c(i & 15, j, k & 15, 0);
+        }
+    }
+
     public int getLightLevel(int i, int j, int k) {
         return this.a(i, j, k, true);
     }
 
     public int a(int i, int j, int k, boolean flag) {
         if (i >= -32000000 && k >= -32000000 && i < 32000000 && k <= 32000000) {
-            int l;
-
             if (flag) {
-                l = this.getTypeId(i, j, k);
-                if (l == Block.STEP.id || l == Block.SOIL.id) {
+                int l = this.getTypeId(i, j, k);
+
+                if (l == Block.STEP.id || l == Block.SOIL.id || l == Block.COBBLESTONE_STAIRS.id || l == Block.WOOD_STAIRS.id) {
                     int i1 = this.a(i, j + 1, k, false);
                     int j1 = this.a(i + 1, j, k, false);
                     int k1 = this.a(i - 1, j, k, false);
@@ -433,14 +453,11 @@ public class World implements IBlockAccess {
 
             if (j < 0) {
                 return 0;
-            } else if (j >= 128) {
-                l = 15 - this.f;
-                if (l < 0) {
-                    l = 0;
+            } else {
+                if (j >= 128) {
+                    j = 127;
                 }
 
-                return l;
-            } else {
                 Chunk chunk = this.getChunkAt(i >> 4, k >> 4);
 
                 i &= 15;
@@ -452,7 +469,7 @@ public class World implements IBlockAccess {
         }
     }
 
-    public boolean k(int i, int j, int k) {
+    public boolean l(int i, int j, int k) {
         if (i >= -32000000 && k >= -32000000 && i < 32000000 && k <= 32000000) {
             if (j < 0) {
                 return false;
@@ -490,7 +507,7 @@ public class World implements IBlockAccess {
         if (!this.worldProvider.e || enumskyblock != EnumSkyBlock.SKY) {
             if (this.isLoaded(i, j, k)) {
                 if (enumskyblock == EnumSkyBlock.SKY) {
-                    if (this.k(i, j, k)) {
+                    if (this.l(i, j, k)) {
                         l = 15;
                     }
                 } else if (enumskyblock == EnumSkyBlock.BLOCK) {
@@ -509,6 +526,14 @@ public class World implements IBlockAccess {
     }
 
     public int a(EnumSkyBlock enumskyblock, int i, int j, int k) {
+        if (j < 0) {
+            j = 0;
+        }
+
+        if (j >= 128) {
+            j = 127;
+        }
+
         if (j >= 0 && j < 128 && i >= -32000000 && k >= -32000000 && i < 32000000 && k <= 32000000) {
             int l = i >> 4;
             int i1 = k >> 4;
@@ -534,8 +559,8 @@ public class World implements IBlockAccess {
 
                         chunk.a(enumskyblock, i & 15, j, k & 15, l);
 
-                        for (int i1 = 0; i1 < this.p.size(); ++i1) {
-                            ((IWorldAccess) this.p.get(i1)).a(i, j, k);
+                        for (int i1 = 0; i1 < this.u.size(); ++i1) {
+                            ((IWorldAccess) this.u.get(i1)).a(i, j, k);
                         }
                     }
                 }
@@ -543,7 +568,7 @@ public class World implements IBlockAccess {
         }
     }
 
-    public float l(int i, int j, int k) {
+    public float m(int i, int j, int k) {
         return this.worldProvider.f[this.getLightLevel(i, j, k)];
     }
 
@@ -552,10 +577,14 @@ public class World implements IBlockAccess {
     }
 
     public MovingObjectPosition a(Vec3D vec3d, Vec3D vec3d1) {
-        return this.rayTrace(vec3d, vec3d1, false);
+        return this.rayTrace(vec3d, vec3d1, false, false);
     }
 
     public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag) {
+        return this.rayTrace(vec3d, vec3d1, flag, false);
+    }
+
+    public MovingObjectPosition rayTrace(Vec3D vec3d, Vec3D vec3d1, boolean flag, boolean flag1) {
         if (!Double.isNaN(vec3d.a) && !Double.isNaN(vec3d.b) && !Double.isNaN(vec3d.c)) {
             if (!Double.isNaN(vec3d1.a) && !Double.isNaN(vec3d1.b) && !Double.isNaN(vec3d1.c)) {
                 int i = MathHelper.floor(vec3d1.a);
@@ -564,7 +593,19 @@ public class World implements IBlockAccess {
                 int l = MathHelper.floor(vec3d.a);
                 int i1 = MathHelper.floor(vec3d.b);
                 int j1 = MathHelper.floor(vec3d.c);
-                int k1 = 200;
+                int k1 = this.getTypeId(l, i1, j1);
+                int l1 = this.getData(l, i1, j1);
+                Block block = Block.byId[k1];
+
+                if ((!flag1 || block == null || block.d(this, l, i1, j1) != null) && k1 > 0 && block.a(l1, flag)) {
+                    MovingObjectPosition movingobjectposition = block.a(this, l, i1, j1, vec3d, vec3d1);
+
+                    if (movingobjectposition != null) {
+                        return movingobjectposition;
+                    }
+                }
+
+                k1 = 200;
 
                 while (k1-- >= 0) {
                     if (Double.isNaN(vec3d.a) || Double.isNaN(vec3d.b) || Double.isNaN(vec3d.c)) {
@@ -575,32 +616,35 @@ public class World implements IBlockAccess {
                         return null;
                     }
 
+                    boolean flag2 = true;
+                    boolean flag3 = true;
+                    boolean flag4 = true;
                     double d0 = 999.0D;
                     double d1 = 999.0D;
                     double d2 = 999.0D;
 
                     if (i > l) {
                         d0 = (double) l + 1.0D;
-                    }
-
-                    if (i < l) {
+                    } else if (i < l) {
                         d0 = (double) l + 0.0D;
+                    } else {
+                        flag2 = false;
                     }
 
                     if (j > i1) {
                         d1 = (double) i1 + 1.0D;
-                    }
-
-                    if (j < i1) {
+                    } else if (j < i1) {
                         d1 = (double) i1 + 0.0D;
+                    } else {
+                        flag3 = false;
                     }
 
                     if (k > j1) {
                         d2 = (double) j1 + 1.0D;
-                    }
-
-                    if (k < j1) {
+                    } else if (k < j1) {
                         d2 = (double) j1 + 0.0D;
+                    } else {
+                        flag4 = false;
                     }
 
                     double d3 = 999.0D;
@@ -610,19 +654,19 @@ public class World implements IBlockAccess {
                     double d7 = vec3d1.b - vec3d.b;
                     double d8 = vec3d1.c - vec3d.c;
 
-                    if (d0 != 999.0D) {
+                    if (flag2) {
                         d3 = (d0 - vec3d.a) / d6;
                     }
 
-                    if (d1 != 999.0D) {
+                    if (flag3) {
                         d4 = (d1 - vec3d.b) / d7;
                     }
 
-                    if (d2 != 999.0D) {
+                    if (flag4) {
                         d5 = (d2 - vec3d.c) / d8;
                     }
 
-                    boolean flag1 = false;
+                    boolean flag5 = false;
                     byte b0;
 
                     if (d3 < d4 && d3 < d5) {
@@ -677,15 +721,15 @@ public class World implements IBlockAccess {
                         ++vec3d2.c;
                     }
 
-                    int l1 = this.getTypeId(l, i1, j1);
-                    int i2 = this.getData(l, i1, j1);
-                    Block block = Block.byId[l1];
+                    int i2 = this.getTypeId(l, i1, j1);
+                    int j2 = this.getData(l, i1, j1);
+                    Block block1 = Block.byId[i2];
 
-                    if (l1 > 0 && block.a(i2, flag)) {
-                        MovingObjectPosition movingobjectposition = block.a(this, l, i1, j1, vec3d, vec3d1);
+                    if ((!flag1 || block1 == null || block1.d(this, l, i1, j1) != null) && i2 > 0 && block1.a(j2, flag)) {
+                        MovingObjectPosition movingobjectposition1 = block1.a(this, l, i1, j1, vec3d, vec3d1);
 
-                        if (movingobjectposition != null) {
-                            return movingobjectposition;
+                        if (movingobjectposition1 != null) {
+                            return movingobjectposition1;
                         }
                     }
                 }
@@ -700,26 +744,26 @@ public class World implements IBlockAccess {
     }
 
     public void makeSound(Entity entity, String s, float f, float f1) {
-        for (int i = 0; i < this.p.size(); ++i) {
-            ((IWorldAccess) this.p.get(i)).a(s, entity.locX, entity.locY - (double) entity.height, entity.locZ, f, f1);
+        for (int i = 0; i < this.u.size(); ++i) {
+            ((IWorldAccess) this.u.get(i)).a(s, entity.locX, entity.locY - (double) entity.height, entity.locZ, f, f1);
         }
     }
 
     public void makeSound(double d0, double d1, double d2, String s, float f, float f1) {
-        for (int i = 0; i < this.p.size(); ++i) {
-            ((IWorldAccess) this.p.get(i)).a(s, d0, d1, d2, f, f1);
+        for (int i = 0; i < this.u.size(); ++i) {
+            ((IWorldAccess) this.u.get(i)).a(s, d0, d1, d2, f, f1);
         }
     }
 
     public void a(String s, int i, int j, int k) {
-        for (int l = 0; l < this.p.size(); ++l) {
-            ((IWorldAccess) this.p.get(l)).a(s, i, j, k);
+        for (int l = 0; l < this.u.size(); ++l) {
+            ((IWorldAccess) this.u.get(l)).a(s, i, j, k);
         }
     }
 
     public void a(String s, double d0, double d1, double d2, double d3, double d4, double d5) {
-        for (int i = 0; i < this.p.size(); ++i) {
-            ((IWorldAccess) this.p.get(i)).a(s, d0, d1, d2, d3, d4, d5);
+        for (int i = 0; i < this.u.size(); ++i) {
+            ((IWorldAccess) this.u.get(i)).a(s, d0, d1, d2, d3, d4, d5);
         }
     }
 
@@ -764,14 +808,14 @@ public class World implements IBlockAccess {
     }
 
     protected void c(Entity entity) {
-        for (int i = 0; i < this.p.size(); ++i) {
-            ((IWorldAccess) this.p.get(i)).a(entity);
+        for (int i = 0; i < this.u.size(); ++i) {
+            ((IWorldAccess) this.u.get(i)).a(entity);
         }
     }
 
     protected void d(Entity entity) {
-        for (int i = 0; i < this.p.size(); ++i) {
-            ((IWorldAccess) this.p.get(i)).b(entity);
+        for (int i = 0; i < this.u.size(); ++i) {
+            ((IWorldAccess) this.u.get(i)).b(entity);
         }
     }
 
@@ -798,10 +842,10 @@ public class World implements IBlockAccess {
             this.everyoneSleeping();
         }
 
-        int i = entity.chunkX;
-        int j = entity.chunkZ;
+        int i = entity.bF;
+        int j = entity.bH;
 
-        if (entity.bB && this.isChunkLoaded(i, j)) {
+        if (entity.bE && this.isChunkLoaded(i, j)) {
             this.getChunkAt(i, j).b(entity);
         }
 
@@ -810,11 +854,11 @@ public class World implements IBlockAccess {
     }
 
     public void addIWorldAccess(IWorldAccess iworldaccess) {
-        this.p.add(iworldaccess);
+        this.u.add(iworldaccess);
     }
 
     public List getEntities(Entity entity, AxisAlignedBB axisalignedbb) {
-        this.I.clear();
+        this.J.clear();
         int i = MathHelper.floor(axisalignedbb.a);
         int j = MathHelper.floor(axisalignedbb.d + 1.0D);
         int k = MathHelper.floor(axisalignedbb.b);
@@ -829,7 +873,7 @@ public class World implements IBlockAccess {
                         Block block = Block.byId[this.getTypeId(k1, i2, l1)];
 
                         if (block != null) {
-                            block.a(this, k1, i2, l1, axisalignedbb, this.I);
+                            block.a(this, k1, i2, l1, axisalignedbb, this.J);
                         }
                     }
                 }
@@ -843,16 +887,16 @@ public class World implements IBlockAccess {
             AxisAlignedBB axisalignedbb1 = ((Entity) list.get(j2)).e_();
 
             if (axisalignedbb1 != null && axisalignedbb1.a(axisalignedbb)) {
-                this.I.add(axisalignedbb1);
+                this.J.add(axisalignedbb1);
             }
 
             axisalignedbb1 = entity.a_((Entity) list.get(j2));
             if (axisalignedbb1 != null && axisalignedbb1.a(axisalignedbb)) {
-                this.I.add(axisalignedbb1);
+                this.J.add(axisalignedbb1);
             }
         }
 
-        return this.I;
+        return this.J;
     }
 
     public int a(float f) {
@@ -884,6 +928,24 @@ public class World implements IBlockAccess {
 
         i &= 15;
 
+        for (j &= 15; k > 0; --k) {
+            int l = chunk.getTypeId(i, k, j);
+            Material material = l == 0 ? Material.AIR : Block.byId[l].material;
+
+            if (material.isSolid() || material.isLiquid()) {
+                return k + 1;
+            }
+        }
+
+        return -1;
+    }
+
+    public int f(int i, int j) {
+        Chunk chunk = this.b(i, j);
+        int k = 127;
+
+        i &= 15;
+
         for (j &= 15; k > 0; --k) {
             int l = chunk.getTypeId(i, k, j);
 
@@ -913,9 +975,9 @@ public class World implements IBlockAccess {
                     nextticklistentry.a((long) i1 + this.worldData.f());
                 }
 
-                if (!this.z.contains(nextticklistentry)) {
-                    this.z.add(nextticklistentry);
-                    this.y.add(nextticklistentry);
+                if (!this.F.contains(nextticklistentry)) {
+                    this.F.add(nextticklistentry);
+                    this.E.add(nextticklistentry);
                 }
             }
         }
@@ -933,25 +995,25 @@ public class World implements IBlockAccess {
             }
         }
 
-        this.entityList.removeAll(this.x);
+        this.entityList.removeAll(this.D);
 
         int j;
         int k;
 
-        for (i = 0; i < this.x.size(); ++i) {
-            entity = (Entity) this.x.get(i);
-            j = entity.chunkX;
-            k = entity.chunkZ;
-            if (entity.bB && this.isChunkLoaded(j, k)) {
+        for (i = 0; i < this.D.size(); ++i) {
+            entity = (Entity) this.D.get(i);
+            j = entity.bF;
+            k = entity.bH;
+            if (entity.bE && this.isChunkLoaded(j, k)) {
                 this.getChunkAt(j, k).b(entity);
             }
         }
 
-        for (i = 0; i < this.x.size(); ++i) {
-            this.d((Entity) this.x.get(i));
+        for (i = 0; i < this.D.size(); ++i) {
+            this.d((Entity) this.D.get(i));
         }
 
-        this.x.clear();
+        this.D.clear();
 
         for (i = 0; i < this.entityList.size(); ++i) {
             entity = (Entity) this.entityList.get(i);
@@ -969,9 +1031,9 @@ public class World implements IBlockAccess {
             }
 
             if (entity.dead) {
-                j = entity.chunkX;
-                k = entity.chunkZ;
-                if (entity.bB && this.isChunkLoaded(j, k)) {
+                j = entity.bF;
+                k = entity.bH;
+                if (entity.bE && this.isChunkLoaded(j, k)) {
                     this.getChunkAt(j, k).b(entity);
                 }
 
@@ -997,12 +1059,12 @@ public class World implements IBlockAccess {
         byte b0 = 32;
 
         if (!flag || this.a(i - b0, 0, j - b0, i + b0, 128, j + b0)) {
-            entity.bk = entity.locX;
-            entity.bl = entity.locY;
-            entity.bm = entity.locZ;
+            entity.bn = entity.locX;
+            entity.bo = entity.locY;
+            entity.bp = entity.locZ;
             entity.lastYaw = entity.yaw;
             entity.lastPitch = entity.pitch;
-            if (flag && entity.bB) {
+            if (flag && entity.bE) {
                 if (entity.vehicle != null) {
                     entity.B();
                 } else {
@@ -1011,15 +1073,15 @@ public class World implements IBlockAccess {
             }
 
             if (Double.isNaN(entity.locX) || Double.isInfinite(entity.locX)) {
-                entity.locX = entity.bk;
+                entity.locX = entity.bn;
             }
 
             if (Double.isNaN(entity.locY) || Double.isInfinite(entity.locY)) {
-                entity.locY = entity.bl;
+                entity.locY = entity.bo;
             }
 
             if (Double.isNaN(entity.locZ) || Double.isInfinite(entity.locZ)) {
-                entity.locZ = entity.bm;
+                entity.locZ = entity.bp;
             }
 
             if (Double.isNaN((double) entity.pitch) || Double.isInfinite((double) entity.pitch)) {
@@ -1034,20 +1096,20 @@ public class World implements IBlockAccess {
             int l = MathHelper.floor(entity.locY / 16.0D);
             int i1 = MathHelper.floor(entity.locZ / 16.0D);
 
-            if (!entity.bB || entity.chunkX != k || entity.bD != l || entity.chunkZ != i1) {
-                if (entity.bB && this.isChunkLoaded(entity.chunkX, entity.chunkZ)) {
-                    this.getChunkAt(entity.chunkX, entity.chunkZ).a(entity, entity.bD);
+            if (!entity.bE || entity.bF != k || entity.bG != l || entity.bH != i1) {
+                if (entity.bE && this.isChunkLoaded(entity.bF, entity.bH)) {
+                    this.getChunkAt(entity.bF, entity.bH).a(entity, entity.bG);
                 }
 
                 if (this.isChunkLoaded(k, i1)) {
-                    entity.bB = true;
+                    entity.bE = true;
                     this.getChunkAt(k, i1).a(entity);
                 } else {
-                    entity.bB = false;
+                    entity.bE = false;
                 }
             }
 
-            if (flag && entity.bB && entity.passenger != null) {
+            if (flag && entity.bE && entity.passenger != null) {
                 if (!entity.passenger.dead && entity.passenger.vehicle == entity) {
                     this.playerJoinedWorld(entity.passenger);
                 } else {
@@ -1064,7 +1126,7 @@ public class World implements IBlockAccess {
         for (int i = 0; i < list.size(); ++i) {
             Entity entity = (Entity) list.get(i);
 
-            if (!entity.dead && entity.aE) {
+            if (!entity.dead && entity.aH) {
                 return false;
             }
         }
@@ -1305,6 +1367,37 @@ public class World implements IBlockAccess {
         return (float) i / (float) j;
     }
 
+    public void a(EntityHuman entityhuman, int i, int j, int k, int l) {
+        if (l == 0) {
+            --j;
+        }
+
+        if (l == 1) {
+            ++j;
+        }
+
+        if (l == 2) {
+            --k;
+        }
+
+        if (l == 3) {
+            ++k;
+        }
+
+        if (l == 4) {
+            --i;
+        }
+
+        if (l == 5) {
+            ++i;
+        }
+
+        if (this.getTypeId(i, j, k) == Block.FIRE.id) {
+            this.a(entityhuman, 1004, i, j, k, 0);
+            this.setTypeId(i, j, k, 0);
+        }
+    }
+
     public TileEntity getTileEntity(int i, int j, int k) {
         Chunk chunk = this.getChunkAt(i >> 4, k >> 4);
 
@@ -1319,7 +1412,7 @@ public class World implements IBlockAccess {
         }
     }
 
-    public void n(int i, int j, int k) {
+    public void o(int i, int j, int k) {
         Chunk chunk = this.getChunkAt(i >> 4, k >> 4);
 
         if (chunk != null) {
@@ -1327,38 +1420,45 @@ public class World implements IBlockAccess {
         }
     }
 
-    public boolean d(int i, int j, int k) {
+    public boolean p(int i, int j, int k) {
         Block block = Block.byId[this.getTypeId(i, j, k)];
 
         return block == null ? false : block.a();
     }
 
+    public boolean d(int i, int j, int k) {
+        Block block = Block.byId[this.getTypeId(i, j, k)];
+
+        return block == null ? false : block.material.h() && block.b();
+    }
+
     public boolean doLighting() {
-        if (this.J >= 50) {
+        if (this.K >= 50) {
             return false;
         } else {
-            ++this.J;
+            ++this.K;
+
+            boolean flag;
 
             try {
                 int i = 500;
 
-                boolean flag;
-
-                while (this.w.size() > 0) {
+                while (this.C.size() > 0) {
                     --i;
                     if (i <= 0) {
                         flag = true;
                         return flag;
                     }
 
-                    ((MetadataChunkBlock) this.w.remove(this.w.size() - 1)).a(this);
+                    ((MetadataChunkBlock) this.C.remove(this.C.size() - 1)).a(this);
                 }
 
                 flag = false;
-                return flag;
             } finally {
-                --this.J;
+                --this.K;
             }
+
+            return flag;
         }
     }
 
@@ -1368,17 +1468,17 @@ public class World implements IBlockAccess {
 
     public void a(EnumSkyBlock enumskyblock, int i, int j, int k, int l, int i1, int j1, boolean flag) {
         if (!this.worldProvider.e || enumskyblock != EnumSkyBlock.SKY) {
-            ++u;
-            if (u == 50) {
-                --u;
+            ++A;
+            if (A == 50) {
+                --A;
             } else {
                 int k1 = (l + i) / 2;
                 int l1 = (j1 + k) / 2;
 
                 if (!this.isLoaded(k1, 64, l1)) {
-                    --u;
+                    --A;
                 } else if (!this.b(k1, l1).g()) {
-                    int i2 = this.w.size();
+                    int i2 = this.C.size();
                     int j2;
 
                     if (flag) {
@@ -1388,23 +1488,23 @@ public class World implements IBlockAccess {
                         }
 
                         for (int k2 = 0; k2 < j2; ++k2) {
-                            MetadataChunkBlock metadatachunkblock = (MetadataChunkBlock) this.w.get(this.w.size() - k2 - 1);
+                            MetadataChunkBlock metadatachunkblock = (MetadataChunkBlock) this.C.get(this.C.size() - k2 - 1);
 
                             if (metadatachunkblock.a == enumskyblock && metadatachunkblock.a(i, j, k, l, i1, j1)) {
-                                --u;
+                                --A;
                                 return;
                             }
                         }
                     }
 
-                    this.w.add(new MetadataChunkBlock(enumskyblock, i, j, k, l, i1, j1));
+                    this.C.add(new MetadataChunkBlock(enumskyblock, i, j, k, l, i1, j1));
                     j2 = 1000000;
-                    if (this.w.size() > 1000000) {
+                    if (this.C.size() > 1000000) {
                         System.out.println("More than " + j2 + " updates, aborting lighting updates");
-                        this.w.clear();
+                        this.C.clear();
                     }
 
-                    --u;
+                    --A;
                 }
             }
         }
@@ -1453,13 +1553,13 @@ public class World implements IBlockAccess {
         if (j != this.f) {
             this.f = j;
 
-            for (int k = 0; k < this.p.size(); ++k) {
-                ((IWorldAccess) this.p.get(k)).a();
+            for (int k = 0; k < this.u.size(); ++k) {
+                ((IWorldAccess) this.u.get(k)).a();
             }
         }
 
         i = this.worldData.f() + 1L;
-        if (i % (long) this.k == 0L) {
+        if (i % (long) this.p == 0L) {
             this.save(false, (IProgressUpdate) null);
         }
 
@@ -1470,17 +1570,17 @@ public class World implements IBlockAccess {
 
     private void x() {
         if (this.worldData.l()) {
-            this.C = 1.0F;
+            this.j = 1.0F;
             if (this.worldData.j()) {
-                this.E = 1.0F;
+                this.l = 1.0F;
             }
         }
     }
 
     protected void i() {
         if (!this.worldProvider.e) {
-            if (this.F > 0) {
-                --this.F;
+            if (this.m > 0) {
+                --this.m;
             }
 
             int i = this.worldData.k();
@@ -1531,34 +1631,34 @@ public class World implements IBlockAccess {
                 }
             }
 
-            this.B = this.C;
+            this.i = this.j;
             if (this.worldData.l()) {
-                this.C = (float) ((double) this.C + 0.01D);
+                this.j = (float) ((double) this.j + 0.01D);
             } else {
-                this.C = (float) ((double) this.C - 0.01D);
+                this.j = (float) ((double) this.j - 0.01D);
             }
 
-            if (this.C < 0.0F) {
-                this.C = 0.0F;
+            if (this.j < 0.0F) {
+                this.j = 0.0F;
             }
 
-            if (this.C > 1.0F) {
-                this.C = 1.0F;
+            if (this.j > 1.0F) {
+                this.j = 1.0F;
             }
 
-            this.D = this.E;
+            this.k = this.l;
             if (this.worldData.j()) {
-                this.E = (float) ((double) this.E + 0.01D);
+                this.l = (float) ((double) this.l + 0.01D);
             } else {
-                this.E = (float) ((double) this.E - 0.01D);
+                this.l = (float) ((double) this.l - 0.01D);
             }
 
-            if (this.E < 0.0F) {
-                this.E = 0.0F;
+            if (this.l < 0.0F) {
+                this.l = 0.0F;
             }
 
-            if (this.E > 1.0F) {
-                this.E = 1.0F;
+            if (this.l > 1.0F) {
+                this.l = 1.0F;
             }
         }
     }
@@ -1584,7 +1684,7 @@ public class World implements IBlockAccess {
     }
 
     protected void j() {
-        this.M.clear();
+        this.N.clear();
 
         int i;
         int j;
@@ -1600,16 +1700,16 @@ public class World implements IBlockAccess {
 
             for (k = -b0; k <= b0; ++k) {
                 for (l = -b0; l <= b0; ++l) {
-                    this.M.add(new ChunkCoordIntPair(k + i, l + j));
+                    this.N.add(new ChunkCoordIntPair(k + i, l + j));
                 }
             }
         }
 
-        if (this.N > 0) {
-            --this.N;
+        if (this.O > 0) {
+            --this.O;
         }
 
-        Iterator iterator = this.M.iterator();
+        Iterator iterator = this.N.iterator();
 
         while (iterator.hasNext()) {
             ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) iterator.next();
@@ -1621,7 +1721,7 @@ public class World implements IBlockAccess {
             int k1;
             int l1;
 
-            if (this.N == 0) {
+            if (this.O == 0) {
                 this.g = this.g * 3 + this.h;
                 k = this.g >> 2;
                 l = k & 15;
@@ -1630,12 +1730,12 @@ public class World implements IBlockAccess {
                 l1 = chunk.getTypeId(l, k1, j1);
                 l += i;
                 j1 += j;
-                if (l1 == 0 && this.getLightLevel(l, k1, j1) <= this.random.nextInt(8) && this.a(EnumSkyBlock.SKY, l, k1, j1) <= 0) {
+                if (l1 == 0 && this.j(l, k1, j1) <= this.random.nextInt(8) && this.a(EnumSkyBlock.SKY, l, k1, j1) <= 0) {
                     EntityHuman entityhuman1 = this.a((double) l + 0.5D, (double) k1 + 0.5D, (double) j1 + 0.5D, 8.0D);
 
                     if (entityhuman1 != null && entityhuman1.d((double) l + 0.5D, (double) k1 + 0.5D, (double) j1 + 0.5D) > 4.0D) {
                         this.makeSound((double) l + 0.5D, (double) k1 + 0.5D, (double) j1 + 0.5D, "ambient.cave.cave", 0.7F, 0.8F + this.random.nextFloat() * 0.2F);
-                        this.N = this.random.nextInt(12000) + 6000;
+                        this.O = this.random.nextInt(12000) + 6000;
                     }
                 }
             }
@@ -1646,15 +1746,15 @@ public class World implements IBlockAccess {
                 l = i + (k & 15);
                 j1 = j + (k >> 8 & 15);
                 k1 = this.e(l, j1);
-                if (this.q(l, k1, j1)) {
+                if (this.s(l, k1, j1)) {
                     this.a((Entity) (new EntityWeatherStorm(this, (double) l, (double) k1, (double) j1)));
-                    this.F = 2;
+                    this.m = 2;
                 }
             }
 
             int i2;
 
-            if (this.random.nextInt(16) == 0 && this.v()) {
+            if (this.random.nextInt(16) == 0) {
                 this.g = this.g * 3 + this.h;
                 k = this.g >> 2;
                 l = k & 15;
@@ -1663,7 +1763,7 @@ public class World implements IBlockAccess {
                 if (this.getWorldChunkManager().getBiome(l + i, j1 + j).c() && k1 >= 0 && k1 < 128 && chunk.a(EnumSkyBlock.BLOCK, l, k1, j1) < 10) {
                     l1 = chunk.getTypeId(l, k1 - 1, j1);
                     i2 = chunk.getTypeId(l, k1, j1);
-                    if (i2 == 0 && Block.SNOW.canPlace(this, l + i, k1, j1 + j) && l1 != 0 && l1 != Block.ICE.id && Block.byId[l1].material.isSolid()) {
+                    if (this.v() && i2 == 0 && Block.SNOW.canPlace(this, l + i, k1, j1 + j) && l1 != 0 && l1 != Block.ICE.id && Block.byId[l1].material.isSolid()) {
                         // CraftBukkit start
                         SnowFormEvent snow = new SnowFormEvent(((WorldServer)this).getWorld().getBlockAt(l + i, k1, j1 + j));
                         ((WorldServer)this).getServer().getPluginManager().callEvent(snow);
@@ -1696,9 +1796,9 @@ public class World implements IBlockAccess {
     }
 
     public boolean a(boolean flag) {
-        int i = this.y.size();
+        int i = this.E.size();
 
-        if (i != this.z.size()) {
+        if (i != this.F.size()) {
             throw new IllegalStateException("TickNextTick list out of synch");
         } else {
             if (i > 1000) {
@@ -1706,14 +1806,14 @@ public class World implements IBlockAccess {
             }
 
             for (int j = 0; j < i; ++j) {
-                NextTickListEntry nextticklistentry = (NextTickListEntry) this.y.first();
+                NextTickListEntry nextticklistentry = (NextTickListEntry) this.E.first();
 
                 if (!flag && nextticklistentry.e > this.worldData.f()) {
                     break;
                 }
 
-                this.y.remove(nextticklistentry);
-                this.z.remove(nextticklistentry);
+                this.E.remove(nextticklistentry);
+                this.F.remove(nextticklistentry);
                 byte b0 = 8;
 
                 if (this.a(nextticklistentry.a - b0, nextticklistentry.b - b0, nextticklistentry.c - b0, nextticklistentry.a + b0, nextticklistentry.b + b0, nextticklistentry.c + b0)) {
@@ -1725,12 +1825,12 @@ public class World implements IBlockAccess {
                 }
             }
 
-            return this.y.size() != 0;
+            return this.E.size() != 0;
         }
     }
 
     public List b(Entity entity, AxisAlignedBB axisalignedbb) {
-        this.O.clear();
+        this.P.clear();
         int i = MathHelper.floor((axisalignedbb.a - 2.0D) / 16.0D);
         int j = MathHelper.floor((axisalignedbb.d + 2.0D) / 16.0D);
         int k = MathHelper.floor((axisalignedbb.c - 2.0D) / 16.0D);
@@ -1739,12 +1839,12 @@ public class World implements IBlockAccess {
         for (int i1 = i; i1 <= j; ++i1) {
             for (int j1 = k; j1 <= l; ++j1) {
                 if (this.isChunkLoaded(i1, j1)) {
-                    this.getChunkAt(i1, j1).a(entity, axisalignedbb, this.O);
+                    this.getChunkAt(i1, j1).a(entity, axisalignedbb, this.P);
                 }
             }
         }
 
-        return this.O;
+        return this.P;
     }
 
     public List a(Class oclass, AxisAlignedBB axisalignedbb) {
@@ -1770,8 +1870,8 @@ public class World implements IBlockAccess {
             this.b(i, k).f();
         }
 
-        for (int l = 0; l < this.p.size(); ++l) {
-            ((IWorldAccess) this.p.get(l)).a(i, j, k, tileentity);
+        for (int l = 0; l < this.u.size(); ++l) {
+            ((IWorldAccess) this.u.get(l)).a(i, j, k, tileentity);
         }
     }
 
@@ -1810,12 +1910,12 @@ public class World implements IBlockAccess {
     }
 
     public void b(List list) {
-        this.x.addAll(list);
+        this.D.addAll(list);
     }
 
-    public boolean a(int i, int j, int k, int l, boolean flag) {
-        int i1 = this.getTypeId(j, k, l);
-        Block block = Block.byId[i1];
+    public boolean a(int i, int j, int k, int l, boolean flag, int i1) {
+        int j1 = this.getTypeId(j, k, l);
+        Block block = Block.byId[j1];
         Block block1 = Block.byId[i];
         AxisAlignedBB axisalignedbb = block1.d(this, j, k, l);
 
@@ -1835,7 +1935,7 @@ public class World implements IBlockAccess {
             }
 
             // CraftBukkit
-            defaultReturn = i > 0 && block == null && block1.canPlace(this, j, k, l);
+            defaultReturn = i > 0 && block == null && block1.canPlace(this, j, k, l, i1);
         }
 
         // CraftBukkit start
@@ -1894,7 +1994,7 @@ public class World implements IBlockAccess {
         } else {
             int i1 = this.getTypeId(i, j, k);
 
-            return i1 == 0 ? false : Block.byId[i1].b(this, i, j, k, l);
+            return i1 == 0 ? false : Block.byId[i1].a(this, i, j, k, l);
         }
     }
 
@@ -1983,7 +2083,7 @@ public class World implements IBlockAccess {
     }
 
     public void k() {
-        this.r.b();
+        this.w.b();
     }
 
     public void setTime(long i) {
@@ -2021,7 +2121,7 @@ public class World implements IBlockAccess {
     }
 
     public IDataManager p() {
-        return this.r;
+        return this.w;
     }
 
     public WorldData q() {
@@ -2029,7 +2129,7 @@ public class World implements IBlockAccess {
     }
 
     public void everyoneSleeping() {
-        this.H = !this.players.isEmpty();
+        this.I = !this.players.isEmpty();
         Iterator iterator = this.players.iterator();
 
         while (iterator.hasNext()) {
@@ -2037,7 +2137,7 @@ public class World implements IBlockAccess {
 
             // CraftBukkit
             if (!entityhuman.isSleeping() && !entityhuman.fauxSleeping) {
-                this.H = false;
+                this.I = false;
                 break;
             }
         }
@@ -2054,7 +2154,7 @@ public class World implements IBlockAccess {
     // CraftBukkit end
 
     protected void s() {
-        this.H = false;
+        this.I = false;
         Iterator iterator = this.players.iterator();
 
         while (iterator.hasNext()) {
@@ -2069,7 +2169,7 @@ public class World implements IBlockAccess {
     }
 
     public boolean everyoneDeeplySleeping() {
-        if (this.H && !this.isStatic) {
+        if (this.I && !this.isStatic) {
             Iterator iterator = this.players.iterator();
 
             // CraftBukkit - This allows us to assume that some people are in bed but not really, allowing time to pass in spite of AFKers
@@ -2098,11 +2198,11 @@ public class World implements IBlockAccess {
     }
 
     public float c(float f) {
-        return (this.D + (this.E - this.D) * f) * this.d(f);
+        return (this.k + (this.l - this.k) * f) * this.d(f);
     }
 
     public float d(float f) {
-        return this.B + (this.C - this.B) * f;
+        return this.i + (this.j - this.i) * f;
     }
 
     public boolean u() {
@@ -2113,7 +2213,7 @@ public class World implements IBlockAccess {
         return (double) this.d(1.0F) > 0.2D;
     }
 
-    public boolean q(int i, int j, int k) {
+    public boolean s(int i, int j, int k) {
         if (!this.v()) {
             return false;
         } else if (!this.isChunkLoaded(i, j, k)) {
@@ -2126,4 +2226,26 @@ public class World implements IBlockAccess {
             return biomebase.c() ? false : biomebase.d();
         }
     }
+
+    public void a(String s, WorldMapBase worldmapbase) {
+        this.z.a(s, worldmapbase);
+    }
+
+    public WorldMapBase a(Class oclass, String s) {
+        return this.z.a(oclass, s);
+    }
+
+    public int b(String s) {
+        return this.z.a(s);
+    }
+
+    public void e(int i, int j, int k, int l, int i1) {
+        this.a((EntityHuman) null, i, j, k, l, i1);
+    }
+
+    public void a(EntityHuman entityhuman, int i, int j, int k, int l, int i1) {
+        for (int j1 = 0; j1 < this.u.size(); ++j1) {
+            ((IWorldAccess) this.u.get(j1)).a(entityhuman, i, j, k, l, i1);
+        }
+    }
 }
diff --git a/src/main/java/net/minecraft/server/WorldGenBigTree.java b/src/main/java/net/minecraft/server/WorldGenBigTree.java
index c93785abe4..8be99e1b92 100644
--- a/src/main/java/net/minecraft/server/WorldGenBigTree.java
+++ b/src/main/java/net/minecraft/server/WorldGenBigTree.java
@@ -60,8 +60,8 @@ public class WorldGenBigTree extends WorldGenerator {
                 for (double d0 = 0.5D; j1 < i; ++j1) {
                     double d1 = this.j * (double) f * ((double) this.b.nextFloat() + 0.328D);
                     double d2 = (double) this.b.nextFloat() * 2.0D * 3.14159D;
-                    int k1 = (int) (d1 * Math.sin(d2) + (double) this.d[0] + d0);
-                    int l1 = (int) (d1 * Math.cos(d2) + (double) this.d[2] + d0);
+                    int k1 = MathHelper.floor(d1 * Math.sin(d2) + (double) this.d[0] + d0);
+                    int l1 = MathHelper.floor(d1 * Math.cos(d2) + (double) this.d[2] + d0);
                     int[] aint1 = new int[] { k1, j, l1};
                     int[] aint2 = new int[] { k1, j + this.n, l1};
 
@@ -291,8 +291,8 @@ public class WorldGenBigTree extends WorldGenerator {
 
             for (j = aint2[b1] + b4; i != j; i += b4) {
                 aint3[b1] = aint[b1] + i;
-                aint3[b2] = (int) ((double) aint[b2] + (double) i * d0);
-                aint3[b3] = (int) ((double) aint[b3] + (double) i * d1);
+                aint3[b2] = MathHelper.floor((double) aint[b2] + (double) i * d0);
+                aint3[b3] = MathHelper.floor((double) aint[b3] + (double) i * d1);
                 int k = this.c.getTypeId(aint3[0], aint3[1], aint3[2]);
 
                 if (k != 0 && k != 18) {
diff --git a/src/main/java/net/minecraft/server/WorldManager.java b/src/main/java/net/minecraft/server/WorldManager.java
index 218a5ade06..3ba6afb74d 100644
--- a/src/main/java/net/minecraft/server/WorldManager.java
+++ b/src/main/java/net/minecraft/server/WorldManager.java
@@ -3,22 +3,21 @@ package net.minecraft.server;
 public class WorldManager implements IWorldAccess {
 
     private MinecraftServer server;
-    public WorldServer world; // CraftBukkit
+    public WorldServer world; // CraftBukkit private -> public
 
-    // CraftBukkit - changed signature
-    public WorldManager(MinecraftServer minecraftserver, WorldServer world) {
+    public WorldManager(MinecraftServer minecraftserver, WorldServer worldserver) {
         this.server = minecraftserver;
-        this.world = world; // CraftBukkit
+        this.world = worldserver;
     }
 
     public void a(String s, double d0, double d1, double d2, double d3, double d4, double d5) {}
 
     public void a(Entity entity) {
-        this.server.tracker.a(entity);
+        this.server.b(this.world.worldProvider.dimension).a(entity);
     }
 
     public void b(Entity entity) {
-        this.server.tracker.untrackEntity(entity);
+        this.server.b(this.world.worldProvider.dimension).untrackEntity(entity);
     }
 
     public void a(String s, double d0, double d1, double d2, float f, float f1) {}
@@ -28,8 +27,7 @@ public class WorldManager implements IWorldAccess {
     public void a() {}
 
     public void a(int i, int j, int k) {
-        // CraftBukkit - add world argument
-        this.server.serverConfigurationManager.flagDirty(i, j, k, world);
+        this.server.serverConfigurationManager.flagDirty(i, j, k, this.world.worldProvider.dimension);
     }
 
     public void a(String s, int i, int j, int k) {}
@@ -37,4 +35,8 @@ public class WorldManager implements IWorldAccess {
     public void a(int i, int j, int k, TileEntity tileentity) {
         this.server.serverConfigurationManager.a(i, j, k, tileentity);
     }
+
+    public void a(EntityHuman entityhuman, int i, int j, int k, int l, int i1) {
+        this.server.serverConfigurationManager.a(entityhuman, (double) j, (double) k, (double) l, 64.0D, this.world.worldProvider.dimension, new Packet61(i, j, k, l, i1));
+    }
 }
diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java
index 66e3e04774..5388ee07e7 100644
--- a/src/main/java/net/minecraft/server/WorldServer.java
+++ b/src/main/java/net/minecraft/server/WorldServer.java
@@ -14,24 +14,25 @@ public class WorldServer extends World implements BlockChangeDelegate {
 
     public ChunkProviderServer chunkProviderServer;
     public boolean weirdIsOpCache = false;
-    public boolean y;
+    public boolean E;
     public final MinecraftServer server; // CraftBukkit - private -> public final
-    private EntityList A = new EntityList();
+    private EntityList G = new EntityList();
 
     public WorldServer(MinecraftServer minecraftserver, IDataManager idatamanager, String s, int i, long j) {
         super(idatamanager, s, j, WorldProvider.a(i));
         this.server = minecraftserver;
 
         // CraftBukkit start
+        this.dimension = i;
         this.cserver = minecraftserver.server;
         this.world = new CraftWorld(this);
-        this.manager = new PlayerManager(minecraftserver, this);
         this.pvpMode = minecraftserver.pvpMode;
     }
 
-    public PlayerManager manager;
+    public final int dimension;
     private final CraftWorld world;
     private final CraftServer cserver;
+    public EntityTracker tracker;
 
     public CraftWorld getWorld() {
         return world;
@@ -59,9 +60,9 @@ public class WorldServer extends World implements BlockChangeDelegate {
     }
 
     protected IChunkProvider b() {
-        IChunkLoader ichunkloader = this.r.a(this.worldProvider);
+        IChunkLoader ichunkloader = this.w.a(this.worldProvider);
 
-        this.chunkProviderServer = new ChunkProviderServer(this, ichunkloader, this.worldProvider.c());
+        this.chunkProviderServer = new ChunkProviderServer(this, ichunkloader, this.worldProvider.b());
         return this.chunkProviderServer;
     }
 
@@ -93,16 +94,16 @@ public class WorldServer extends World implements BlockChangeDelegate {
 
     protected void c(Entity entity) {
         super.c(entity);
-        this.A.a(entity.id, entity);
+        this.G.a(entity.id, entity);
     }
 
     protected void d(Entity entity) {
         super.d(entity);
-        this.A.d(entity.id);
+        this.G.d(entity.id);
     }
 
     public Entity getEntity(int i) {
-        return (Entity) this.A.a(i);
+        return (Entity) this.G.a(i);
     }
 
     public boolean a(Entity entity) {
@@ -116,7 +117,7 @@ public class WorldServer extends World implements BlockChangeDelegate {
             }
             // CraftBukkit end
 
-            this.server.serverConfigurationManager.a(entity.locX, entity.locY, entity.locZ, 512.0D, new Packet71Weather(entity));
+            this.server.serverConfigurationManager.a(entity.locX, entity.locY, entity.locZ, 512.0D, this.worldProvider.dimension, new Packet71Weather(entity));
             return true;
         } else {
             return false;
@@ -126,7 +127,7 @@ public class WorldServer extends World implements BlockChangeDelegate {
     public void a(Entity entity, byte b0) {
         Packet38EntityStatus packet38entitystatus = new Packet38EntityStatus(entity.id, b0);
 
-        this.server.tracker.b(entity, packet38entitystatus);
+        this.server.b(this.worldProvider.dimension).b(entity, packet38entitystatus);
     }
 
     public Explosion createExplosion(Entity entity, double d0, double d1, double d2, float f, boolean flag) {
@@ -138,17 +139,17 @@ public class WorldServer extends World implements BlockChangeDelegate {
         }
         // CraftBukkit end
 
-        this.server.serverConfigurationManager.a(d0, d1, d2, 64.0D, new Packet60Explosion(d0, d1, d2, f, explosion.g));
+        this.server.serverConfigurationManager.a(d0, d1, d2, 64.0D, this.worldProvider.dimension, new Packet60Explosion(d0, d1, d2, f, explosion.g));
         return explosion;
     }
 
     public void d(int i, int j, int k, int l, int i1) {
         super.d(i, j, k, l, i1);
-        this.server.serverConfigurationManager.a((double) i, (double) j, (double) k, 64.0D, new Packet54PlayNoteBlock(i, j, k, l, i1));
+        this.server.serverConfigurationManager.a((double) i, (double) j, (double) k, 64.0D, this.worldProvider.dimension, new Packet54PlayNoteBlock(i, j, k, l, i1));
     }
 
     public void saveLevel() {
-        this.r.e();
+        this.w.e();
     }
 
     protected void i() {
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index a7be0d88af..df6ee62068 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -27,6 +27,7 @@ import net.minecraft.server.ChunkCoordinates;
 import net.minecraft.server.ConvertProgressUpdater;
 import net.minecraft.server.Convertable;
 import net.minecraft.server.EntityPlayer;
+import net.minecraft.server.EntityTracker;
 import net.minecraft.server.MinecraftServer;
 import net.minecraft.server.PropertyManager;
 import net.minecraft.server.ServerConfigurationManager;
@@ -36,6 +37,7 @@ import net.minecraft.server.WorldManager;
 import net.minecraft.server.WorldServer;
 import net.minecraft.server.ServerCommand;
 import net.minecraft.server.ICommandListener;
+import net.minecraft.server.SecondaryWorldServer;
 import org.bukkit.*;
 import org.bukkit.plugin.Plugin;
 import org.bukkit.plugin.PluginManager;
@@ -57,7 +59,7 @@ import org.bukkit.util.config.Configuration;
 public final class CraftServer implements Server {
     private final String serverName = "Craftbukkit";
     private final String serverVersion;
-    private final String protocolVersion = "1.5_02";
+    private final String protocolVersion = "1.6.2";
     private final PluginManager pluginManager = new SimplePluginManager(this);
     private final ServicesManager servicesManager = new SimpleServicesManager();
     private final BukkitScheduler scheduler =  new CraftScheduler(this);
@@ -364,12 +366,13 @@ public final class CraftServer implements Server {
             converter.convert(name, new ConvertProgressUpdater(console));
         }
 
-        WorldServer internal = new WorldServer(console, new ServerNBTManager(new File("."), name, true), name, environment == World.Environment.NETHER ? -1 : 0, seed);
+        WorldServer internal = new WorldServer(console, new ServerNBTManager(new File("."), name, true), name, environment.getId(), seed);
+        internal.z = console.worlds.get(0).z;
 
+        internal.tracker = new EntityTracker(console, environment.getId());
         internal.addIWorldAccess((IWorldAccess)new WorldManager(console, internal));
         internal.spawnMonsters = 1;
         internal.setSpawnFlags(true, true);
-        console.serverConfigurationManager.setPlayerFileData(internal);
         console.worlds.add(internal);
 
         short short1 = 196;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java
index 974bd85907..9de2a0a73a 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftCreeper.java
@@ -19,7 +19,7 @@ public class CraftCreeper extends CraftMonster implements Creeper {
     }
 
     public boolean isPowered() {
-        return getHandle().W().a(17) == 1;
+        return getHandle().X().a(17) == 1;
     }
 
     public void setPowered(boolean powered) {
@@ -32,14 +32,14 @@ public class CraftCreeper extends CraftMonster implements Creeper {
             server.getPluginManager().callEvent(event);
 
             if (!event.isCancelled()) {
-                getHandle().W().b(17, (byte)1);
+                getHandle().X().b(17, (byte)1);
             }
         } else {
             CreeperPowerEvent event = new CreeperPowerEvent(entity, CreeperPowerEvent.PowerCause.SET_OFF);
             server.getPluginManager().callEvent(event);
 
             if (!event.isCancelled()) {
-                getHandle().W().b(17, (byte)0);
+                getHandle().X().b(17, (byte)0);
             }
         }
 
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 0ae975175d..371b9ee4ba 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -13,6 +13,8 @@ import net.minecraft.server.Packet6SpawnPosition;
 import net.minecraft.server.ServerConfigurationManager;
 import net.minecraft.server.WorldServer;
 import net.minecraft.server.ChunkCoordIntPair;
+import net.minecraft.server.Packet9Respawn;
+import net.minecraft.server.World;
 import org.bukkit.Achievement;
 import org.bukkit.Location;
 import org.bukkit.Material;
@@ -168,58 +170,26 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
         WorldServer newWorld = ((CraftWorld)location.getWorld()).getHandle();
         ServerConfigurationManager manager = server.getHandle();
         EntityPlayer entity = getHandle();
-        boolean teleportSuccess;
 
         if (oldWorld != newWorld) {
+            entity.dimension = newWorld.dimension;
+            entity.netServerHandler.sendPacket(new Packet9Respawn((byte) entity.dimension));
+            oldWorld.removeEntity(entity);
+            entity.dead = false;
 
-            EntityPlayer newEntity = new EntityPlayer(manager.server, newWorld, entity.name, new ItemInWorldManager(newWorld));
-
-            newEntity.id = entity.id;
-            newEntity.netServerHandler = entity.netServerHandler;
-            newEntity.health = entity.health;
-            newEntity.fireTicks = entity.fireTicks;
-            newEntity.inventory = entity.inventory;
-            newEntity.inventory.d = newEntity;
-            newEntity.activeContainer = entity.activeContainer;
-            newEntity.defaultContainer = entity.defaultContainer;
-            newEntity.locX = location.getX();
-            newEntity.locY = location.getY();
-            newEntity.locZ = location.getZ();
-            newEntity.displayName = entity.displayName;
-            newEntity.compassTarget = entity.compassTarget;
-            newEntity.fauxSleeping = entity.fauxSleeping;
-            newWorld.chunkProviderServer.getChunkAt((int) location.getBlockX() >> 4, (int) location.getBlockZ() >> 4);
-
-            teleportSuccess = newEntity.netServerHandler.teleport(location);
-
-            if (teleportSuccess) {
-                manager.server.tracker.trackPlayer(entity);
-                manager.server.tracker.untrackEntity(entity);
-                int cx = (int) location.getBlockX() >> 4;
-                int cz = (int) location.getBlockZ() >> 4;
-                for (int x = -10 ; x <= 10 ; x++) {
-                    for (int z = -10 ; z <= 10 ; z++) {
-                        ChunkCoordIntPair chunkPosition = new ChunkCoordIntPair(cx + x, cz + z);
-                        if (entity.g.remove(chunkPosition)) {
-                            newEntity.g.add(chunkPosition);
-                        }
-                    }
-                }
-                oldWorld.manager.removePlayer(entity);
-                manager.players.remove(entity);
-                oldWorld.removeEntity(entity);
-
-                newWorld.manager.addPlayer(newEntity);
-                newWorld.addEntity(newEntity);
-                manager.players.add(newEntity);
-
-                entity.netServerHandler.player = newEntity;
-                this.entity = newEntity;
-
-                setCompassTarget(getCompassTarget());
+            if (entity.Q()) {
+                newWorld.addEntity(entity);
+                entity.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
+                newWorld.entityJoinedWorld(entity, false);
             }
 
-            return teleportSuccess;
+            manager.a(entity);
+            entity.netServerHandler.a(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
+            entity.a((World)newWorld);
+            manager.a(entity, newWorld);
+            entity.a(entity.defaultContainer);
+
+            return true;
         } else {
             return entity.netServerHandler.teleport(location);
         }