From 696543cf3f43756dfc2d4c1d18b2b461badcb107 Mon Sep 17 00:00:00 2001
From: Travis Watkins <amaranth@ubuntu.com>
Date: Wed, 20 Mar 2013 15:09:23 -0500
Subject: [PATCH] Update CraftBukkit to Minecraft 1.5.1

---
 pom.xml                                       |   6 +-
 .../net/minecraft/server/BlockDispenser.java  |   2 +
 .../net/minecraft/server/ContainerAnvil.java  |   2 +-
 .../net/minecraft/server/DedicatedServer.java |   2 +-
 .../DedicatedServerConnectionThread.java      |  20 +-
 .../java/net/minecraft/server/Entity.java     |  16 +-
 .../minecraft/server/EntityEnderDragon.java   |   2 +-
 .../net/minecraft/server/EntityHuman.java     |  14 +-
 .../net/minecraft/server/EntityLiving.java    |  26 ++-
 .../net/minecraft/server/EntityPlayer.java    |  10 +-
 .../net/minecraft/server/EntitySquid.java     |   2 +-
 .../net/minecraft/server/EntityTracker.java   |  44 ++--
 .../minecraft/server/EntityTrackerEntry.java  |  32 +--
 .../net/minecraft/server/MinecraftServer.java |   2 +-
 .../java/net/minecraft/server/Packet.java     |   4 +-
 .../java/net/minecraft/server/PlayerList.java |  14 +-
 .../server/TileEntityBrewingStand.java        |  42 ++--
 .../minecraft/server/TileEntityFurnace.java   |  27 ++-
 .../minecraft/server/TileEntityHopper.java    | 221 +++++++++---------
 .../server/TileEntityRecordPlayer.java        |  40 ++++
 src/main/java/net/minecraft/server/World.java |  10 +-
 21 files changed, 307 insertions(+), 231 deletions(-)
 create mode 100644 src/main/java/net/minecraft/server/TileEntityRecordPlayer.java

diff --git a/pom.xml b/pom.xml
index 5a74ee9b7e..ce239ff7fc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
   <groupId>org.bukkit</groupId>
   <artifactId>craftbukkit</artifactId>
   <packaging>jar</packaging>
-  <version>1.5-R0.1-SNAPSHOT</version>
+  <version>1.5.1-R0.1-SNAPSHOT</version>
   <name>CraftBukkit</name>
   <url>http://www.bukkit.org</url>
 
@@ -12,8 +12,8 @@
     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     <api.version>unknown</api.version>
     <junit.version>4.11</junit.version>
-    <minecraft.version>1.5</minecraft.version>
-    <minecraft_version>1_5_R1</minecraft_version>
+    <minecraft.version>1.5.1</minecraft.version>
+    <minecraft_version>1_5_R2</minecraft_version>
   </properties>
 
   <scm>
diff --git a/src/main/java/net/minecraft/server/BlockDispenser.java b/src/main/java/net/minecraft/server/BlockDispenser.java
index b3fed06dcf..e9c9ec590e 100644
--- a/src/main/java/net/minecraft/server/BlockDispenser.java
+++ b/src/main/java/net/minecraft/server/BlockDispenser.java
@@ -159,6 +159,8 @@ public class BlockDispenser extends BlockContainer {
                     }
                 }
             }
+
+            world.m(i, j, k, l);
         }
 
         super.remove(world, i, j, k, l, i1);
diff --git a/src/main/java/net/minecraft/server/ContainerAnvil.java b/src/main/java/net/minecraft/server/ContainerAnvil.java
index fbf76421ad..c0d1128d59 100644
--- a/src/main/java/net/minecraft/server/ContainerAnvil.java
+++ b/src/main/java/net/minecraft/server/ContainerAnvil.java
@@ -148,7 +148,7 @@ public class ContainerAnvil extends Container {
                         int k2 = l1 - k1;
                         boolean flag1 = enchantment.canEnchant(itemstack);
 
-                        if (this.n.abilities.canInstantlyBuild) {
+                        if (this.n.abilities.canInstantlyBuild || itemstack.id == ItemEnchantedBook.ENCHANTED_BOOK.id) {
                             flag1 = true;
                         }
 
diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java
index f985c05585..bd7e41c18e 100644
--- a/src/main/java/net/minecraft/server/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/DedicatedServer.java
@@ -48,7 +48,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer
         System.setErr(new PrintStream(new LoggerOutputStream(this.getLogger().getLogger(), Level.SEVERE), true));
         // CraftBukkit end
 
-        this.getLogger().info("Starting minecraft server version 1.5");
+        this.getLogger().info("Starting minecraft server version 1.5.1");
         if (Runtime.getRuntime().maxMemory() / 1024L / 1024L < 512L) {
             this.getLogger().warning("To start the server with more ram, launch it as \"java -Xmx1024M -Xms1024M -jar minecraft_server.jar\"");
         }
diff --git a/src/main/java/net/minecraft/server/DedicatedServerConnectionThread.java b/src/main/java/net/minecraft/server/DedicatedServerConnectionThread.java
index 5be8dc2b69..fbe96fa494 100644
--- a/src/main/java/net/minecraft/server/DedicatedServerConnectionThread.java
+++ b/src/main/java/net/minecraft/server/DedicatedServerConnectionThread.java
@@ -57,28 +57,28 @@ public class DedicatedServerConnectionThread extends Thread {
         while (this.e.a) {
             try {
                 Socket socket = this.d.accept();
-                InetAddress inetaddress = socket.getInetAddress();
-                long i = System.currentTimeMillis();
-                HashMap hashmap = this.b;
 
-                // CraftBukkit start
+                // CraftBukkit start - connection throttle
+                InetAddress address = socket.getInetAddress();
+                long currentTime = System.currentTimeMillis();
+
                 if (((MinecraftServer) this.e.d()).server == null) {
                     socket.close();
                     continue;
                 }
 
                 connectionThrottle = ((MinecraftServer) this.e.d()).server.getConnectionThrottle();
-                // CraftBukkit end
 
                 synchronized (this.b) {
-                    if (this.b.containsKey(inetaddress) && !b(inetaddress) && i - ((Long) this.b.get(inetaddress)).longValue() < connectionThrottle) {
-                        this.b.put(inetaddress, Long.valueOf(i));
+                    if (this.b.containsKey(address) && !"127.0.0.1".equals(address.getHostAddress()) && currentTime - ((Long) this.b.get(address)).longValue() < connectionThrottle) {
+                        this.b.put(address, Long.valueOf(currentTime));
                         socket.close();
                         continue;
                     }
 
-                    this.b.put(inetaddress, Long.valueOf(i));
+                    this.b.put(address, Long.valueOf(currentTime));
                 }
+                // CraftBukkit end
 
                 PendingConnection pendingconnection = new PendingConnection(this.e.d(), socket, "Connection #" + this.c++);
 
@@ -103,10 +103,6 @@ public class DedicatedServerConnectionThread extends Thread {
         }
     }
 
-    private static boolean b(InetAddress inetaddress) {
-        return "127.0.0.1".equals(inetaddress.getHostAddress());
-    }
-
     public void a(InetAddress inetaddress) {
         if (inetaddress != null) {
             HashMap hashmap = this.b;
diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java
index b9667a0e16..2e7cb431ec 100644
--- a/src/main/java/net/minecraft/server/Entity.java
+++ b/src/main/java/net/minecraft/server/Entity.java
@@ -88,7 +88,7 @@ public abstract class Entity {
     public int ticksLived;
     public int maxFireTicks;
     public int fireTicks; // CraftBukkit - private -> public
-    protected boolean ae;
+    protected boolean inWater;
     public int noDamageTicks;
     private boolean justCreated;
     protected boolean fireProof;
@@ -137,7 +137,7 @@ public abstract class Entity {
         this.ticksLived = 0;
         this.maxFireTicks = 1;
         this.fireTicks = 0;
-        this.ae = false;
+        this.inWater = false;
         this.noDamageTicks = 0;
         this.justCreated = true;
         this.fireProof = false;
@@ -819,16 +819,16 @@ public abstract class Entity {
     }
 
     public boolean F() {
-        return this.ae || this.world.F(MathHelper.floor(this.locX), MathHelper.floor(this.locY), MathHelper.floor(this.locZ)) || this.world.F(MathHelper.floor(this.locX), MathHelper.floor(this.locY + (double) this.length), MathHelper.floor(this.locZ));
+        return this.inWater || this.world.F(MathHelper.floor(this.locX), MathHelper.floor(this.locY), MathHelper.floor(this.locZ)) || this.world.F(MathHelper.floor(this.locX), MathHelper.floor(this.locY + (double) this.length), MathHelper.floor(this.locZ));
     }
 
     public boolean G() {
-        return this.ae;
+        return this.inWater;
     }
 
     public boolean H() {
         if (this.world.a(this.boundingBox.grow(0.0D, -0.4000000059604645D, 0.0D).shrink(0.001D, 0.001D, 0.001D), Material.WATER, this)) {
-            if (!this.ae && !this.justCreated) {
+            if (!this.inWater && !this.justCreated) {
                 float f = MathHelper.sqrt(this.motX * this.motX * 0.20000000298023224D + this.motY * this.motY + this.motZ * this.motZ * 0.20000000298023224D) * 0.2F;
 
                 if (f > 1.0F) {
@@ -856,13 +856,13 @@ public abstract class Entity {
             }
 
             this.fallDistance = 0.0F;
-            this.ae = true;
+            this.inWater = true;
             this.fireTicks = 0;
         } else {
-            this.ae = false;
+            this.inWater = false;
         }
 
-        return this.ae;
+        return this.inWater;
     }
 
     public boolean a(Material material) {
diff --git a/src/main/java/net/minecraft/server/EntityEnderDragon.java b/src/main/java/net/minecraft/server/EntityEnderDragon.java
index 7019a1a23a..6d381bed57 100644
--- a/src/main/java/net/minecraft/server/EntityEnderDragon.java
+++ b/src/main/java/net/minecraft/server/EntityEnderDragon.java
@@ -430,7 +430,7 @@ public class EntityEnderDragon extends EntityLiving implements IComplex {
                     int j2 = this.world.getTypeId(k1, l1, i2);
 
                     if (j2 != 0) {
-                        if (j2 != Block.OBSIDIAN.id && j2 != Block.WHITESTONE.id && j2 != Block.BEDROCK.id) {
+                        if (j2 != Block.OBSIDIAN.id && j2 != Block.WHITESTONE.id && j2 != Block.BEDROCK.id && this.world.getGameRules().getBoolean("mobGriefing")) {
                             // CraftBukkit start - add blocks to list rather than destroying them
                             // flag1 = this.world.setAir(k1, l1, i2) || flag1;
                             flag1 = true;
diff --git a/src/main/java/net/minecraft/server/EntityHuman.java b/src/main/java/net/minecraft/server/EntityHuman.java
index bfcb6ce7cc..1f7b8ad7e5 100644
--- a/src/main/java/net/minecraft/server/EntityHuman.java
+++ b/src/main/java/net/minecraft/server/EntityHuman.java
@@ -436,11 +436,11 @@ public abstract class EntityHuman extends EntityLiving implements ICommandListen
 
     public void c(Entity entity, int i) {
         this.addScore(i);
-        Collection collection = this.getScoreboard().a(IObjective.e);
+        Collection collection = this.getScoreboard().getObjectivesForCriteria(IScoreboardCriteria.e);
 
         if (entity instanceof EntityHuman) {
             this.a(StatisticList.A, 1);
-            collection.addAll(this.getScoreboard().a(IObjective.d));
+            collection.addAll(this.getScoreboard().getObjectivesForCriteria(IScoreboardCriteria.d));
         } else {
             this.a(StatisticList.z, 1);
         }
@@ -449,9 +449,9 @@ public abstract class EntityHuman extends EntityLiving implements ICommandListen
 
         while (iterator.hasNext()) {
             ScoreboardObjective scoreboardobjective = (ScoreboardObjective) iterator.next();
-            ScoreboardScore scoreboardscore = this.getScoreboard().a(this.getLocalizedName(), scoreboardobjective);
+            ScoreboardScore scoreboardscore = this.getScoreboard().getPlayerScoreForObjective(this.getLocalizedName(), scoreboardobjective);
 
-            scoreboardscore.a();
+            scoreboardscore.incrementScore();
         }
     }
 
@@ -690,7 +690,7 @@ public abstract class EntityHuman extends EntityLiving implements ICommandListen
         ScoreboardTeam scoreboardteam = this.getScoreboardTeam();
         ScoreboardTeam scoreboardteam1 = entityhuman.getScoreboardTeam();
 
-        return scoreboardteam != scoreboardteam1 ? true : (scoreboardteam != null ? scoreboardteam.g() : true);
+        return scoreboardteam != scoreboardteam1 ? true : (scoreboardteam != null ? scoreboardteam.allowFriendlyFire() : true);
     }
 
     protected void a(EntityLiving entityliving, boolean flag) {
@@ -1490,10 +1490,10 @@ public abstract class EntityHuman extends EntityLiving implements ICommandListen
     }
 
     public ScoreboardTeam getScoreboardTeam() {
-        return this.getScoreboard().i(this.name);
+        return this.getScoreboard().getPlayerTeam(this.name);
     }
 
     public String getScoreboardDisplayName() {
-        return ScoreboardTeam.a(this.getScoreboardTeam(), this.name);
+        return ScoreboardTeam.getPlayerDisplayName(this.getScoreboardTeam(), this.name);
     }
 }
diff --git a/src/main/java/net/minecraft/server/EntityLiving.java b/src/main/java/net/minecraft/server/EntityLiving.java
index 27b2ce24fe..15fbf6926c 100644
--- a/src/main/java/net/minecraft/server/EntityLiving.java
+++ b/src/main/java/net/minecraft/server/EntityLiving.java
@@ -5,6 +5,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Random;
+import java.util.concurrent.Callable;
 
 // CraftBukkit start
 import org.bukkit.craftbukkit.event.CraftEventFactory;
@@ -1686,13 +1687,26 @@ public abstract class EntityLiving extends Entity {
             Integer integer = (Integer) iterator.next();
             MobEffect mobeffect = (MobEffect) this.effects.get(integer);
 
-            if (!mobeffect.tick(this)) {
-                if (!this.world.isStatic) {
-                    iterator.remove();
-                    this.c(mobeffect);
+            try {
+                if (!mobeffect.tick(this)) {
+                    if (!this.world.isStatic) {
+                        iterator.remove();
+                        this.c(mobeffect);
+                    }
+                } else if (mobeffect.getDuration() % 600 == 0) {
+                    this.b(mobeffect);
                 }
-            } else if (mobeffect.getDuration() % 600 == 0) {
-                this.b(mobeffect);
+            } catch (Throwable throwable) {
+                CrashReport crashreport = CrashReport.a(throwable, "Ticking mob effect instance");
+                CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Mob effect being ticked");
+
+                crashreportsystemdetails.a("Effect Name", (Callable) (new CrashReportEffectName(this, mobeffect)));
+                crashreportsystemdetails.a("Effect ID", (Callable) (new CrashReportEffectID(this, mobeffect)));
+                crashreportsystemdetails.a("Effect Duration", (Callable) (new CrashReportEffectDuration(this, mobeffect)));
+                crashreportsystemdetails.a("Effect Amplifier", (Callable) (new CrashReportEffectAmplifier(this, mobeffect)));
+                crashreportsystemdetails.a("Effect is Splash", (Callable) (new CrashReportEffectSplash(this, mobeffect)));
+                crashreportsystemdetails.a("Effect is Ambient", (Callable) (new CrashReportEffectAmbient(this, mobeffect)));
+                throw new ReportedException(crashreport);
             }
         }
 
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
index 03140c2723..573c0f0449 100644
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
@@ -201,13 +201,13 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
 
     public void setHealth(int i) {
         super.setHealth(i);
-        Collection collection = this.getScoreboard().a(IObjective.f);
+        Collection collection = this.getScoreboard().getObjectivesForCriteria(IScoreboardCriteria.f);
         Iterator iterator = collection.iterator();
 
         while (iterator.hasNext()) {
             ScoreboardObjective scoreboardobjective = (ScoreboardObjective) iterator.next();
 
-            this.getScoreboard().a(this.getLocalizedName(), scoreboardobjective).a(Arrays.asList(new EntityHuman[] { this}));
+            this.getScoreboard().getPlayerScoreForObjective(this.getLocalizedName(), scoreboardobjective).updateForList(Arrays.asList(new EntityHuman[] { this}));
         }
     }
 
@@ -304,14 +304,14 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
         this.closeInventory();
         // CraftBukkit end
 
-        Collection collection = this.world.getScoreboard().a(IObjective.c);
+        Collection collection = this.world.getScoreboard().getObjectivesForCriteria(IScoreboardCriteria.c);
         Iterator iterator = collection.iterator();
 
         while (iterator.hasNext()) {
             ScoreboardObjective scoreboardobjective = (ScoreboardObjective) iterator.next();
-            ScoreboardScore scoreboardscore = this.getScoreboard().a(this.getLocalizedName(), scoreboardobjective);
+            ScoreboardScore scoreboardscore = this.getScoreboard().getPlayerScoreForObjective(this.getLocalizedName(), scoreboardobjective);
 
-            scoreboardscore.a();
+            scoreboardscore.incrementScore();
         }
 
         EntityLiving entityliving = this.bN();
diff --git a/src/main/java/net/minecraft/server/EntitySquid.java b/src/main/java/net/minecraft/server/EntitySquid.java
index 30259de3b6..58a81106c7 100644
--- a/src/main/java/net/minecraft/server/EntitySquid.java
+++ b/src/main/java/net/minecraft/server/EntitySquid.java
@@ -133,7 +133,7 @@ public class EntitySquid extends EntityWaterAnimal {
         ++this.bC;
         if (this.bC > 100) {
             this.bO = this.bP = this.bQ = 0.0F;
-        } else if (this.random.nextInt(50) == 0 || !this.ae || this.bO == 0.0F && this.bP == 0.0F && this.bQ == 0.0F) {
+        } else if (this.random.nextInt(50) == 0 || !this.inWater || this.bO == 0.0F && this.bP == 0.0F && this.bQ == 0.0F) {
             float f = this.random.nextFloat() * 3.1415927F * 2.0F;
 
             this.bO = MathHelper.cos(f) * 0.2F;
diff --git a/src/main/java/net/minecraft/server/EntityTracker.java b/src/main/java/net/minecraft/server/EntityTracker.java
index cfcd647a84..4de1273206 100644
--- a/src/main/java/net/minecraft/server/EntityTracker.java
+++ b/src/main/java/net/minecraft/server/EntityTracker.java
@@ -18,8 +18,7 @@ public class EntityTracker {
         this.d = worldserver.getMinecraftServer().getPlayerList().a();
     }
 
-    // CraftBukkit - synchronized
-    public synchronized void track(Entity entity) {
+    public void track(Entity entity) {
         if (entity instanceof EntityPlayer) {
             this.addEntity(entity, 512, 2);
             EntityPlayer entityplayer = (EntityPlayer) entity;
@@ -89,8 +88,7 @@ public class EntityTracker {
         this.addEntity(entity, i, j, false);
     }
 
-    // CraftBukkit - synchronized
-    public synchronized void addEntity(Entity entity, int i, int j, boolean flag) {
+    public void addEntity(Entity entity, int i, int j, boolean flag) {
         if (i > this.d) {
             i = this.d;
         }
@@ -98,13 +96,13 @@ public class EntityTracker {
         try {
             if (this.trackedEntities.b(entity.id)) {
                 throw new IllegalStateException("Entity is already tracked!");
-            } else {
-                EntityTrackerEntry entitytrackerentry = new EntityTrackerEntry(entity, i, j, flag);
-
-                this.b.add(entitytrackerentry);
-                this.trackedEntities.a(entity.id, entitytrackerentry);
-                entitytrackerentry.scanPlayers(this.world.players);
             }
+
+            EntityTrackerEntry entitytrackerentry = new EntityTrackerEntry(entity, i, j, flag);
+
+            this.b.add(entitytrackerentry);
+            this.trackedEntities.a(entity.id, entitytrackerentry);
+            entitytrackerentry.scanPlayers(this.world.players);
         } catch (Throwable throwable) {
             CrashReport crashreport = CrashReport.a(throwable, "Adding entity to track");
             CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity To Track");
@@ -112,12 +110,20 @@ public class EntityTracker {
             crashreportsystemdetails.a("Tracking range", (i + " blocks"));
             crashreportsystemdetails.a("Update interval", (Callable) (new CrashReportEntityTrackerUpdateInterval(this, j)));
             entity.a(crashreportsystemdetails);
-            throw new ReportedException(crashreport);
+            CrashReportSystemDetails crashreportsystemdetails1 = crashreport.a("Entity That Is Already Tracked");
+
+            ((EntityTrackerEntry) this.trackedEntities.get(entity.id)).tracker.a(crashreportsystemdetails1);
+
+            try {
+                throw new ReportedException(crashreport);
+            } catch (ReportedException reportedexception) {
+                System.err.println("\"Silently\" catching entity tracking error.");
+                reportedexception.printStackTrace();
+            }
         }
     }
 
-    // CraftBukkit - synchronized
-    public synchronized void untrackEntity(Entity entity) {
+    public void untrackEntity(Entity entity) {
         if (entity instanceof EntityPlayer) {
             EntityPlayer entityplayer = (EntityPlayer) entity;
             Iterator iterator = this.b.iterator();
@@ -137,8 +143,7 @@ public class EntityTracker {
         }
     }
 
-    // CraftBukkit - synchronized
-    public synchronized void updatePlayers() {
+    public void updatePlayers() {
         ArrayList arraylist = new ArrayList();
         Iterator iterator = this.b.iterator();
 
@@ -165,8 +170,7 @@ public class EntityTracker {
         }
     }
 
-    // CraftBukkit - synchronized
-    public synchronized void a(Entity entity, Packet packet) {
+    public void a(Entity entity, Packet packet) {
         EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) this.trackedEntities.get(entity.id);
 
         if (entitytrackerentry != null) {
@@ -174,8 +178,7 @@ public class EntityTracker {
         }
     }
 
-    // CraftBukkit - synchronized
-    public synchronized void sendPacketToEntity(Entity entity, Packet packet) {
+    public void sendPacketToEntity(Entity entity, Packet packet) {
         EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) this.trackedEntities.get(entity.id);
 
         if (entitytrackerentry != null) {
@@ -183,8 +186,7 @@ public class EntityTracker {
         }
     }
 
-    // CraftBukkit - synchronized
-    public synchronized void untrackPlayer(EntityPlayer entityplayer) {
+    public void untrackPlayer(EntityPlayer entityplayer) {
         Iterator iterator = this.b.iterator();
 
         while (iterator.hasNext()) {
diff --git a/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
index 4948f23d3c..ae9ed5233f 100644
--- a/src/main/java/net/minecraft/server/EntityTrackerEntry.java
+++ b/src/main/java/net/minecraft/server/EntityTrackerEntry.java
@@ -132,22 +132,24 @@ public class EntityTrackerEntry {
                 }
                 // CraftBukkit end
 
-                if (j1 >= -128 && j1 < 128 && k1 >= -128 && k1 < 128 && l1 >= -128 && l1 < 128 && this.u <= 400 && !this.w) {
-                    if (flag && flag1) {
-                        object = new Packet33RelEntityMoveLook(this.tracker.id, (byte) j1, (byte) k1, (byte) l1, (byte) l, (byte) i1);
-                    } else if (flag) {
-                        object = new Packet31RelEntityMove(this.tracker.id, (byte) j1, (byte) k1, (byte) l1);
-                    } else if (flag1) {
-                        object = new Packet32EntityLook(this.tracker.id, (byte) l, (byte) i1);
+                if (this.m > 0) {
+                    if (j1 >= -128 && j1 < 128 && k1 >= -128 && k1 < 128 && l1 >= -128 && l1 < 128 && this.u <= 400 && !this.w) {
+                        if (flag && flag1) {
+                            object = new Packet33RelEntityMoveLook(this.tracker.id, (byte) j1, (byte) k1, (byte) l1, (byte) l, (byte) i1);
+                        } else if (flag) {
+                            object = new Packet31RelEntityMove(this.tracker.id, (byte) j1, (byte) k1, (byte) l1);
+                        } else if (flag1) {
+                            object = new Packet32EntityLook(this.tracker.id, (byte) l, (byte) i1);
+                        }
+                    } else {
+                        this.u = 0;
+                        // CraftBukkit start - refresh list of who can see a player before sending teleport packet
+                        if (this.tracker instanceof EntityPlayer) {
+                            this.scanPlayers(new java.util.ArrayList(this.trackedPlayers));
+                        }
+                        // CraftBukkit end
+                        object = new Packet34EntityTeleport(this.tracker.id, i, j, k, (byte) l, (byte) i1);
                     }
-                } else {
-                    this.u = 0;
-                    // CraftBukkit start - refresh list of who can see a player before sending teleport packet
-                    if (this.tracker instanceof EntityPlayer) {
-                        this.scanPlayers(new java.util.ArrayList(this.trackedPlayers));
-                    }
-                    // CraftBukkit end
-                    object = new Packet34EntityTeleport(this.tracker.id, i, j, k, (byte) l, (byte) i1);
                 }
 
                 if (this.isMoving) {
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index d3f3f86efe..5c535cc66b 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -746,7 +746,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IMo
     }
 
     public String getVersion() {
-        return "1.5";
+        return "1.5.1";
     }
 
     public int y() {
diff --git a/src/main/java/net/minecraft/server/Packet.java b/src/main/java/net/minecraft/server/Packet.java
index c4212e8351..b82596fc1f 100644
--- a/src/main/java/net/minecraft/server/Packet.java
+++ b/src/main/java/net/minecraft/server/Packet.java
@@ -120,10 +120,10 @@ public abstract class Packet {
 
         // CraftBukkit start
         catch (java.net.SocketTimeoutException exception) {
-            iconsolelogmanager.severe("Read timed out");
+            iconsolelogmanager.info("Read timed out");
             return null;
         } catch (java.net.SocketException exception) {
-            iconsolelogmanager.severe("Connection reset");
+            iconsolelogmanager.info("Connection reset");
             return null;
         }
         // CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java
index d57ff15b22..6efb5b6a99 100644
--- a/src/main/java/net/minecraft/server/PlayerList.java
+++ b/src/main/java/net/minecraft/server/PlayerList.java
@@ -129,7 +129,7 @@ public abstract class PlayerList {
 
     protected void a(ScoreboardServer scoreboardserver, EntityPlayer entityplayer) {
         HashSet hashset = new HashSet();
-        Iterator iterator = scoreboardserver.g().iterator();
+        Iterator iterator = scoreboardserver.getTeams().iterator();
 
         while (iterator.hasNext()) {
             ScoreboardTeam scoreboardteam = (ScoreboardTeam) iterator.next();
@@ -138,10 +138,10 @@ public abstract class PlayerList {
         }
 
         for (int i = 0; i < 3; ++i) {
-            ScoreboardObjective scoreboardobjective = scoreboardserver.a(i);
+            ScoreboardObjective scoreboardobjective = scoreboardserver.getObjectiveForSlot(i);
 
             if (scoreboardobjective != null && !hashset.contains(scoreboardobjective)) {
-                List list = scoreboardserver.d(scoreboardobjective);
+                List list = scoreboardserver.getScoreboardScorePacketsForObjective(scoreboardobjective);
                 Iterator iterator1 = list.iterator();
 
                 while (iterator1.hasNext()) {
@@ -845,7 +845,7 @@ public abstract class PlayerList {
                     }
 
                     ScoreboardTeam scoreboardteam = entityplayer.getScoreboardTeam();
-                    String s2 = scoreboardteam == null ? "" : scoreboardteam.b();
+                    String s2 = scoreboardteam == null ? "" : scoreboardteam.getName();
 
                     if (flag1 == s1.equalsIgnoreCase(s2)) {
                         continue;
@@ -904,15 +904,15 @@ public abstract class PlayerList {
                 }
 
                 Scoreboard scoreboard = entityhuman.getScoreboard();
-                ScoreboardObjective scoreboardobjective = scoreboard.b(s);
+                ScoreboardObjective scoreboardobjective = scoreboard.getObjective(s);
 
                 if (scoreboardobjective == null) {
                     return false;
                 }
 
-                ScoreboardScore scoreboardscore = entityhuman.getScoreboard().a(entityhuman.getLocalizedName(), scoreboardobjective);
+                ScoreboardScore scoreboardscore = entityhuman.getScoreboard().getPlayerScoreForObjective(entityhuman.getLocalizedName(), scoreboardobjective);
 
-                i = scoreboardscore.c();
+                i = scoreboardscore.getScore();
                 if (i < ((Integer) entry.getValue()).intValue() && flag) {
                     return false;
                 }
diff --git a/src/main/java/net/minecraft/server/TileEntityBrewingStand.java b/src/main/java/net/minecraft/server/TileEntityBrewingStand.java
index 8d77f12d47..88039bc3c1 100644
--- a/src/main/java/net/minecraft/server/TileEntityBrewingStand.java
+++ b/src/main/java/net/minecraft/server/TileEntityBrewingStand.java
@@ -10,11 +10,13 @@ import org.bukkit.event.inventory.BrewEvent;
 
 public class TileEntityBrewingStand extends TileEntity implements IWorldInventory {
 
-    public ItemStack[] items = new ItemStack[4]; // CraftBukkit private -> public
-    public int brewTime; // CraftBukkit private -> public
-    private int c;
-    private int d;
-    private String e;
+    private static final int[] a = new int[] { 3};
+    private static final int[] b = new int[] { 0, 1, 2};
+    public ItemStack[] items = new ItemStack[4]; // CraftBukkit - private -> public
+    public int brewTime; // CraftBukkit - private -> public
+    private int e;
+    private int f;
+    private String g;
 
     public TileEntityBrewingStand() {}
 
@@ -44,15 +46,15 @@ public class TileEntityBrewingStand extends TileEntity implements IWorldInventor
     // CraftBukkit end
 
     public String getName() {
-        return this.c() ? this.e : "container.brewing";
+        return this.c() ? this.g : "container.brewing";
     }
 
     public boolean c() {
-        return this.e != null && this.e.length() > 0;
+        return this.g != null && this.g.length() > 0;
     }
 
     public void a(String s) {
-        this.e = s;
+        this.g = s;
     }
 
     public int getSize() {
@@ -68,19 +70,19 @@ public class TileEntityBrewingStand extends TileEntity implements IWorldInventor
             } else if (!this.l()) {
                 this.brewTime = 0;
                 this.update();
-            } else if (this.d != this.items[3].id) {
+            } else if (this.f != this.items[3].id) {
                 this.brewTime = 0;
                 this.update();
             }
         } else if (this.l()) {
             this.brewTime = 400;
-            this.d = this.items[3].id;
+            this.f = this.items[3].id;
         }
 
         int i = this.j();
 
-        if (i != this.c) {
-            this.c = i;
+        if (i != this.e) {
+            this.e = i;
             this.world.setData(this.x, this.y, this.z, i, 2);
         }
 
@@ -190,7 +192,7 @@ public class TileEntityBrewingStand extends TileEntity implements IWorldInventor
 
         this.brewTime = nbttagcompound.getShort("BrewTime");
         if (nbttagcompound.hasKey("CustomName")) {
-            this.e = nbttagcompound.getString("CustomName");
+            this.g = nbttagcompound.getString("CustomName");
         }
     }
 
@@ -211,7 +213,7 @@ public class TileEntityBrewingStand extends TileEntity implements IWorldInventor
 
         nbttagcompound.set("Items", nbttaglist);
         if (this.c()) {
-            nbttagcompound.setString("CustomName", this.e);
+            nbttagcompound.setString("CustomName", this.g);
         }
     }
 
@@ -275,11 +277,15 @@ public class TileEntityBrewingStand extends TileEntity implements IWorldInventor
         return i;
     }
 
-    public int c(int i) {
-        return i == 1 ? 3 : 0;
+    public int[] getSlotsForFace(int i) {
+        return i == 1 ? a : b;
     }
 
-    public int d(int i) {
-        return i == 1 ? 1 : 3;
+    public boolean canPlaceItemThroughFace(int i, ItemStack itemstack, int j) {
+        return this.b(i, itemstack);
+    }
+
+    public boolean canTakeItemThroughFace(int i, ItemStack itemstack, int j) {
+        return true;
     }
 }
diff --git a/src/main/java/net/minecraft/server/TileEntityFurnace.java b/src/main/java/net/minecraft/server/TileEntityFurnace.java
index b8f1d3e9db..9e5a2f5099 100644
--- a/src/main/java/net/minecraft/server/TileEntityFurnace.java
+++ b/src/main/java/net/minecraft/server/TileEntityFurnace.java
@@ -12,11 +12,14 @@ import org.bukkit.craftbukkit.entity.CraftHumanEntity;
 
 public class TileEntityFurnace extends TileEntity implements IWorldInventory {
 
+    private static final int[] d = new int[] { 0};
+    private static final int[] e = new int[] { 2, 1};
+    private static final int[] f = new int[] { 1};
     private ItemStack[] items = new ItemStack[3];
     public int burnTime = 0;
     public int ticksForCurrentFuel = 0;
     public int cookTime = 0;
-    private String e;
+    private String h;
 
     // CraftBukkit start
     private int lastTick = (int) (System.currentTimeMillis() / 50);
@@ -94,15 +97,15 @@ public class TileEntityFurnace extends TileEntity implements IWorldInventory {
     }
 
     public String getName() {
-        return this.c() ? this.e : "container.furnace";
+        return this.c() ? this.h : "container.furnace";
     }
 
     public boolean c() {
-        return this.e != null && this.e.length() > 0;
+        return this.h != null && this.h.length() > 0;
     }
 
     public void a(String s) {
-        this.e = s;
+        this.h = s;
     }
 
     public void a(NBTTagCompound nbttagcompound) {
@@ -124,7 +127,7 @@ public class TileEntityFurnace extends TileEntity implements IWorldInventory {
         this.cookTime = nbttagcompound.getShort("CookTime");
         this.ticksForCurrentFuel = fuelTime(this.items[1]);
         if (nbttagcompound.hasKey("CustomName")) {
-            this.e = nbttagcompound.getString("CustomName");
+            this.h = nbttagcompound.getString("CustomName");
         }
     }
 
@@ -146,7 +149,7 @@ public class TileEntityFurnace extends TileEntity implements IWorldInventory {
 
         nbttagcompound.set("Items", nbttaglist);
         if (this.c()) {
-            nbttagcompound.setString("CustomName", this.e);
+            nbttagcompound.setString("CustomName", this.h);
         }
     }
 
@@ -319,11 +322,15 @@ public class TileEntityFurnace extends TileEntity implements IWorldInventory {
         return i == 2 ? false : (i == 1 ? isFuel(itemstack) : true);
     }
 
-    public int c(int i) {
-        return i == 0 ? 2 : (i == 1 ? 0 : 1);
+    public int[] getSlotsForFace(int i) {
+        return i == 0 ? e : (i == 1 ? d : f);
     }
 
-    public int d(int i) {
-        return 1;
+    public boolean canPlaceItemThroughFace(int i, ItemStack itemstack, int j) {
+        return this.b(i, itemstack);
+    }
+
+    public boolean canTakeItemThroughFace(int i, ItemStack itemstack, int j) {
+        return j != 0 || i != 1 || itemstack.id == Item.BUCKET.id;
     }
 }
diff --git a/src/main/java/net/minecraft/server/TileEntityHopper.java b/src/main/java/net/minecraft/server/TileEntityHopper.java
index 25cf3df842..a1e2bc2673 100644
--- a/src/main/java/net/minecraft/server/TileEntityHopper.java
+++ b/src/main/java/net/minecraft/server/TileEntityHopper.java
@@ -39,7 +39,6 @@ public class TileEntityHopper extends TileEntity implements IHopper {
     }
     // CraftBukkit end
 
-
     public TileEntityHopper() {}
 
     public void a(NBTTagCompound nbttagcompound) {
@@ -176,7 +175,7 @@ public class TileEntityHopper extends TileEntity implements IHopper {
     public boolean j() {
         if (this.world != null && !this.world.isStatic) {
             if (!this.l() && BlockHopper.d(this.p())) {
-                boolean flag = this.u() | a((IHopper) this);
+                boolean flag = this.u() | suckInItems(this);
 
                 if (flag) {
                     this.c(8);
@@ -192,71 +191,83 @@ public class TileEntityHopper extends TileEntity implements IHopper {
     }
 
     private boolean u() {
-        int i = a(this, -1);
-        boolean flag = false;
+        IInventory iinventory = this.v();
 
-        if (i > -1) {
-            IInventory iinventory = this.v();
+        if (iinventory == null) {
+            return false;
+        } else {
+            for (int i = 0; i < this.getSize(); ++i) {
+                if (this.getItem(i) != null) {
+                    ItemStack itemstack = this.getItem(i).cloneItemStack();
+                    ItemStack itemstack1 = addItem(iinventory, this.splitStack(i, 1), Facing.OPPOSITE_FACING[BlockHopper.c(this.p())]);
 
-            if (iinventory != null) {
-                ItemStack itemstack = this.getItem(i).cloneItemStack();
-                ItemStack itemstack1 = a(iinventory, this.splitStack(i, 1), Facing.OPPOSITE_FACING[BlockHopper.c(this.p())]);
+                    if (itemstack1 == null || itemstack1.count == 0) {
+                        iinventory.update();
+                        return true;
+                    }
 
-                if (itemstack1 != null && itemstack1.count != 0) {
                     this.setItem(i, itemstack);
-                } else {
-                    flag |= true;
-                    iinventory.update();
                 }
             }
-        }
 
-        return flag;
+            return false;
+        }
     }
 
-    public static boolean a(IHopper ihopper) {
-        boolean flag = false;
-        IInventory iinventory = b(ihopper);
+    public static boolean suckInItems(IHopper ihopper) {
+        IInventory iinventory = getSourceInventory(ihopper);
 
         if (iinventory != null) {
             byte b0 = 0;
-            int i = 0;
-            int j = iinventory.getSize();
 
             if (iinventory instanceof IWorldInventory && b0 > -1) {
                 IWorldInventory iworldinventory = (IWorldInventory) iinventory;
+                int[] aint = iworldinventory.getSlotsForFace(b0);
 
-                i = iworldinventory.c(b0);
-                j = Math.min(j, i + iworldinventory.d(b0));
-            }
+                for (int i = 0; i < aint.length; ++i) {
+                    if (tryTakeInItemFromSlot(ihopper, iinventory, aint[i], b0)) {
+                        return true;
+                    }
+                }
+            } else {
+                int j = iinventory.getSize();
 
-            for (int k = i; k < j && !flag; ++k) {
-                ItemStack itemstack = iinventory.getItem(k);
-
-                if (itemstack != null) {
-                    ItemStack itemstack1 = itemstack.cloneItemStack();
-                    ItemStack itemstack2 = a(ihopper, iinventory.splitStack(k, 1), -1);
-
-                    if (itemstack2 != null && itemstack2.count != 0) {
-                        iinventory.setItem(k, itemstack1);
-                    } else {
-                        flag |= true;
-                        iinventory.update();
+                for (int k = 0; k < j; ++k) {
+                    if (tryTakeInItemFromSlot(ihopper, iinventory, k, b0)) {
+                        return true;
                     }
                 }
             }
         } else {
-            EntityItem entityitem = a(ihopper.getWorld(), ihopper.aA(), ihopper.aB() + 1.0D, ihopper.aC());
+            EntityItem entityitem = getEntityItemAt(ihopper.getWorld(), ihopper.aA(), ihopper.aB() + 1.0D, ihopper.aC());
 
             if (entityitem != null) {
-                flag |= a((IInventory) ihopper, entityitem);
+                return addEntityItem(ihopper, entityitem);
             }
         }
 
-        return flag;
+        return false;
     }
 
-    public static boolean a(IInventory iinventory, EntityItem entityitem) {
+    private static boolean tryTakeInItemFromSlot(IHopper ihopper, IInventory iinventory, int i, int j) {
+        ItemStack itemstack = iinventory.getItem(i);
+
+        if (itemstack != null && canTakeItemFromInventory(iinventory, itemstack, i, j)) {
+            ItemStack itemstack1 = itemstack.cloneItemStack();
+            ItemStack itemstack2 = addItem(ihopper, iinventory.splitStack(i, 1), -1);
+
+            if (itemstack2 == null || itemstack2.count == 0) {
+                iinventory.update();
+                return true;
+            }
+
+            iinventory.setItem(i, itemstack1);
+        }
+
+        return false;
+    }
+
+    public static boolean addEntityItem(IInventory iinventory, EntityItem entityitem) {
         boolean flag = false;
 
         if (entityitem == null) {
@@ -271,7 +282,7 @@ public class TileEntityHopper extends TileEntity implements IHopper {
             // CraftBukkit end
 
             ItemStack itemstack = entityitem.getItemStack().cloneItemStack();
-            ItemStack itemstack1 = a(iinventory, itemstack, -1);
+            ItemStack itemstack1 = addItem(iinventory, itemstack, -1);
 
             if (itemstack1 != null && itemstack1.count != 0) {
                 entityitem.setItemStack(itemstack1);
@@ -284,63 +295,19 @@ public class TileEntityHopper extends TileEntity implements IHopper {
         }
     }
 
-    public static int a(IInventory iinventory, int i) {
-        int j = 0;
-        int k = iinventory.getSize();
-
+    public static ItemStack addItem(IInventory iinventory, ItemStack itemstack, int i) {
         if (iinventory instanceof IWorldInventory && i > -1) {
             IWorldInventory iworldinventory = (IWorldInventory) iinventory;
+            int[] aint = iworldinventory.getSlotsForFace(i);
 
-            j = iworldinventory.c(i);
-            k = Math.min(k, j + iworldinventory.d(i));
-        }
-
-        for (int l = j; l < k; ++l) {
-            if (iinventory.getItem(l) != null) {
-                return l;
+            for (int j = 0; j < aint.length && itemstack != null && itemstack.count > 0; ++j) {
+                itemstack = tryMoveInItem(iinventory, itemstack, aint[j], i);
             }
-        }
+        } else {
+            int k = iinventory.getSize();
 
-        return -1;
-    }
-
-    public static ItemStack a(IInventory iinventory, ItemStack itemstack, int i) {
-        int j = 0;
-        int k = iinventory.getSize();
-
-        if (iinventory instanceof IWorldInventory && i > -1) {
-            IWorldInventory iworldinventory = (IWorldInventory) iinventory;
-
-            j = iworldinventory.c(i);
-            k = Math.min(k, j + iworldinventory.d(i));
-        }
-
-        for (int l = j; l < k && itemstack != null && itemstack.count > 0; ++l) {
-            ItemStack itemstack1 = iinventory.getItem(l);
-
-            if (iinventory.b(l, itemstack)) {
-                boolean flag = false;
-
-                if (itemstack1 == null) {
-                    iinventory.setItem(l, itemstack);
-                    itemstack = null;
-                    flag = true;
-                } else if (a(itemstack1, itemstack)) {
-                    int i1 = itemstack.getMaxStackSize() - itemstack1.count;
-                    int j1 = Math.min(itemstack.count, i1);
-
-                    itemstack.count -= j1;
-                    itemstack1.count += j1;
-                    flag = j1 > 0;
-                }
-
-                if (flag) {
-                    if (iinventory instanceof TileEntityHopper) {
-                        ((TileEntityHopper) iinventory).c(8);
-                    }
-
-                    iinventory.update();
-                }
+            for (int l = 0; l < k && itemstack != null && itemstack.count > 0; ++l) {
+                itemstack = tryMoveInItem(iinventory, itemstack, l, i);
             }
         }
 
@@ -351,40 +318,76 @@ public class TileEntityHopper extends TileEntity implements IHopper {
         return itemstack;
     }
 
+    private static boolean canPlaceItemInInventory(IInventory iinventory, ItemStack itemstack, int i, int j) {
+        return !iinventory.b(i, itemstack) ? false : !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canPlaceItemThroughFace(i, itemstack, j);
+    }
+
+    private static boolean canTakeItemFromInventory(IInventory iinventory, ItemStack itemstack, int i, int j) {
+        return !(iinventory instanceof IWorldInventory) || ((IWorldInventory) iinventory).canTakeItemThroughFace(i, itemstack, j);
+    }
+
+    private static ItemStack tryMoveInItem(IInventory iinventory, ItemStack itemstack, int i, int j) {
+        ItemStack itemstack1 = iinventory.getItem(i);
+
+        if (canPlaceItemInInventory(iinventory, itemstack, i, j)) {
+            boolean flag = false;
+
+            if (itemstack1 == null) {
+                iinventory.setItem(i, itemstack);
+                itemstack = null;
+                flag = true;
+            } else if (canMergeItems(itemstack1, itemstack)) {
+                int k = itemstack.getMaxStackSize() - itemstack1.count;
+                int l = Math.min(itemstack.count, k);
+
+                itemstack.count -= l;
+                itemstack1.count += l;
+                flag = l > 0;
+            }
+
+            if (flag) {
+                if (iinventory instanceof TileEntityHopper) {
+                    ((TileEntityHopper) iinventory).c(8);
+                }
+
+                iinventory.update();
+            }
+        }
+
+        return itemstack;
+    }
+
     private IInventory v() {
         int i = BlockHopper.c(this.p());
 
-        return b(this.getWorld(), (double) (this.x + Facing.b[i]), (double) (this.y + Facing.c[i]), (double) (this.z + Facing.d[i]));
+        return getInventoryAt(this.getWorld(), (double) (this.x + Facing.b[i]), (double) (this.y + Facing.c[i]), (double) (this.z + Facing.d[i]));
     }
 
-    public static IInventory b(IHopper ihopper) {
-        return b(ihopper.getWorld(), ihopper.aA(), ihopper.aB() + 1.0D, ihopper.aC());
+    public static IInventory getSourceInventory(IHopper ihopper) {
+        return getInventoryAt(ihopper.getWorld(), ihopper.aA(), ihopper.aB() + 1.0D, ihopper.aC());
     }
 
-    public static EntityItem a(World world, double d0, double d1, double d2) {
+    public static EntityItem getEntityItemAt(World world, double d0, double d1, double d2) {
         List list = world.a(EntityItem.class, AxisAlignedBB.a().a(d0, d1, d2, d0 + 1.0D, d1 + 1.0D, d2 + 1.0D), IEntitySelector.a);
 
         return list.size() > 0 ? (EntityItem) list.get(0) : null;
     }
 
-    public static IInventory b(World world, double d0, double d1, double d2) {
+    public static IInventory getInventoryAt(World world, double d0, double d1, double d2) {
         IInventory iinventory = null;
         int i = MathHelper.floor(d0);
         int j = MathHelper.floor(d1);
         int k = MathHelper.floor(d2);
+        TileEntity tileentity = world.getTileEntity(i, j, k);
 
-        if (iinventory == null) {
-            TileEntity tileentity = world.getTileEntity(i, j, k);
+        if (tileentity != null && tileentity instanceof IInventory) {
+            iinventory = (IInventory) tileentity;
+            if (iinventory instanceof TileEntityChest) {
+                int l = world.getTypeId(i, j, k);
+                Block block = Block.byId[l];
 
-            if (tileentity != null && tileentity instanceof IInventory) {
-                iinventory = (IInventory) tileentity;
-                if (iinventory instanceof TileEntityChest) {
-                    int l = world.getTypeId(i, j, k);
-                    Block block = Block.byId[l];
-
-                    if (block instanceof BlockChest) {
-                        iinventory = ((BlockChest) block).g_(world, i, j, k);
-                    }
+                if (block instanceof BlockChest) {
+                    iinventory = ((BlockChest) block).g_(world, i, j, k);
                 }
             }
         }
@@ -400,7 +403,7 @@ public class TileEntityHopper extends TileEntity implements IHopper {
         return iinventory;
     }
 
-    private static boolean a(ItemStack itemstack, ItemStack itemstack1) {
+    private static boolean canMergeItems(ItemStack itemstack, ItemStack itemstack1) {
         return itemstack.id != itemstack1.id ? false : (itemstack.getData() != itemstack1.getData() ? false : (itemstack.count > itemstack.getMaxStackSize() ? false : ItemStack.equals(itemstack, itemstack1)));
     }
 
diff --git a/src/main/java/net/minecraft/server/TileEntityRecordPlayer.java b/src/main/java/net/minecraft/server/TileEntityRecordPlayer.java
new file mode 100644
index 0000000000..48a435ac87
--- /dev/null
+++ b/src/main/java/net/minecraft/server/TileEntityRecordPlayer.java
@@ -0,0 +1,40 @@
+package net.minecraft.server;
+
+public class TileEntityRecordPlayer extends TileEntity {
+
+    private ItemStack record;
+
+    public TileEntityRecordPlayer() {}
+
+    public void a(NBTTagCompound nbttagcompound) {
+        super.a(nbttagcompound);
+        if (nbttagcompound.hasKey("RecordItem")) {
+            this.setRecord(ItemStack.createStack(nbttagcompound.getCompound("RecordItem")));
+        } else if (nbttagcompound.getInt("Record") > 0) {
+            this.setRecord(new ItemStack(nbttagcompound.getInt("Record"), 1, 0));
+        }
+    }
+
+    public void b(NBTTagCompound nbttagcompound) {
+        super.b(nbttagcompound);
+        if (this.getRecord() != null) {
+            nbttagcompound.setCompound("RecordItem", this.getRecord().save(new NBTTagCompound()));
+            nbttagcompound.setInt("Record", this.getRecord().id);
+        }
+    }
+
+    public ItemStack getRecord() {
+        return this.record;
+    }
+
+    public void setRecord(ItemStack itemstack) {
+        // CraftBukkit start - There can only be one
+        if (itemstack != null) {
+            itemstack.count = 1;
+        }
+        // CraftBukkit end
+
+        this.record = itemstack;
+        this.update();
+    }
+}
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
index 9c398156df..b6947897e2 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -1814,7 +1814,11 @@ public abstract class World implements IBlockAccess {
     public boolean w(int i, int j, int k) {
         Block block = Block.byId[this.getTypeId(i, j, k)];
 
-        return block == null ? false : (block.material.k() && block.b() ? true : (block instanceof BlockStairs ? (this.getData(i, j, k) & 4) == 4 : (block instanceof BlockStepAbstract ? (this.getData(i, j, k) & 8) == 8 : (block instanceof BlockHopper ? true : (block instanceof BlockSnow ? (this.getData(i, j, k) & 7) == 7 : false)))));
+        return this.a(block, this.getData(i, j, k));
+    }
+
+    public boolean a(Block block, int i) {
+        return block == null ? false : (block.material.k() && block.b() ? true : (block instanceof BlockStairs ? (i & 4) == 4 : (block instanceof BlockStepAbstract ? (i & 8) == 8 : (block instanceof BlockHopper ? true : (block instanceof BlockSnow ? (i & 7) == 7 : false)))));
     }
 
     public boolean c(int i, int j, int k, boolean flag) {
@@ -2403,7 +2407,7 @@ public abstract class World implements IBlockAccess {
         int l1 = i + l;
         int i2 = j + l;
         int j2 = k + l;
-        ChunkCache chunkcache = new ChunkCache(this, i1, j1, k1, l1, i2, j2);
+        ChunkCache chunkcache = new ChunkCache(this, i1, j1, k1, l1, i2, j2, 0);
         PathEntity pathentity = (new Pathfinder(chunkcache, flag, flag1, flag2, flag3)).a(entity, entity1, f);
 
         this.methodProfiler.b();
@@ -2422,7 +2426,7 @@ public abstract class World implements IBlockAccess {
         int k2 = l + k1;
         int l2 = i1 + k1;
         int i3 = j1 + k1;
-        ChunkCache chunkcache = new ChunkCache(this, l1, i2, j2, k2, l2, i3);
+        ChunkCache chunkcache = new ChunkCache(this, l1, i2, j2, k2, l2, i3, 0);
         PathEntity pathentity = (new Pathfinder(chunkcache, flag, flag1, flag2, flag3)).a(entity, i, j, k, f);
 
         this.methodProfiler.b();