From a8a4bedd2a9ef3c192ecf76db9afaf0b784ed08d Mon Sep 17 00:00:00 2001
From: md_5 <git@md-5.net>
Date: Thu, 9 Jun 2016 11:43:49 +1000
Subject: [PATCH] Update to Minecraft 1.10

---
 nms-patches/Block.patch                       |   8 +-
 nms-patches/BlockCake.patch                   |   2 +-
 nms-patches/BlockChorusFlower.patch           |   4 +-
 nms-patches/BlockCommand.patch                |   8 +-
 nms-patches/BlockEnderPortal.patch            |   2 +-
 nms-patches/BlockFlowing.patch                |   2 +-
 nms-patches/BlockJukeBox.patch                |   2 +-
 nms-patches/BlockMinecartTrackAbstract.patch  |  10 --
 nms-patches/BlockPortal.patch                 |   4 +-
 nms-patches/BlockPumpkin.patch                |  49 +++----
 nms-patches/BlockRedstoneTorch.patch          |   4 +-
 nms-patches/BlockSapling.patch                |   4 +-
 nms-patches/BlockTrapdoor.patch               |   2 +-
 nms-patches/BlockVine.patch                   |   8 +-
 nms-patches/Chunk.patch                       |  38 ++---
 nms-patches/ChunkProviderServer.patch         |   7 +-
 nms-patches/ChunkRegionLoader.patch           |  34 ++++-
 nms-patches/CommandExecute.patch              |   4 +-
 nms-patches/CommandGamemode.patch             |   6 +-
 nms-patches/CommandSpreadPlayers.patch        |   8 +-
 nms-patches/CommandTp.patch                   |   3 +-
 nms-patches/Container.patch                   |   2 +-
 nms-patches/ContainerBeacon.patch             |  10 +-
 nms-patches/ContainerChest.patch              |   4 +-
 nms-patches/ContainerDispenser.patch          |   2 +-
 nms-patches/ContainerEnchantTable.patch       |  12 +-
 nms-patches/ContainerHopper.patch             |   2 +-
 nms-patches/ContainerHorse.patch              |   6 +-
 nms-patches/ContainerMerchant.patch           |   2 +-
 nms-patches/ContainerPlayer.patch             |   2 +-
 nms-patches/ContainerWorkbench.patch          |   4 +-
 nms-patches/CraftingManager.patch             |   6 +-
 nms-patches/DedicatedServer.patch             |  57 +++++---
 nms-patches/DispenseBehaviorProjectile.patch  |   2 +-
 nms-patches/DispenserRegistry.patch           |  11 +-
 nms-patches/Enchantment.patch                 |   4 +-
 nms-patches/EnderDragonBattle.patch           |   4 +-
 nms-patches/Entity.patch                      |  66 ++++-----
 nms-patches/EntityAgeable.patch               |  14 +-
 nms-patches/EntityAreaEffectCloud.patch       |  12 +-
 nms-patches/EntityArmorStand.patch            |  10 +-
 nms-patches/EntityArrow.patch                 |   8 +-
 nms-patches/EntityBoat.patch                  |  24 ++--
 nms-patches/EntityChicken.patch               |  10 +-
 nms-patches/EntityCow.patch                   |   2 +-
 nms-patches/EntityCreature.patch              |   4 +-
 nms-patches/EntityCreeper.patch               |  14 +-
 nms-patches/EntityEgg.patch                   |   2 +-
 nms-patches/EntityEnderDragon.patch           |  16 +--
 nms-patches/EntityEnderPearl.patch            |   4 +-
 nms-patches/EntityEnderman.patch              |   4 +-
 nms-patches/EntityExperienceOrb.patch         |  14 +-
 nms-patches/EntityFallingBlock.patch          |   6 +-
 nms-patches/EntityFireball.patch              |  14 +-
 nms-patches/EntityFishingHook.patch           |  20 +--
 nms-patches/EntityGhast.patch                 |   6 +-
 nms-patches/EntityHanging.patch               | 100 +++++++------
 nms-patches/EntityHorse.patch                 |  34 ++---
 nms-patches/EntityHuman.patch                 |  70 +++++----
 nms-patches/EntityInsentient.patch            |  28 ++--
 nms-patches/EntityItem.patch                  |  14 +-
 nms-patches/EntityItemFrame.patch             |   2 +-
 nms-patches/EntityLargeFireball.patch         |   2 +-
 nms-patches/EntityLeash.patch                 |   2 +-
 nms-patches/EntityLightning.patch             |  10 +-
 nms-patches/EntityLiving.patch                |  91 ++++++------
 nms-patches/EntityMinecartAbstract.patch      |  85 +++++------
 nms-patches/EntityMonster.patch               |   2 +-
 nms-patches/EntityMushroomCow.patch           |   2 +-
 nms-patches/EntityOcelot.patch                |  10 +-
 nms-patches/EntityPig.patch                   |   6 +-
 nms-patches/EntityPlayer.patch                | 107 +++++++-------
 nms-patches/EntityProjectile.patch            |   2 +-
 nms-patches/EntitySheep.patch                 |  12 +-
 nms-patches/EntitySilverfish.patch            |   4 +-
 nms-patches/EntitySkeleton.patch              |  35 +++--
 nms-patches/EntitySlime.patch                 |   4 +-
 nms-patches/EntitySmallFireball.patch         |   4 +-
 nms-patches/EntitySnowman.patch               |   4 +-
 nms-patches/EntitySpider.patch                |   2 +-
 nms-patches/EntityTNTPrimed.patch             |  10 +-
 nms-patches/EntityThrownExpBottle.patch       |   2 +-
 nms-patches/EntityTippedArrow.patch           |  19 +--
 nms-patches/EntityTrackerEntry.patch          |  42 +++---
 nms-patches/EntityVillager.patch              |   2 +-
 nms-patches/EntityWither.patch                |  14 +-
 nms-patches/EntityWitherSkull.patch           |  12 +-
 nms-patches/EntityWolf.patch                  |  23 +--
 nms-patches/EntityZombie.patch                |  34 ++---
 nms-patches/FoodMetaData.patch                |   2 +-
 nms-patches/HandshakeListener.patch           |   4 +-
 nms-patches/InventoryCraftResult.patch        |   2 +-
 nms-patches/InventoryLargeChest.patch         |   4 +-
 nms-patches/ItemArmor.patch                   |   4 +-
 nms-patches/ItemChorusFruit.patch             |  11 +-
 nms-patches/ItemFireball.patch                |   2 +-
 nms-patches/ItemFlintAndSteel.patch           |   2 +-
 nms-patches/ItemMonsterEgg.patch              |  10 +-
 nms-patches/ItemSnowball.patch                |   4 +-
 nms-patches/ItemStack.patch                   |  16 +--
 nms-patches/LoginListener.patch               |  13 +-
 nms-patches/MethodProfiler.patch              |   4 +-
 nms-patches/MinecraftServer.patch             | 107 +++++++-------
 nms-patches/MobEffectList.patch               |   8 +-
 .../NameReferencingFileConverter.patch        |  27 ++--
 nms-patches/PacketDataSerializer.patch        |   8 +-
 nms-patches/PathfinderGoalDefendVillage.patch |   2 +-
 nms-patches/PathfinderGoalHorseTrap.patch     |   4 +-
 nms-patches/PathfinderGoalHurtByTarget.patch  |   4 +-
 nms-patches/PathfinderGoalMakeLove.patch      |   2 +-
 ...athfinderGoalNearestAttackableTarget.patch |   4 +-
 nms-patches/PathfinderGoalPanic.patch         |   2 +-
 nms-patches/PlayerConnection.patch            | 133 +++++++++---------
 nms-patches/PlayerInteractManager.patch       |  23 +--
 nms-patches/PlayerInventory.patch             |   4 +-
 nms-patches/PlayerList.patch                  |  54 +++----
 nms-patches/PortalTravelAgent.patch           |  48 ++++---
 nms-patches/RecipesBanner.patch               |   2 +-
 nms-patches/RecipesFurnace.patch              |  15 +-
 nms-patches/ScoreboardServer.patch            |   6 +-
 nms-patches/SecondaryWorldServer.patch        |   2 +-
 nms-patches/SpawnerCreature.patch             |  17 +--
 nms-patches/TileEntity.patch                  |   2 +-
 nms-patches/TileEntityBanner.patch            |   2 +-
 nms-patches/TileEntityBrewingStand.patch      |   2 +-
 nms-patches/TileEntityChest.patch             |   8 +-
 nms-patches/TileEntityDispenser.patch         |   2 +-
 nms-patches/TileEntityFurnace.patch           |  17 +--
 nms-patches/TileEntityHopper.patch            |  10 +-
 nms-patches/TileEntityPiston.patch            |   4 +-
 nms-patches/TileEntitySign.patch              |   4 +-
 nms-patches/TileEntitySkull.patch             |  13 --
 nms-patches/UserCache.patch                   |   4 +-
 nms-patches/World.patch                       |  74 +++++-----
 nms-patches/WorldData.patch                   |   8 +-
 nms-patches/WorldGenGroundBush.patch          |   2 +-
 nms-patches/WorldGenVillagePieces.patch       |  26 ++--
 nms-patches/WorldMap.patch                    |   2 +-
 nms-patches/WorldServer.patch                 |  24 ++--
 pom.xml                                       |   6 +-
 .../org/bukkit/craftbukkit/CraftServer.java   |   4 +-
 .../org/bukkit/craftbukkit/CraftSound.java    |  19 +++
 .../org/bukkit/craftbukkit/CraftWorld.java    |   2 +
 .../craftbukkit/block/CraftFlowerPot.java     |   2 +-
 .../bukkit/craftbukkit/block/CraftSkull.java  |   4 +-
 .../craftbukkit/entity/CraftArmorStand.java   |  11 --
 .../craftbukkit/entity/CraftEntity.java       |  25 +++-
 .../craftbukkit/entity/CraftPlayer.java       |   4 +-
 .../craftbukkit/entity/CraftPolarBear.java    |  27 ++++
 .../craftbukkit/entity/CraftSkeleton.java     |   5 +-
 .../craftbukkit/entity/CraftSnowman.java      |   4 +-
 .../craftbukkit/entity/CraftTippedArrow.java  |  20 +--
 .../craftbukkit/entity/CraftVillager.java     |   4 +-
 .../craftbukkit/entity/CraftZombie.java       |  17 +--
 .../craftbukkit/event/CraftEventFactory.java  |   8 +-
 .../inventory/CraftMetaBlockState.java        |   2 +-
 .../craftbukkit/potion/CraftPotionUtil.java   |  15 +-
 .../CraftBlockProjectileSource.java           |   2 +-
 src/test/java/org/bukkit/BiomeTest.java       |   4 +-
 .../java/org/bukkit/potion/PotionTest.java    |   4 +-
 .../bukkit/support/AbstractTestingBase.java   |   1 -
 161 files changed, 1176 insertions(+), 1147 deletions(-)
 delete mode 100644 nms-patches/BlockMinecartTrackAbstract.patch
 delete mode 100644 nms-patches/TileEntitySkull.patch
 create mode 100644 src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java

diff --git a/nms-patches/Block.patch b/nms-patches/Block.patch
index e0c2bb60af..3a0d23383b 100644
--- a/nms-patches/Block.patch
+++ b/nms-patches/Block.patch
@@ -9,7 +9,7 @@
      }
  
      public static int getCombinedId(IBlockData iblockdata) {
-@@ -327,7 +327,8 @@
+@@ -332,7 +332,8 @@
              int j = this.getDropCount(i, world.random);
  
              for (int k = 0; k < j; ++k) {
@@ -19,7 +19,7 @@
                      Item item = this.getDropType(iblockdata, world.random, i);
  
                      if (item != null) {
-@@ -863,7 +864,7 @@
+@@ -873,7 +874,7 @@
  
              if (hashset.contains(block16)) {
                  for (int i = 0; i < 15; ++i) {
@@ -28,7 +28,7 @@
  
                      Block.REGISTRY_ID.a(block16.fromLegacyData(i), j);
                  }
-@@ -872,7 +873,7 @@
+@@ -882,7 +883,7 @@
  
                  while (iterator2.hasNext()) {
                      IBlockData iblockdata = (IBlockData) iterator2.next();
@@ -37,7 +37,7 @@
  
                      Block.REGISTRY_ID.a(iblockdata, k);
                  }
-@@ -881,6 +882,12 @@
+@@ -891,6 +892,12 @@
  
      }
  
diff --git a/nms-patches/BlockCake.patch b/nms-patches/BlockCake.patch
index dd717e3927..a389142902 100644
--- a/nms-patches/BlockCake.patch
+++ b/nms-patches/BlockCake.patch
@@ -2,7 +2,7 @@
 +++ b/net/minecraft/server/BlockCake.java
 @@ -34,7 +34,18 @@
      private void b(World world, BlockPosition blockposition, IBlockData iblockdata, EntityHuman entityhuman) {
-         if (entityhuman.l(false)) {
+         if (entityhuman.m(false)) {
              entityhuman.b(StatisticList.J);
 -            entityhuman.getFoodData().eat(2, 0.1F);
 +            // CraftBukkit start
diff --git a/nms-patches/BlockChorusFlower.patch b/nms-patches/BlockChorusFlower.patch
index e5482d55b5..95acef097d 100644
--- a/nms-patches/BlockChorusFlower.patch
+++ b/nms-patches/BlockChorusFlower.patch
@@ -9,7 +9,7 @@
  public class BlockChorusFlower extends Block {
  
      public static final BlockStateInteger AGE = BlockStateInteger.of("age", 0, 5);
-@@ -68,8 +70,20 @@
+@@ -69,8 +71,20 @@
                      }
  
                      if (flag && a(world, blockposition1, (EnumDirection) null) && world.isEmpty(blockposition.up(2))) {
@@ -32,7 +32,7 @@
                      } else if (i < 4) {
                          j = random.nextInt(4);
                          boolean flag2 = false;
-@@ -83,18 +97,53 @@
+@@ -84,18 +98,53 @@
                              BlockPosition blockposition2 = blockposition.shift(enumdirection);
  
                              if (world.isEmpty(blockposition2) && world.isEmpty(blockposition2.down()) && a(world, blockposition2, enumdirection.opposite())) {
diff --git a/nms-patches/BlockCommand.patch b/nms-patches/BlockCommand.patch
index 08c95440f6..c791a4a053 100644
--- a/nms-patches/BlockCommand.patch
+++ b/nms-patches/BlockCommand.patch
@@ -10,8 +10,8 @@
  
      public static final BlockStateDirection a = BlockDirectional.FACING;
 @@ -30,7 +32,16 @@
-                 boolean flag1 = tileentitycommand.e();
-                 boolean flag2 = tileentitycommand.g();
+                 boolean flag1 = tileentitycommand.g();
+                 boolean flag2 = tileentitycommand.h();
  
 -                if (flag && !flag1) {
 +            // CraftBukkit start
@@ -25,8 +25,8 @@
 +
 +            if (eventRedstone.getNewCurrent() > 0 && !(eventRedstone.getOldCurrent() > 0)) { // CraftBukkit
                      tileentitycommand.a(true);
-                     if (tileentitycommand.j() != TileEntityCommand.Type.SEQUENCE && !flag2) {
-                         boolean flag3 = !tileentitycommand.k() || this.e(world, blockposition, iblockdata);
+                     if (tileentitycommand.k() != TileEntityCommand.Type.SEQUENCE && !flag2) {
+                         boolean flag3 = !tileentitycommand.l() || this.e(world, blockposition, iblockdata);
 @@ -41,7 +52,7 @@
                              this.c(world, blockposition);
                          }
diff --git a/nms-patches/BlockEnderPortal.patch b/nms-patches/BlockEnderPortal.patch
index b818c2af97..5f27102f2a 100644
--- a/nms-patches/BlockEnderPortal.patch
+++ b/nms-patches/BlockEnderPortal.patch
@@ -12,7 +12,7 @@
 @@ -37,6 +39,10 @@
  
      public void a(World world, BlockPosition blockposition, IBlockData iblockdata, Entity entity) {
-         if (!entity.isPassenger() && !entity.isVehicle() && entity.aV() && !world.isClientSide && entity.getBoundingBox().b(iblockdata.c(world, blockposition).a(blockposition))) {
+         if (!entity.isPassenger() && !entity.isVehicle() && entity.aX() && !world.isClientSide && entity.getBoundingBox().b(iblockdata.c(world, blockposition).a(blockposition))) {
 +            // CraftBukkit start - Entity in portal
 +            EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ()));
 +            world.getServer().getPluginManager().callEvent(event);
diff --git a/nms-patches/BlockFlowing.patch b/nms-patches/BlockFlowing.patch
index b2a5219794..4651b55e77 100644
--- a/nms-patches/BlockFlowing.patch
+++ b/nms-patches/BlockFlowing.patch
@@ -69,6 +69,6 @@
      private void flow(World world, BlockPosition blockposition, IBlockData iblockdata, int i) {
 -        if (this.h(world, blockposition, iblockdata)) {
 +        if (world.isLoaded(blockposition) && this.h(world, blockposition, iblockdata)) { // CraftBukkit - add isLoaded check
-             if (iblockdata.getBlock() != Blocks.AIR) {
+             if (iblockdata.getMaterial() != Material.AIR) {
                  if (this.material == Material.LAVA) {
                      this.fizz(world, blockposition);
diff --git a/nms-patches/BlockJukeBox.patch b/nms-patches/BlockJukeBox.patch
index b279f1013f..ac548cae50 100644
--- a/nms-patches/BlockJukeBox.patch
+++ b/nms-patches/BlockJukeBox.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/BlockJukeBox.java
 +++ b/net/minecraft/server/BlockJukeBox.java
-@@ -140,6 +140,11 @@
+@@ -144,6 +144,11 @@
          }
  
          public void setRecord(@Nullable ItemStack itemstack) {
diff --git a/nms-patches/BlockMinecartTrackAbstract.patch b/nms-patches/BlockMinecartTrackAbstract.patch
deleted file mode 100644
index b78169d653..0000000000
--- a/nms-patches/BlockMinecartTrackAbstract.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/net/minecraft/server/BlockMinecartTrackAbstract.java
-+++ b/net/minecraft/server/BlockMinecartTrackAbstract.java
-@@ -11,6 +11,7 @@
-     protected static final AxisAlignedBB b = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 1.0D, 0.15625D, 1.0D);
-     protected final boolean c;
- 
-+    // PAIL: We stage this entire file just to unsynthetic this method. We should rename and AT it in future
-     public static boolean b(World world, BlockPosition blockposition) {
-         return i(world.getType(blockposition));
-     }
diff --git a/nms-patches/BlockPortal.patch b/nms-patches/BlockPortal.patch
index 812e886eb5..90264c38f9 100644
--- a/nms-patches/BlockPortal.patch
+++ b/nms-patches/BlockPortal.patch
@@ -19,7 +19,7 @@
 +                Entity entity = ItemMonsterEgg.spawnCreature(world, EntityTypes.getName(EntityPigZombie.class), (double) blockposition1.getX() + 0.5D, (double) blockposition1.getY() + 1.1D, (double) blockposition1.getZ() + 0.5D, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.NETHER_PORTAL);
  
                  if (entity != null) {
-                     entity.portalCooldown = entity.aC();
+                     entity.portalCooldown = entity.aE();
 @@ -70,14 +74,16 @@
          BlockPortal.Shape blockportal_shape = new BlockPortal.Shape(world, blockposition, EnumDirection.EnumAxis.X);
  
@@ -44,7 +44,7 @@
 @@ -108,6 +114,10 @@
  
      public void a(World world, BlockPosition blockposition, IBlockData iblockdata, Entity entity) {
-         if (!entity.isPassenger() && !entity.isVehicle() && entity.aV()) {
+         if (!entity.isPassenger() && !entity.isVehicle() && entity.aX()) {
 +            // CraftBukkit start - Entity in portal
 +            EntityPortalEnterEvent event = new EntityPortalEnterEvent(entity.getBukkitEntity(), new org.bukkit.Location(world.getWorld(), blockposition.getX(), blockposition.getY(), blockposition.getZ()));
 +            world.getServer().getPluginManager().callEvent(event);
diff --git a/nms-patches/BlockPumpkin.patch b/nms-patches/BlockPumpkin.patch
index 4404b2f361..27c335cca9 100644
--- a/nms-patches/BlockPumpkin.patch
+++ b/nms-patches/BlockPumpkin.patch
@@ -13,11 +13,12 @@
  public class BlockPumpkin extends BlockFacingHorizontal {
  
      private ShapeDetector snowGolemPart;
-@@ -41,17 +47,24 @@
+@@ -40,18 +46,25 @@
+         int i;
          int j;
  
-         if ((shapedetector_shapedetectorcollection = this.getDetectorSnowGolem().a(world, blockposition)) != null) {
-+            BlockStateListPopulator blockList = new BlockStateListPopulator(world.getWorld()); // CraftBukkit - Use BlockStateListPopulator
++        BlockStateListPopulator blockList = new BlockStateListPopulator(world.getWorld()); // CraftBukkit - Use BlockStateListPopulator
+         if (shapedetector_shapedetectorcollection != null) {
              for (i = 0; i < this.getDetectorSnowGolem().b(); ++i) {
                  ShapeDetectorBlock shapedetectorblock = shapedetector_shapedetectorcollection.a(0, i, 0);
  
@@ -40,38 +41,38 @@
  
              for (j = 0; j < 120; ++j) {
                  world.addParticle(EnumParticle.SNOW_SHOVEL, (double) blockposition1.getX() + world.random.nextDouble(), (double) blockposition1.getY() + world.random.nextDouble() * 2.5D, (double) blockposition1.getZ() + world.random.nextDouble(), 0.0D, 0.0D, 0.0D, new int[0]);
-@@ -62,10 +75,16 @@
+@@ -62,12 +75,17 @@
  
                  world.update(shapedetectorblock1.getPosition(), Blocks.AIR);
              }
 +            } // CraftBukkit end
-         } else if ((shapedetector_shapedetectorcollection = this.getDetectorIronGolem().a(world, blockposition)) != null) {
-+            BlockStateListPopulator blockList = new BlockStateListPopulator(world.getWorld()); // CraftBukkit - Use BlockStateListPopulator
-             for (i = 0; i < this.getDetectorIronGolem().c(); ++i) {
-                 for (int k = 0; k < this.getDetectorIronGolem().b(); ++k) {
--                    world.setTypeAndData(shapedetector_shapedetectorcollection.a(i, k, 0).getPosition(), Blocks.AIR.getBlockData(), 2);
-+                    // CraftBukkit start
-+                    // world.setTypeAndData(shapedetectorcollection.a(i, k, 0).d(), Blocks.AIR.getBlockData(), 2);
-+                    BlockPosition pos = shapedetector_shapedetectorcollection.a(i, k, 0).getPosition();
-+                    blockList.setTypeId(pos.getX(), pos.getY(), pos.getZ(), 0);
-+                    // CraftBukkit end
+         } else {
+             shapedetector_shapedetectorcollection = this.getDetectorIronGolem().a(world, blockposition);
+             if (shapedetector_shapedetectorcollection != null) {
+                 for (i = 0; i < this.getDetectorIronGolem().c(); ++i) {
+                     for (int k = 0; k < this.getDetectorIronGolem().b(); ++k) {
+-                        world.setTypeAndData(shapedetector_shapedetectorcollection.a(i, k, 0).getPosition(), Blocks.AIR.getBlockData(), 2);
++                        // CraftBukkit start
++                        // world.setTypeAndData(shapedetector_shapedetectorcollection.a(i, k, 0).getPosition(), Blocks.AIR.getBlockData(), 2);
++                        BlockPosition pos = shapedetector_shapedetectorcollection.a(i, k, 0).getPosition();
++                        blockList.setTypeId(pos.getX(), pos.getY(), pos.getZ(), 0);
++                        // CraftBukkit end
+                     }
                  }
-             }
  
-@@ -74,7 +93,10 @@
+@@ -76,7 +94,9 @@
  
-             entityirongolem.setPlayerCreated(true);
-             entityirongolem.setPositionRotation((double) blockposition2.getX() + 0.5D, (double) blockposition2.getY() + 0.05D, (double) blockposition2.getZ() + 0.5D, 0.0F, 0.0F);
--            world.addEntity(entityirongolem);
-+
+                 entityirongolem.setPlayerCreated(true);
+                 entityirongolem.setPositionRotation((double) blockposition2.getX() + 0.5D, (double) blockposition2.getY() + 0.05D, (double) blockposition2.getZ() + 0.5D, 0.0F, 0.0F);
+-                world.addEntity(entityirongolem);
 +            // CraftBukkit start
 +            if (world.addEntity(entityirongolem, SpawnReason.BUILD_IRONGOLEM)) {
 +                blockList.updateList();
  
-             for (j = 0; j < 120; ++j) {
-                 world.addParticle(EnumParticle.SNOWBALL, (double) blockposition2.getX() + world.random.nextDouble(), (double) blockposition2.getY() + world.random.nextDouble() * 3.9D, (double) blockposition2.getZ() + world.random.nextDouble(), 0.0D, 0.0D, 0.0D, new int[0]);
-@@ -87,6 +109,7 @@
-                     world.update(shapedetectorblock2.getPosition(), Blocks.AIR);
+                 for (j = 0; j < 120; ++j) {
+                     world.addParticle(EnumParticle.SNOWBALL, (double) blockposition2.getX() + world.random.nextDouble(), (double) blockposition2.getY() + world.random.nextDouble() * 3.9D, (double) blockposition2.getZ() + world.random.nextDouble(), 0.0D, 0.0D, 0.0D, new int[0]);
+@@ -90,6 +110,7 @@
+                     }
                  }
              }
 +            } // CraftBukkit end
diff --git a/nms-patches/BlockRedstoneTorch.patch b/nms-patches/BlockRedstoneTorch.patch
index 4f65a1abff..f2dd63cedb 100644
--- a/nms-patches/BlockRedstoneTorch.patch
+++ b/nms-patches/BlockRedstoneTorch.patch
@@ -8,7 +8,7 @@
 +
  public class BlockRedstoneTorch extends BlockTorch {
  
-     private static Map<World, List<BlockRedstoneTorch.RedstoneUpdateInfo>> g = Maps.newHashMap();
+     private static final Map<World, List<BlockRedstoneTorch.RedstoneUpdateInfo>> g = Maps.newHashMap();
 @@ -14,7 +16,7 @@
  
      private boolean a(World world, BlockPosition blockposition, boolean flag) {
@@ -43,7 +43,7 @@
 +                // CraftBukkit end
                  world.setTypeAndData(blockposition, Blocks.UNLIT_REDSTONE_TORCH.getBlockData().set(BlockRedstoneTorch.FACING, iblockdata.get(BlockRedstoneTorch.FACING)), 3);
                  if (this.a(world, blockposition, true)) {
-                     world.a((EntityHuman) null, blockposition, SoundEffects.eG, SoundCategory.BLOCKS, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F);
+                     world.a((EntityHuman) null, blockposition, SoundEffects.eR, SoundCategory.BLOCKS, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F);
 @@ -115,6 +134,15 @@
                  }
              }
diff --git a/nms-patches/BlockSapling.patch b/nms-patches/BlockSapling.patch
index 16b6d0cd2b..42df791c87 100644
--- a/nms-patches/BlockSapling.patch
+++ b/nms-patches/BlockSapling.patch
@@ -82,8 +82,8 @@
                          break label66;
 @@ -63,11 +107,13 @@
              if (!flag) {
-                 j = 0;
                  i = 0;
+                 j = 0;
 +                treeType = TreeType.REDWOOD; // CraftBukkit
                  object = new WorldGenTaiga2(true);
              }
@@ -104,8 +104,8 @@
                          break label78;
 @@ -89,11 +136,13 @@
              if (!flag) {
-                 j = 0;
                  i = 0;
+                 j = 0;
 +                treeType = TreeType.SMALL_JUNGLE; // CraftBukkit
                  object = new WorldGenTrees(true, 4 + random.nextInt(7), iblockdata1, iblockdata2, false);
              }
diff --git a/nms-patches/BlockTrapdoor.patch b/nms-patches/BlockTrapdoor.patch
index 58cfb7609d..310070951d 100644
--- a/nms-patches/BlockTrapdoor.patch
+++ b/nms-patches/BlockTrapdoor.patch
@@ -8,7 +8,7 @@
  
  public class BlockTrapdoor extends Block {
  
-@@ -94,6 +95,19 @@
+@@ -91,6 +92,19 @@
              boolean flag = world.isBlockIndirectlyPowered(blockposition);
  
              if (flag || block.getBlockData().m()) {
diff --git a/nms-patches/BlockVine.patch b/nms-patches/BlockVine.patch
index c3b2a19d5e..03b7104c18 100644
--- a/nms-patches/BlockVine.patch
+++ b/nms-patches/BlockVine.patch
@@ -32,20 +32,20 @@
 +                                org.bukkit.block.Block source = world.getWorld().getBlockAt(blockposition.getX(), blockposition.getY(), blockposition.getZ());
 +                                org.bukkit.block.Block bukkitBlock = world.getWorld().getBlockAt(blockposition2.getX(), blockposition2.getY(), blockposition2.getZ());
 +
-                                 if (flag1 && this.x(world.getType(blockposition3))) {
+                                 if (flag2 && this.x(world.getType(blockposition3))) {
 -                                    world.setTypeAndData(blockposition2, this.getBlockData().set(getDirection(enumdirection2), Boolean.valueOf(true)), 2);
 +                                    // world.setTypeAndData(blockposition2, this.getBlockData().set(getDirection(enumdirection2), Boolean.valueOf(true)), 2);
 +                                    CraftEventFactory.handleBlockSpreadEvent(bukkitBlock, source, this, toLegacyData(this.getBlockData().set(getDirection(enumdirection2), Boolean.valueOf(true))));
-                                 } else if (flag2 && this.x(world.getType(blockposition4))) {
+                                 } else if (flag3 && this.x(world.getType(blockposition4))) {
 -                                    world.setTypeAndData(blockposition2, this.getBlockData().set(getDirection(enumdirection3), Boolean.valueOf(true)), 2);
 +                                    // world.setTypeAndData(blockposition2, this.getBlockData().set(getDirection(enumdirection3), Boolean.valueOf(true)), 2);
 +                                    CraftEventFactory.handleBlockSpreadEvent(bukkitBlock, source, this, toLegacyData(this.getBlockData().set(getDirection(enumdirection3), Boolean.valueOf(true))));
-                                 } else if (flag1 && world.isEmpty(blockposition3) && this.x(world.getType(blockposition.shift(enumdirection2)))) {
+                                 } else if (flag2 && world.isEmpty(blockposition3) && this.x(world.getType(blockposition.shift(enumdirection2)))) {
 -                                    world.setTypeAndData(blockposition3, this.getBlockData().set(getDirection(enumdirection.opposite()), Boolean.valueOf(true)), 2);
 +                                    // world.setTypeAndData(blockposition3, this.getBlockData().set(getDirection(enumdirection.opposite()), Boolean.valueOf(true)), 2);
 +                                    bukkitBlock = world.getWorld().getBlockAt(blockposition3.getX(), blockposition3.getY(), blockposition3.getZ());
 +                                    CraftEventFactory.handleBlockSpreadEvent(bukkitBlock, source, this, toLegacyData(this.getBlockData().set(getDirection(enumdirection.opposite()), Boolean.valueOf(true))));
-                                 } else if (flag2 && world.isEmpty(blockposition4) && this.x(world.getType(blockposition.shift(enumdirection3)))) {
+                                 } else if (flag3 && world.isEmpty(blockposition4) && this.x(world.getType(blockposition.shift(enumdirection3)))) {
 -                                    world.setTypeAndData(blockposition4, this.getBlockData().set(getDirection(enumdirection.opposite()), Boolean.valueOf(true)), 2);
 +                                    // world.setTypeAndData(blockposition4, this.getBlockData().set(getDirection(enumdirection.opposite()), Boolean.valueOf(true)), 2);
 +                                    bukkitBlock = world.getWorld().getBlockAt(blockposition4.getX(), blockposition4.getY(), blockposition4.getZ());
diff --git a/nms-patches/Chunk.patch b/nms-patches/Chunk.patch
index 83e96077ca..3c96375521 100644
--- a/nms-patches/Chunk.patch
+++ b/nms-patches/Chunk.patch
@@ -59,8 +59,8 @@
 +
      public Chunk(World world, ChunkSnapshot chunksnapshot, int i, int j) {
          this(world, i, j);
-         short short0 = 256;
-@@ -466,7 +503,8 @@
+         boolean flag = true;
+@@ -467,7 +504,8 @@
                      }
                  }
  
@@ -70,20 +70,7 @@
                      block.onPlace(this.world, blockposition, iblockdata);
                  }
  
-@@ -547,7 +585,11 @@
-         int j = MathHelper.floor(entity.locZ / 16.0D);
- 
-         if (i != this.locX || j != this.locZ) {
--            Chunk.e.warn("Wrong location! (" + i + ", " + j + ") should be (" + this.locX + ", " + this.locZ + "), " + entity, new Object[] { entity});
-+            // CraftBukkit start
-+            Bukkit.getLogger().warning("Wrong location for " + entity + " in world '" + world.getWorld().getName() + "'!");
-+            // Chunk.e.warn("Wrong location! (" + i + ", " + j + ") should be (" + this.locX + ", " + this.locZ + "), " + entity, new Object[] { entity});
-+            Bukkit.getLogger().warning("Entity is at " + entity.locX + "," + entity.locZ + " (chunk " + i + "," + j + ") but was stored in chunk " + this.locX + "," + this.locZ);
-+            // CraftBukkit end
-             entity.die();
-         }
- 
-@@ -602,7 +644,15 @@
+@@ -604,7 +642,15 @@
  
      @Nullable
      public TileEntity a(BlockPosition blockposition, Chunk.EnumTileEntityState chunk_enumtileentitystate) {
@@ -100,7 +87,7 @@
  
          if (tileentity == null) {
              if (chunk_enumtileentitystate == Chunk.EnumTileEntityState.IMMEDIATE) {
-@@ -637,6 +687,13 @@
+@@ -639,6 +685,13 @@
  
              tileentity.z();
              this.tileEntities.put(blockposition, tileentity);
@@ -114,17 +101,18 @@
          }
      }
  
-@@ -680,7 +737,21 @@
-         }
+@@ -681,9 +734,21 @@
+         int i = aentityslice.length;
  
-         for (int i = 0; i < this.entitySlices.length; ++i) {
--            this.world.c((Collection) this.entitySlices[i]);
+         for (int j = 0; j < i; ++j) {
+-            EntitySlice entityslice = aentityslice[j];
 +            // CraftBukkit start
-+            List<Entity> newList = Lists.newArrayList(this.entitySlices[i]);
++            List<Entity> newList = Lists.newArrayList(aentityslice[j]);
 +            java.util.Iterator<Entity> iter = newList.iterator();
 +            while (iter.hasNext()) {
 +                Entity entity = iter.next();
-+
+ 
+-            this.world.c((Collection) entityslice);
 +                // Do not pass along players, as doing so can get them stuck outside of time.
 +                // (which for example disables inventory icon updates and prevents block breaking)
 +                if (entity instanceof EntityPlayer) {
@@ -137,7 +125,7 @@
          }
  
      }
-@@ -738,8 +809,8 @@
+@@ -745,8 +810,8 @@
              while (iterator.hasNext()) {
                  Entity entity = (Entity) iterator.next();
  
@@ -148,7 +136,7 @@
                  }
              }
          }
-@@ -802,6 +873,29 @@
+@@ -809,6 +874,29 @@
          } else {
              this.o();
              chunkgenerator.recreateStructures(this.locX, this.locZ);
diff --git a/nms-patches/ChunkProviderServer.patch b/nms-patches/ChunkProviderServer.patch
index c3349bd155..b5a6d413c3 100644
--- a/nms-patches/ChunkProviderServer.patch
+++ b/nms-patches/ChunkProviderServer.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/ChunkProviderServer.java
 +++ b/net/minecraft/server/ChunkProviderServer.java
-@@ -14,10 +14,16 @@
+@@ -14,6 +14,12 @@
  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  
@@ -13,11 +13,6 @@
  public class ChunkProviderServer implements IChunkProvider {
  
      private static final Logger a = LogManager.getLogger();
--    private final Set<Long> unloadQueue = Sets.newHashSet();
-+    public final Set<Long> unloadQueue = Sets.newHashSet(); // PAIL: private -> public
-     public final ChunkGenerator chunkGenerator;
-     private final IChunkLoader chunkLoader;
-     public final Long2ObjectMap<Chunk> chunks = new Long2ObjectOpenHashMap(8192);
 @@ -69,19 +75,74 @@
          Chunk chunk = this.getLoadedChunkAt(i, j);
  
diff --git a/nms-patches/ChunkRegionLoader.patch b/nms-patches/ChunkRegionLoader.patch
index 309445cdc7..bb45e8250e 100644
--- a/nms-patches/ChunkRegionLoader.patch
+++ b/nms-patches/ChunkRegionLoader.patch
@@ -44,10 +44,10 @@
 -    protected Chunk a(World world, int i, int j, NBTTagCompound nbttagcompound) {
 +    protected Object[] a(World world, int i, int j, NBTTagCompound nbttagcompound) { // CraftBukkit - return Chunk -> Object[]
          if (!nbttagcompound.hasKeyOfType("Level", 10)) {
-             ChunkRegionLoader.a.error("Chunk file at " + i + "," + j + " is missing level data, skipping");
+             ChunkRegionLoader.a.error("Chunk file at {},{} is missing level data, skipping", new Object[] { Integer.valueOf(i), Integer.valueOf(j)});
              return null;
 @@ -64,10 +92,28 @@
-                     ChunkRegionLoader.a.error("Chunk file at " + i + "," + j + " is in the wrong location; relocating. (Expected " + i + ", " + j + ", got " + chunk.locX + ", " + chunk.locZ + ")");
+                     ChunkRegionLoader.a.error("Chunk file at {},{} is in the wrong location; relocating. (Expected {}, {}, got {}, {})", new Object[] { Integer.valueOf(i), Integer.valueOf(j), Integer.valueOf(i), Integer.valueOf(j), Integer.valueOf(chunk.locX), Integer.valueOf(chunk.locZ)});
                      nbttagcompound1.setInt("xPos", i);
                      nbttagcompound1.setInt("zPos", j);
 +
@@ -76,7 +76,7 @@
              }
          }
      }
-@@ -296,6 +342,13 @@
+@@ -326,6 +372,13 @@
              chunk.a(nbttagcompound.getByteArray("Biomes"));
          }
  
@@ -90,7 +90,7 @@
          NBTTagList nbttaglist1 = nbttagcompound.getList("Entities", 10);
  
          if (nbttaglist1 != null) {
-@@ -339,7 +392,7 @@
+@@ -369,7 +422,7 @@
              }
          }
  
@@ -99,7 +99,29 @@
      }
  
      @Nullable
-@@ -403,8 +456,14 @@
+@@ -397,14 +450,20 @@
+     }
+ 
+     @Nullable
++    // CraftBukkit start
+     public static Entity a(NBTTagCompound nbttagcompound, World world, double d0, double d1, double d2, boolean flag) {
++        return spawnEntity(nbttagcompound, world, d0, d1, d2, flag, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.DEFAULT);
++    }
++
++    public static Entity spawnEntity(NBTTagCompound nbttagcompound, World world, double d0, double d1, double d2, boolean flag, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason spawnReason) {
++        // CraftBukkit end
+         Entity entity = a(nbttagcompound, world);
+ 
+         if (entity == null) {
+             return null;
+         } else {
+             entity.setPositionRotation(d0, d1, d2, entity.yaw, entity.pitch);
+-            if (flag && !world.addEntity(entity)) {
++            if (flag && !world.addEntity(entity, spawnReason)) { // CraftBukkit
+                 return null;
+             } else {
+                 if (nbttagcompound.hasKeyOfType("Passengers", 9)) {
+@@ -433,8 +492,14 @@
          }
      }
  
@@ -112,6 +134,6 @@
 +    public static void a(Entity entity, World world, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason reason) {
 +        if (world.addEntity(entity, reason) && entity.isVehicle()) {
 +            // CraftBukkit end
-             Iterator iterator = entity.bv().iterator();
+             Iterator iterator = entity.bx().iterator();
  
              while (iterator.hasNext()) {
diff --git a/nms-patches/CommandExecute.patch b/nms-patches/CommandExecute.patch
index 6b7a5aab0d..8651d1a239 100644
--- a/nms-patches/CommandExecute.patch
+++ b/nms-patches/CommandExecute.patch
@@ -11,7 +11,7 @@
  
  public class CommandExecute extends CommandAbstract {
  
-@@ -50,7 +54,10 @@
+@@ -55,7 +59,10 @@
              }
  
              String s = a(astring, b0);
@@ -23,7 +23,7 @@
                  public String getName() {
                      return entity.getName();
                  }
-@@ -95,25 +102,57 @@
+@@ -100,25 +107,57 @@
                      return entity.h();
                  }
              };
diff --git a/nms-patches/CommandGamemode.patch b/nms-patches/CommandGamemode.patch
index 4c838cf5a2..b91fed85c8 100644
--- a/nms-patches/CommandGamemode.patch
+++ b/nms-patches/CommandGamemode.patch
@@ -3,14 +3,14 @@
 @@ -28,6 +28,12 @@
              EntityPlayer entityplayer = astring.length >= 2 ? a(minecraftserver, icommandlistener, astring[1]) : a(icommandlistener);
  
-             entityplayer.a(worldsettings_enumgamemode);
+             entityplayer.a(enumgamemode);
 +            // CraftBukkit start - handle event cancelling the change
-+            if (entityplayer.playerInteractManager.getGameMode() != worldsettings_enumgamemode) {
++            if (entityplayer.playerInteractManager.getGameMode() != enumgamemode) {
 +                icommandlistener.sendMessage(new ChatComponentText("Failed to set the gamemode of '" + entityplayer.getName() + "'"));
 +                return;
 +            }
 +            // CraftBukkit end
-             ChatMessage chatmessage = new ChatMessage("gameMode." + worldsettings_enumgamemode.b(), new Object[0]);
+             ChatMessage chatmessage = new ChatMessage("gameMode." + enumgamemode.b(), new Object[0]);
  
              if (icommandlistener.getWorld().getGameRules().getBoolean("sendCommandFeedback")) {
 @@ -50,10 +56,17 @@
diff --git a/nms-patches/CommandSpreadPlayers.patch b/nms-patches/CommandSpreadPlayers.patch
index eb6722068f..33279985d3 100644
--- a/nms-patches/CommandSpreadPlayers.patch
+++ b/nms-patches/CommandSpreadPlayers.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/CommandSpreadPlayers.java
 +++ b/net/minecraft/server/CommandSpreadPlayers.java
-@@ -236,9 +236,16 @@
+@@ -240,9 +240,16 @@
      }
  
      public List<String> tabComplete(MinecraftServer minecraftserver, ICommandListener icommandlistener, String[] astring, @Nullable BlockPosition blockposition) {
@@ -18,7 +18,7 @@
      static class Location2D {
  
          double a;
-@@ -305,7 +312,7 @@
+@@ -309,7 +316,7 @@
                  }
  
                  blockposition = blockposition.down();
@@ -27,7 +27,7 @@
  
              return blockposition.getY() + 1;
          }
-@@ -321,7 +328,7 @@
+@@ -325,7 +332,7 @@
                  }
  
                  blockposition = blockposition.down();
@@ -36,7 +36,7 @@
              } while (material == Material.AIR);
  
              return !material.isLiquid() && material != Material.FIRE;
-@@ -331,5 +338,12 @@
+@@ -335,5 +342,12 @@
              this.a = MathHelper.a(random, d0, d2);
              this.b = MathHelper.a(random, d1, d3);
          }
diff --git a/nms-patches/CommandTp.patch b/nms-patches/CommandTp.patch
index e1663bf75c..47791cb013 100644
--- a/nms-patches/CommandTp.patch
+++ b/nms-patches/CommandTp.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/CommandTp.java
 +++ b/net/minecraft/server/CommandTp.java
-@@ -98,27 +98,28 @@
+@@ -53,17 +53,11 @@
              } else {
                  Entity entity = b(minecraftserver, icommandlistener, astring[astring.length - 1]);
  
@@ -22,6 +22,7 @@
                  }
              }
          }
+@@ -126,10 +120,17 @@
      }
  
      public List<String> tabComplete(MinecraftServer minecraftserver, ICommandListener icommandlistener, String[] astring, @Nullable BlockPosition blockposition) {
diff --git a/nms-patches/Container.patch b/nms-patches/Container.patch
index 9e43c7361c..615268753a 100644
--- a/nms-patches/Container.patch
+++ b/nms-patches/Container.patch
@@ -20,7 +20,7 @@
      public List<ItemStack> b = Lists.newArrayList();
 @@ -19,12 +30,24 @@
      protected List<ICrafting> listeners = Lists.newArrayList();
-     private Set<EntityHuman> i = Sets.newHashSet();
+     private final Set<EntityHuman> i = Sets.newHashSet();
  
 +    // CraftBukkit start
 +    public boolean checkReachable = true;
diff --git a/nms-patches/ContainerBeacon.patch b/nms-patches/ContainerBeacon.patch
index fd200e7100..0e544bc0e5 100644
--- a/nms-patches/ContainerBeacon.patch
+++ b/nms-patches/ContainerBeacon.patch
@@ -8,7 +8,7 @@
  
  public class ContainerBeacon extends Container {
  
-     private IInventory beacon;
+     private final IInventory beacon;
      private final ContainerBeacon.SlotBeacon f;
 +    // CraftBukkit start
 +    private CraftInventoryView bukkitEntity = null;
@@ -18,9 +18,9 @@
      public ContainerBeacon(IInventory iinventory, IInventory iinventory1) {
 +        player = (PlayerInventory) iinventory; // CraftBukkit - TODO: check this
          this.beacon = iinventory1;
-         this.a((Slot) (this.f = new ContainerBeacon.SlotBeacon(iinventory1, 0, 136, 110)));
-         byte b0 = 36;
-@@ -49,6 +55,7 @@
+         this.f = new ContainerBeacon.SlotBeacon(iinventory1, 0, 136, 110);
+         this.a((Slot) this.f);
+@@ -50,6 +56,7 @@
      }
  
      public boolean a(EntityHuman entityhuman) {
@@ -28,7 +28,7 @@
          return this.beacon.a(entityhuman);
      }
  
-@@ -113,4 +120,17 @@
+@@ -114,4 +121,17 @@
              return 1;
          }
      }
diff --git a/nms-patches/ContainerChest.patch b/nms-patches/ContainerChest.patch
index 0a166c6a42..05e02ff571 100644
--- a/nms-patches/ContainerChest.patch
+++ b/nms-patches/ContainerChest.patch
@@ -11,8 +11,8 @@
  
  public class ContainerChest extends Container {
  
-     private IInventory container;
-     private int f;
+     private final IInventory container;
+     private final int f;
 +    // CraftBukkit start
 +    private CraftInventoryView bukkitEntity = null;
 +    private PlayerInventory player;
diff --git a/nms-patches/ContainerDispenser.patch b/nms-patches/ContainerDispenser.patch
index d1a63cd639..9435edcb5c 100644
--- a/nms-patches/ContainerDispenser.patch
+++ b/nms-patches/ContainerDispenser.patch
@@ -11,7 +11,7 @@
  
  public class ContainerDispenser extends Container {
  
-     public IInventory items;
+     public final IInventory items;
 +    // CraftBukkit start
 +    private CraftInventoryView bukkitEntity = null;
 +    private PlayerInventory player;
diff --git a/nms-patches/ContainerEnchantTable.patch b/nms-patches/ContainerEnchantTable.patch
index 37fd4ffa85..e7e871e98d 100644
--- a/nms-patches/ContainerEnchantTable.patch
+++ b/nms-patches/ContainerEnchantTable.patch
@@ -34,8 +34,8 @@
 +            return new org.bukkit.Location(world.getWorld(), position.getX(), position.getY(), position.getZ());
 +        }
      };
-     private World world;
-     private BlockPosition position;
+     public World world;
+     private final BlockPosition position;
 @@ -23,6 +41,10 @@
      public int[] costs = new int[3];
      public int[] h = new int[] { -1, -1, -1};
@@ -150,19 +150,19 @@
                      if (!entityhuman.abilities.canInstantlyBuild) {
                          itemstack1.count -= j;
                          if (itemstack1.count <= 0) {
-@@ -227,6 +297,11 @@
+@@ -228,6 +298,11 @@
  
      public void b(EntityHuman entityhuman) {
          super.b(entityhuman);
 +        // CraftBukkit Start - If an enchantable was opened from a null location, set the world to the player's world, preventing a crash
-+        if(this.world == null) {
++        if (this.world == null) {
 +            this.world = entityhuman.getWorld();
 +        }
 +        // CraftBukkit end
          if (!this.world.isClientSide) {
              for (int i = 0; i < this.enchantSlots.getSize(); ++i) {
                  ItemStack itemstack = this.enchantSlots.splitWithoutUpdate(i);
-@@ -240,6 +315,7 @@
+@@ -241,6 +316,7 @@
      }
  
      public boolean a(EntityHuman entityhuman) {
@@ -170,7 +170,7 @@
          return this.world.getType(this.position).getBlock() != Blocks.ENCHANTING_TABLE ? false : entityhuman.e((double) this.position.getX() + 0.5D, (double) this.position.getY() + 0.5D, (double) this.position.getZ() + 0.5D) <= 64.0D;
      }
  
-@@ -293,4 +369,17 @@
+@@ -294,4 +370,17 @@
  
          return itemstack;
      }
diff --git a/nms-patches/ContainerHopper.patch b/nms-patches/ContainerHopper.patch
index 3f5914a7c1..96f6b28aa4 100644
--- a/nms-patches/ContainerHopper.patch
+++ b/nms-patches/ContainerHopper.patch
@@ -33,7 +33,7 @@
          this.hopper = iinventory;
 +        this.player = playerinventory; // CraftBukkit - save player
          iinventory.startOpen(entityhuman);
-         byte b0 = 51;
+         boolean flag = true;
  
 @@ -30,6 +51,7 @@
      }
diff --git a/nms-patches/ContainerHorse.patch b/nms-patches/ContainerHorse.patch
index 0a80f1414f..c15f5de3c3 100644
--- a/nms-patches/ContainerHorse.patch
+++ b/nms-patches/ContainerHorse.patch
@@ -12,8 +12,8 @@
  
  public class ContainerHorse extends Container {
  
-     private IInventory a;
-     private EntityHorse f;
+     private final IInventory a;
+     private final EntityHorse f;
  
 +    // CraftBukkit start
 +    org.bukkit.craftbukkit.inventory.CraftInventoryView bukkitEntity;
@@ -34,4 +34,4 @@
 +        // CraftBukkit end
          this.a = iinventory1;
          this.f = entityhorse;
-         byte b0 = 3;
+         boolean flag = true;
diff --git a/nms-patches/ContainerMerchant.patch b/nms-patches/ContainerMerchant.patch
index 92b1aede66..7cd43434dc 100644
--- a/nms-patches/ContainerMerchant.patch
+++ b/nms-patches/ContainerMerchant.patch
@@ -9,7 +9,7 @@
  public class ContainerMerchant extends Container {
  
 @@ -8,6 +9,19 @@
-     private InventoryMerchant f;
+     private final InventoryMerchant f;
      private final World g;
  
 +    // CraftBukkit start
diff --git a/nms-patches/ContainerPlayer.patch b/nms-patches/ContainerPlayer.patch
index f868d983f3..a79220cb9f 100644
--- a/nms-patches/ContainerPlayer.patch
+++ b/nms-patches/ContainerPlayer.patch
@@ -66,7 +66,7 @@
      }
  
      public void b(EntityHuman entityhuman) {
-@@ -146,4 +171,17 @@
+@@ -150,4 +175,17 @@
      public boolean a(ItemStack itemstack, Slot slot) {
          return slot.inventory != this.resultInventory && super.a(itemstack, slot);
      }
diff --git a/nms-patches/ContainerWorkbench.patch b/nms-patches/ContainerWorkbench.patch
index 9680722d0a..d2b2757cc4 100644
--- a/nms-patches/ContainerWorkbench.patch
+++ b/nms-patches/ContainerWorkbench.patch
@@ -15,8 +15,8 @@
 -    public IInventory resultInventory = new InventoryCraftResult();
 +    public InventoryCrafting craftInventory; // CraftBukkit - move initialization into constructor
 +    public IInventory resultInventory; // CraftBukkit - move initialization into constructor
-     private World g;
-     private BlockPosition h;
+     private final World g;
+     private final BlockPosition h;
 +    // CraftBukkit start
 +    private CraftInventoryView bukkitEntity = null;
 +    private PlayerInventory player;
diff --git a/nms-patches/CraftingManager.patch b/nms-patches/CraftingManager.patch
index 58ea8f3745..d37e1c5cf8 100644
--- a/nms-patches/CraftingManager.patch
+++ b/nms-patches/CraftingManager.patch
@@ -17,10 +17,10 @@
  
      public static CraftingManager getInstance() {
          return CraftingManager.a;
-@@ -177,7 +183,12 @@
-         this.registerShapedRecipe(new ItemStack(Blocks.HOPPER), new Object[] { "I I", "ICI", " I ", Character.valueOf('I'), Items.IRON_INGOT, Character.valueOf('C'), Blocks.CHEST});
+@@ -178,7 +184,12 @@
          this.registerShapedRecipe(new ItemStack(Items.ARMOR_STAND, 1), new Object[] { "///", " / ", "/_/", Character.valueOf('/'), Items.STICK, Character.valueOf('_'), new ItemStack(Blocks.STONE_SLAB, 1, BlockDoubleStepAbstract.EnumStoneSlabVariant.STONE.a())});
          this.registerShapedRecipe(new ItemStack(Blocks.END_ROD, 4), new Object[] { "/", "#", Character.valueOf('/'), Items.BLAZE_ROD, Character.valueOf('#'), Items.CHORUS_FRUIT_POPPED});
+         this.registerShapedRecipe(new ItemStack(Blocks.di, 1), new Object[] { "XXX", "XXX", "XXX", Character.valueOf('X'), new ItemStack(Items.DYE, 1, EnumColor.WHITE.getInvColorIndex())});
 -        Collections.sort(this.recipes, new Comparator() {
 +        sort();
 +    }
@@ -31,7 +31,7 @@
              public int a(IRecipe irecipe, IRecipe irecipe1) {
                  return irecipe instanceof ShapelessRecipes && irecipe1 instanceof ShapedRecipes ? 1 : (irecipe1 instanceof ShapelessRecipes && irecipe instanceof ShapedRecipes ? -1 : (irecipe1.a() < irecipe.a() ? -1 : (irecipe1.a() > irecipe.a() ? 1 : 0)));
              }
-@@ -285,13 +296,18 @@
+@@ -290,13 +301,18 @@
  
          do {
              if (!iterator.hasNext()) {
diff --git a/nms-patches/DedicatedServer.patch b/nms-patches/DedicatedServer.patch
index 47e205ccde..98760e5474 100644
--- a/nms-patches/DedicatedServer.patch
+++ b/nms-patches/DedicatedServer.patch
@@ -12,7 +12,7 @@
  import java.net.InetAddress;
  import java.net.Proxy;
  import java.util.Collections;
-@@ -17,10 +16,20 @@
+@@ -18,11 +17,21 @@
  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  
@@ -29,14 +29,15 @@
  public class DedicatedServer extends MinecraftServer implements IMinecraftServer {
  
      private static final Logger LOGGER = LogManager.getLogger();
+     private static final Pattern l = Pattern.compile("^[a-fA-F0-9]{40}$");
 -    private final List<ServerCommand> serverCommandQueue = Collections.synchronizedList(Lists.newArrayList());
 +    private final List<ServerCommand> serverCommandQueue = Collections.synchronizedList(Lists.<ServerCommand>newArrayList()); // CraftBukkit - fix decompile error
-     private RemoteStatusListener m;
+     private RemoteStatusListener n;
      public final RemoteControlCommandListener remoteControlCommandListener = new RemoteControlCommandListener(this);
-     private RemoteControlListener o;
-@@ -30,8 +39,10 @@
-     private WorldSettings.EnumGamemode s;
-     private boolean t;
+     private RemoteControlListener p;
+@@ -32,8 +41,10 @@
+     private EnumGamemode t;
+     private boolean u;
  
 -    public DedicatedServer(File file, DataConverterManager dataconvertermanager, YggdrasilAuthenticationService yggdrasilauthenticationservice, MinecraftSessionService minecraftsessionservice, GameProfileRepository gameprofilerepository, UserCache usercache) {
 -        super(file, Proxy.NO_PROXY, dataconvertermanager, yggdrasilauthenticationservice, minecraftsessionservice, gameprofilerepository, usercache);
@@ -47,8 +48,12 @@
          Thread thread = new Thread("Server Infinisleeper") {
              {
                  this.setDaemon(true);
-@@ -53,13 +64,27 @@
-     protected boolean init() throws IOException {
+@@ -52,16 +63,30 @@
+         };
+     }
+ 
+-    protected boolean init() throws IOException {
++    public boolean init() throws IOException {
          Thread thread = new Thread("Server console handler") {
              public void run() {
 -                BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(System.in));
@@ -78,7 +83,7 @@
                      }
                  } catch (IOException ioexception) {
                      DedicatedServer.LOGGER.error("Exception handling console input", ioexception);
-@@ -68,6 +93,27 @@
+@@ -70,6 +95,27 @@
              }
          };
  
@@ -105,17 +110,17 @@
 +
          thread.setDaemon(true);
          thread.start();
-         DedicatedServer.LOGGER.info("Starting minecraft server version 1.9.4");
-@@ -76,7 +122,7 @@
+         DedicatedServer.LOGGER.info("Starting minecraft server version 1.10");
+@@ -78,7 +124,7 @@
          }
  
          DedicatedServer.LOGGER.info("Loading properties");
 -        this.propertyManager = new PropertyManager(new File("server.properties"));
 +        this.propertyManager = new PropertyManager(this.options); // CraftBukkit - CLI argument support
-         this.q = new EULA(new File("eula.txt"));
-         if (!this.q.a()) {
+         this.r = new EULA(new File("eula.txt"));
+         if (!this.r.a()) {
              DedicatedServer.LOGGER.info("You need to agree to the EULA in order to run the server. Go to eula.txt for more info.");
-@@ -132,6 +178,8 @@
+@@ -134,6 +180,8 @@
                  return false;
              }
  
@@ -124,7 +129,7 @@
              if (!this.getOnlineMode()) {
                  DedicatedServer.LOGGER.warn("**** SERVER IS RUNNING IN OFFLINE/INSECURE MODE!");
                  DedicatedServer.LOGGER.warn("The server will make no attempt to authenticate usernames. Beware.");
-@@ -146,7 +194,7 @@
+@@ -148,7 +196,7 @@
              if (!NameReferencingFileConverter.a(this.propertyManager)) {
                  return false;
              } else {
@@ -133,10 +138,10 @@
                  long j = System.nanoTime();
  
                  if (this.S() == null) {
-@@ -204,7 +252,18 @@
+@@ -206,7 +254,18 @@
                      DedicatedServer.LOGGER.info("Starting remote control listener");
-                     this.o = new RemoteControlListener(this);
-                     this.o.a();
+                     this.p = new RemoteControlListener(this);
+                     this.p.a();
 +                    this.remoteConsole = new org.bukkit.craftbukkit.command.CraftRemoteConsoleCommandSender(this.remoteControlCommandListener); // CraftBukkit
 +                }
 +
@@ -152,7 +157,21 @@
  
                  if (this.aP() > 0L) {
                      Thread thread1 = new Thread(new ThreadWatchdog(this));
-@@ -297,7 +356,7 @@
+@@ -266,7 +325,7 @@
+         return this.propertyManager.getBoolean("hardcore", false);
+     }
+ 
+-    protected void a(CrashReport crashreport) {}
++    public void a(CrashReport crashreport) {}
+ 
+     public CrashReport b(CrashReport crashreport) {
+         crashreport = super.b(crashreport);
+@@ -293,11 +352,11 @@
+         return crashreport;
+     }
+ 
+-    protected void B() {
++    public void B() {
          System.exit(0);
      }
  
diff --git a/nms-patches/DispenseBehaviorProjectile.patch b/nms-patches/DispenseBehaviorProjectile.patch
index 2ce244de64..d8994bf756 100644
--- a/nms-patches/DispenseBehaviorProjectile.patch
+++ b/nms-patches/DispenseBehaviorProjectile.patch
@@ -12,7 +12,7 @@
  
      public DispenseBehaviorProjectile() {}
 @@ -10,9 +15,38 @@
-         EnumDirection enumdirection = BlockDispenser.e(isourceblock.f());
+         EnumDirection enumdirection = (EnumDirection) isourceblock.e().get(BlockDispenser.FACING);
          IProjectile iprojectile = this.a(world, iposition, itemstack);
  
 -        iprojectile.shoot((double) enumdirection.getAdjacentX(), (double) ((float) enumdirection.getAdjacentY() + 0.1F), (double) enumdirection.getAdjacentZ(), this.getPower(), this.a());
diff --git a/nms-patches/DispenserRegistry.patch b/nms-patches/DispenserRegistry.patch
index 85c1dd22d6..9246d281e5 100644
--- a/nms-patches/DispenserRegistry.patch
+++ b/nms-patches/DispenserRegistry.patch
@@ -164,7 +164,7 @@
  
 @@ -169,9 +265,48 @@
                  ItemBucket itembucket = (ItemBucket) itemstack.getItem();
-                 BlockPosition blockposition = isourceblock.getBlockPosition().shift(BlockDispenser.e(isourceblock.f()));
+                 BlockPosition blockposition = isourceblock.getBlockPosition().shift((EnumDirection) isourceblock.e().get(BlockDispenser.FACING));
  
 +                // CraftBukkit start
 +                World world = isourceblock.getWorld();
@@ -246,7 +246,7 @@
                      itemstack.setItem(item);
 @@ -220,11 +379,39 @@
                  World world = isourceblock.getWorld();
-                 BlockPosition blockposition = isourceblock.getBlockPosition().shift(BlockDispenser.e(isourceblock.f()));
+                 BlockPosition blockposition = isourceblock.getBlockPosition().shift((EnumDirection) isourceblock.e().get(BlockDispenser.FACING));
  
 +                // CraftBukkit start
 +                org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockPosition().getX(), isourceblock.getBlockPosition().getY(), isourceblock.getBlockPosition().getZ());
@@ -289,7 +289,7 @@
                      world.setAir(blockposition);
 @@ -252,6 +439,30 @@
                      World world = isourceblock.getWorld();
-                     BlockPosition blockposition = isourceblock.getBlockPosition().shift(BlockDispenser.e(isourceblock.f()));
+                     BlockPosition blockposition = isourceblock.getBlockPosition().shift((EnumDirection) isourceblock.e().get(BlockDispenser.FACING));
  
 +                    // CraftBukkit start
 +                    org.bukkit.block.Block block = world.getWorld().getBlockAt(isourceblock.getBlockPosition().getX(), isourceblock.getBlockPosition().getY(), isourceblock.getBlockPosition().getZ());
@@ -321,7 +321,7 @@
 @@ -279,11 +490,40 @@
              protected ItemStack b(ISourceBlock isourceblock, ItemStack itemstack) {
                  World world = isourceblock.getWorld();
-                 BlockPosition blockposition = isourceblock.getBlockPosition().shift(BlockDispenser.e(isourceblock.f()));
+                 BlockPosition blockposition = isourceblock.getBlockPosition().shift((EnumDirection) isourceblock.e().get(BlockDispenser.FACING));
 -                EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null);
 +                // EntityTNTPrimed entitytntprimed = new EntityTNTPrimed(world, (double) blockposition.getX() + 0.5D, (double) blockposition.getY(), (double) blockposition.getZ() + 0.5D, (EntityLiving) null);
 +
@@ -355,8 +355,9 @@
 +                // CraftBukkit end
  
                  world.addEntity(entitytntprimed);
-                 world.a((EntityHuman) null, entitytntprimed.locX, entitytntprimed.locY, entitytntprimed.locZ, SoundEffects.gk, SoundCategory.BLOCKS, 1.0F, 1.0F);
+-                world.a((EntityHuman) null, entitytntprimed.locX, entitytntprimed.locY, entitytntprimed.locZ, SoundEffects.gz, SoundCategory.BLOCKS, 1.0F, 1.0F);
 -                --itemstack.count;
++                world.a((EntityHuman) null, entitytntprimed.locX, entitytntprimed.locY, entitytntprimed.locZ, SoundEffects.gk, SoundCategory.BLOCKS, 1.0F, 1.0F);
 +                // --itemstack.count; // CraftBukkit - handled above
                  return itemstack;
              }
diff --git a/nms-patches/Enchantment.patch b/nms-patches/Enchantment.patch
index beea80b087..e339cfd62e 100644
--- a/nms-patches/Enchantment.patch
+++ b/nms-patches/Enchantment.patch
@@ -14,8 +14,8 @@
          Enchantment.enchantments.a(62, new MinecraftKey("lure"), new EnchantmentLure(Enchantment.Rarity.RARE, EnchantmentSlotType.FISHING_ROD, new EnumItemSlot[] { EnumItemSlot.MAINHAND}));
          Enchantment.enchantments.a(70, new MinecraftKey("mending"), new EnchantmentMending(Enchantment.Rarity.RARE, EnumItemSlot.values()));
 +        // CraftBukkit start
-+        for (Enchantment enchantment : Enchantment.enchantments) {
-+            org.bukkit.enchantments.Enchantment.registerEnchantment(new org.bukkit.craftbukkit.enchantments.CraftEnchantment(enchantment));
++        for (Object enchantment : Enchantment.enchantments) {
++            org.bukkit.enchantments.Enchantment.registerEnchantment(new org.bukkit.craftbukkit.enchantments.CraftEnchantment((Enchantment) enchantment));
 +        }
 +        // CraftBukkit end
      }
diff --git a/nms-patches/EnderDragonBattle.patch b/nms-patches/EnderDragonBattle.patch
index 59158e3e95..d7871f70ee 100644
--- a/nms-patches/EnderDragonBattle.patch
+++ b/nms-patches/EnderDragonBattle.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/EnderDragonBattle.java
 +++ b/net/minecraft/server/EnderDragonBattle.java
-@@ -249,7 +249,7 @@
+@@ -246,7 +246,7 @@
                          ShapeDetector.ShapeDetectorCollection shapedetector_shapedetectorcollection = this.f.a(this.d, tileentity.getPosition());
  
                          if (shapedetector_shapedetectorcollection != null) {
@@ -9,7 +9,7 @@
  
                              if (this.o == null && blockposition.getX() == 0 && blockposition.getZ() == 0) {
                                  this.o = blockposition;
-@@ -269,7 +269,7 @@
+@@ -266,7 +266,7 @@
  
              if (shapedetector_shapedetectorcollection1 != null) {
                  if (this.o == null) {
diff --git a/nms-patches/Entity.patch b/nms-patches/Entity.patch
index 9a9a59a623..3fc0085eb8 100644
--- a/nms-patches/Entity.patch
+++ b/nms-patches/Entity.patch
@@ -48,17 +48,17 @@
      private static final Logger a = LogManager.getLogger();
      private static final AxisAlignedBB b = new AxisAlignedBB(0.0D, 0.0D, 0.0D, 0.0D, 0.0D, 0.0D);
      private static double c = 1.0D;
-@@ -98,6 +137,9 @@
+@@ -99,6 +138,9 @@
      public boolean glowing;
-     private final Set<String> aG;
-     private boolean aH;
+     private final Set<String> aH;
+     private boolean aI;
 +    public boolean valid; // CraftBukkit
 +    public org.bukkit.projectiles.ProjectileSource projectileSource; // CraftBukkit - For projectiles only
 +    public boolean forceExplosionKnockback; // CraftBukkit - SPIGOT-949
  
      public Entity(World world) {
          this.id = Entity.entityCount++;
-@@ -195,6 +237,33 @@
+@@ -197,6 +239,33 @@
      }
  
      protected void setYawPitch(float f, float f1) {
@@ -92,8 +92,8 @@
          this.yaw = f % 360.0F;
          this.pitch = f1 % 360.0F;
      }
-@@ -238,7 +307,7 @@
-             if (this.ak) {
+@@ -240,7 +309,7 @@
+             if (this.al) {
                  MinecraftServer minecraftserver = this.world.getMinecraftServer();
  
 -                if (minecraftserver.getAllowNether()) {
@@ -101,7 +101,7 @@
                      if (!this.isPassenger()) {
                          int i = this.V();
  
-@@ -323,6 +392,27 @@
+@@ -325,6 +394,27 @@
      protected void burnFromLava() {
          if (!this.fireProof) {
              this.damageEntity(DamageSource.LAVA, 4.0F);
@@ -129,7 +129,7 @@
              this.setOnFire(15);
          }
      }
-@@ -363,6 +453,22 @@
+@@ -365,6 +455,22 @@
              this.a(this.getBoundingBox().c(d0, d1, d2));
              this.recalcPosition();
          } else {
@@ -208,7 +208,7 @@
 +            */
 +            // CraftBukkit end
  
-             boolean flag2 = this.ah();
+             boolean flag2 = this.ai();
  
 @@ -634,7 +765,16 @@
                  this.burn(1);
@@ -228,7 +228,7 @@
                          this.setOnFire(8);
                      }
                  }
-@@ -748,7 +888,7 @@
+@@ -756,7 +896,7 @@
          return null;
      }
  
@@ -237,7 +237,7 @@
          if (!this.fireProof) {
              this.damageEntity(DamageSource.FIRE, (float) i);
          }
-@@ -914,6 +1054,13 @@
+@@ -922,6 +1062,13 @@
      }
  
      public void spawnIn(World world) {
@@ -251,7 +251,7 @@
          this.world = world;
      }
  
-@@ -1107,6 +1254,18 @@
+@@ -1126,6 +1273,18 @@
          try {
              nbttagcompound.set("Pos", this.a(new double[] { this.locX, this.locY, this.locZ}));
              nbttagcompound.set("Motion", this.a(new double[] { this.motX, this.motY, this.motZ}));
@@ -270,7 +270,7 @@
              nbttagcompound.set("Rotation", this.a(new float[] { this.yaw, this.pitch}));
              nbttagcompound.setFloat("FallDistance", this.fallDistance);
              nbttagcompound.setShort("Fire", (short) this.fireTicks);
-@@ -1116,6 +1275,12 @@
+@@ -1135,6 +1294,12 @@
              nbttagcompound.setBoolean("Invulnerable", this.invulnerable);
              nbttagcompound.setInt("PortalCooldown", this.portalCooldown);
              nbttagcompound.a("UUID", this.getUniqueID());
@@ -283,7 +283,7 @@
              if (this.getCustomName() != null && !this.getCustomName().isEmpty()) {
                  nbttagcompound.setString("CustomName", this.getCustomName());
              }
-@@ -1187,6 +1352,8 @@
+@@ -1210,6 +1375,8 @@
              this.motX = nbttaglist1.e(0);
              this.motY = nbttaglist1.e(1);
              this.motZ = nbttaglist1.e(2);
@@ -292,15 +292,15 @@
              if (Math.abs(this.motX) > 10.0D) {
                  this.motX = 0.0D;
              }
-@@ -1198,6 +1365,7 @@
+@@ -1221,6 +1388,7 @@
              if (Math.abs(this.motZ) > 10.0D) {
                  this.motZ = 0.0D;
              }
 +            // CraftBukkit end */
  
-             this.lastX = this.M = this.locX = nbttaglist.e(0);
-             this.lastY = this.N = this.locY = nbttaglist.e(1);
-@@ -1246,6 +1414,58 @@
+             this.locX = nbttaglist.e(0);
+             this.locY = nbttaglist.e(1);
+@@ -1278,6 +1446,58 @@
                  this.setPosition(this.locX, this.locY, this.locZ);
              }
  
@@ -359,7 +359,7 @@
          } catch (Throwable throwable) {
              CrashReport crashreport = CrashReport.a(throwable, "Loading entity NBT");
              CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity being loaded");
-@@ -1307,6 +1527,12 @@
+@@ -1337,6 +1557,12 @@
  
      public EntityItem a(ItemStack itemstack, float f) {
          if (itemstack.count != 0 && itemstack.getItem() != null) {
@@ -372,8 +372,8 @@
              EntityItem entityitem = new EntityItem(this.world, this.locX, this.locY + (double) f, this.locZ, itemstack);
  
              entityitem.q();
-@@ -1428,6 +1654,24 @@
-         if (entity.bz() != this) {
+@@ -1458,6 +1684,24 @@
+         if (entity.bB() != this) {
              throw new IllegalStateException("Use x.startRiding(y), not y.addPassenger(x)");
          } else {
 +            // CraftBukkit start
@@ -394,11 +394,11 @@
 +                }
 +            }
 +            // CraftBukkit end
-             if (!this.world.isClientSide && entity instanceof EntityHuman && !(this.bu() instanceof EntityHuman)) {
+             if (!this.world.isClientSide && entity instanceof EntityHuman && !(this.bw() instanceof EntityHuman)) {
                  this.passengers.add(0, entity);
              } else {
-@@ -1441,6 +1685,22 @@
-         if (entity.bz() == this) {
+@@ -1471,6 +1715,22 @@
+         if (entity.bB() == this) {
              throw new IllegalStateException("Use x.stopRiding(y), not y.removePassenger(x)");
          } else {
 +            // CraftBukkit start
@@ -420,7 +420,7 @@
              this.passengers.remove(entity);
              entity.j = 60;
          }
-@@ -1584,10 +1844,38 @@
+@@ -1614,10 +1874,38 @@
      }
  
      public void onLightningStrike(EntityLightning entitylightning) {
@@ -461,7 +461,7 @@
          }
  
      }
-@@ -1722,19 +2010,67 @@
+@@ -1752,19 +2040,67 @@
          if (!this.world.isClientSide && !this.dead) {
              this.world.methodProfiler.a("changeDimension");
              MinecraftServer minecraftserver = this.h();
@@ -532,7 +532,7 @@
              BlockPosition blockposition;
  
              if (i == 1) {
-@@ -1763,12 +2099,18 @@
+@@ -1793,12 +2129,18 @@
                  blockposition = new BlockPosition(this);
              }
  
@@ -552,7 +552,7 @@
                  if (j == 1 && i == 1) {
                      BlockPosition blockposition1 = worldserver1.q(worldserver1.getSpawn());
  
-@@ -1776,6 +2118,7 @@
+@@ -1806,6 +2148,7 @@
                  } else {
                      entity.setPositionRotation(blockposition, entity.yaw, entity.pitch);
                  }
@@ -560,7 +560,7 @@
  
                  boolean flag = entity.attachedToPlayer;
  
-@@ -1783,6 +2126,14 @@
+@@ -1813,6 +2156,14 @@
                  worldserver1.addEntity(entity);
                  entity.attachedToPlayer = flag;
                  worldserver1.entityJoinedWorld(entity, false);
@@ -575,7 +575,7 @@
              }
  
              this.dead = true;
-@@ -1893,6 +2244,11 @@
+@@ -1923,6 +2274,11 @@
      }
  
      public void setCustomName(String s) {
@@ -587,7 +587,7 @@
          this.datawatcher.set(Entity.aA, s);
      }
  
-@@ -1950,7 +2306,26 @@
+@@ -1980,7 +2336,26 @@
      }
  
      public void a(AxisAlignedBB axisalignedbb) {
@@ -615,8 +615,8 @@
      }
  
      public float getHeadHeight() {
-@@ -2124,7 +2499,7 @@
-         for (Iterator iterator = this.bv().iterator(); iterator.hasNext(); entity.a(oclass, set)) {
+@@ -2154,7 +2529,7 @@
+         for (Iterator iterator = this.bx().iterator(); iterator.hasNext(); entity.a(oclass, set)) {
              entity = (Entity) iterator.next();
              if (oclass.isAssignableFrom(entity.getClass())) {
 -                set.add(entity);
diff --git a/nms-patches/EntityAgeable.patch b/nms-patches/EntityAgeable.patch
index a8ceef6220..5a95ae6bcc 100644
--- a/nms-patches/EntityAgeable.patch
+++ b/nms-patches/EntityAgeable.patch
@@ -2,13 +2,13 @@
 +++ b/net/minecraft/server/EntityAgeable.java
 @@ -10,6 +10,7 @@
      protected int c;
-     private float bx = -1.0F;
-     private float by;
+     private float by = -1.0F;
+     private float bz;
 +    public boolean ageLocked; // CraftBukkit
  
      public EntityAgeable(World world) {
          super(world);
-@@ -28,13 +29,16 @@
+@@ -28,13 +29,18 @@
                      if (entityageable != null) {
                          entityageable.setAgeRaw(-24000);
                          entityageable.setPositionRotation(this.locX, this.locY, this.locZ, 0.0F, 0.0F);
@@ -20,13 +20,15 @@
  
                          if (!entityhuman.abilities.canInstantlyBuild) {
                              --itemstack.count;
-+                            if (itemstack.count == 0) { // CraftBukkit - allow less than 0 stacks as "infinite"
++                            // CraftBukkit start - allow less than 0 stacks as "infinite"
++                            if (itemstack.count == 0) {
 +                                entityhuman.inventory.setItem(entityhuman.inventory.itemInHandIndex, (ItemStack) null);
 +                            }
++                            // CraftBukkit end
                          }
                      }
                  }
-@@ -97,12 +101,14 @@
+@@ -97,12 +103,14 @@
          super.b(nbttagcompound);
          nbttagcompound.setInt("Age", this.getAge());
          nbttagcompound.setInt("ForcedAge", this.b);
@@ -41,7 +43,7 @@
      }
  
      public void a(DataWatcherObject<?> datawatcherobject) {
-@@ -115,7 +121,7 @@
+@@ -115,7 +123,7 @@
  
      public void n() {
          super.n();
diff --git a/nms-patches/EntityAreaEffectCloud.patch b/nms-patches/EntityAreaEffectCloud.patch
index 2da2e1c5fd..2125291710 100644
--- a/nms-patches/EntityAreaEffectCloud.patch
+++ b/nms-patches/EntityAreaEffectCloud.patch
@@ -11,19 +11,19 @@
  import java.util.Map.Entry;
  import javax.annotation.Nullable;
  
-@@ -92,6 +96,22 @@
+@@ -96,6 +100,22 @@
  
      }
  
 +    // CraftBukkit start accessor methods
 +    public void refreshEffects() {
 +        if (!this.hasColor) {
-+            this.getDataWatcher().set(EntityAreaEffectCloud.b, Integer.valueOf(PotionUtil.a((Collection) PotionUtil.a(this.e, (Collection) this.effects)))); // PAIL: rename
++            this.getDataWatcher().set(EntityAreaEffectCloud.b, Integer.valueOf(PotionUtil.a((Collection) PotionUtil.a(this.potionRegistry, (Collection) this.effects)))); // PAIL: rename
 +        }
 +    }
 +
 +    public String getType() {
-+        return ((MinecraftKey) PotionRegistry.a.b(this.e)).toString(); // PAIL: rename
++        return ((MinecraftKey) PotionRegistry.a.b(this.potionRegistry)).toString(); // PAIL: rename
 +    }
 +
 +    public void setType(String string) {
@@ -34,7 +34,7 @@
      public int getColor() {
          return ((Integer) this.getDataWatcher().get(EntityAreaEffectCloud.b)).intValue();
      }
-@@ -238,6 +258,7 @@
+@@ -265,6 +285,7 @@
                      if (!list.isEmpty()) {
                          Iterator iterator2 = list.iterator();
  
@@ -42,7 +42,7 @@
                          while (iterator2.hasNext()) {
                              EntityLiving entityliving = (EntityLiving) iterator2.next();
  
-@@ -247,6 +268,17 @@
+@@ -274,6 +295,17 @@
                                  double d2 = d0 * d0 + d1 * d1;
  
                                  if (d2 <= (double) (f * f)) {
@@ -57,6 +57,6 @@
 +                                if (entity instanceof CraftLivingEntity) {
 +                                    EntityLiving entityliving = ((CraftLivingEntity) entity).getHandle();
 +                                    // CraftBukkit end
-                                     this.g.put(entityliving, Integer.valueOf(this.ticksLived + this.reapplicationDelay));
+                                     this.au.put(entityliving, Integer.valueOf(this.ticksLived + this.reapplicationDelay));
                                      Iterator iterator3 = arraylist.iterator();
  
diff --git a/nms-patches/EntityArmorStand.patch b/nms-patches/EntityArmorStand.patch
index 67ced54f69..9e7ef90b8a 100644
--- a/nms-patches/EntityArmorStand.patch
+++ b/nms-patches/EntityArmorStand.patch
@@ -15,10 +15,10 @@
 +
  public class EntityArmorStand extends EntityLiving {
  
-     private static final Vector3f bq = new Vector3f(0.0F, 0.0F, 0.0F);
-@@ -362,6 +371,21 @@
-         if (itemstack1 == null || (this.bA & 1 << enumitemslot.c() + 8) == 0) {
-             if (itemstack1 != null || (this.bA & 1 << enumitemslot.c() + 16) == 0) {
+     private static final Vector3f br = new Vector3f(0.0F, 0.0F, 0.0F);
+@@ -373,6 +382,21 @@
+         if (itemstack1 == null || (this.bB & 1 << enumitemslot.c() + 8) == 0) {
+             if (itemstack1 != null || (this.bB & 1 << enumitemslot.c() + 16) == 0) {
                  ItemStack itemstack2;
 +                // CraftBukkit start
 +                org.bukkit.inventory.ItemStack armorStandItem = CraftItemStack.asCraftMirror(itemstack1);
@@ -38,7 +38,7 @@
  
                  if (entityhuman.abilities.canInstantlyBuild && (itemstack1 == null || itemstack1.getItem() == Item.getItemOf(Blocks.AIR)) && itemstack != null) {
                      itemstack2 = itemstack.cloneItemStack();
-@@ -383,6 +407,11 @@
+@@ -394,6 +418,11 @@
      }
  
      public boolean damageEntity(DamageSource damagesource, float f) {
diff --git a/nms-patches/EntityArrow.patch b/nms-patches/EntityArrow.patch
index 25005044d3..ef051dd026 100644
--- a/nms-patches/EntityArrow.patch
+++ b/nms-patches/EntityArrow.patch
@@ -21,7 +21,7 @@
          if (entityliving instanceof EntityHuman) {
              this.fromPlayer = EntityArrow.PickupStatus.ALLOWED;
          }
-@@ -229,7 +236,7 @@
+@@ -236,7 +243,7 @@
  
      protected void a(MovingObjectPosition movingobjectposition) {
          Entity entity = movingobjectposition.entity;
@@ -30,7 +30,7 @@
          if (entity != null) {
              float f = MathHelper.sqrt(this.motX * this.motX + this.motY * this.motY + this.motZ * this.motZ);
              int i = MathHelper.f((double) f * this.damage);
-@@ -247,7 +254,13 @@
+@@ -254,7 +261,13 @@
              }
  
              if (this.isBurning() && !(entity instanceof EntityEnderman)) {
@@ -45,7 +45,7 @@
              }
  
              if (entity.damageEntity(damagesource, (float) i)) {
-@@ -397,6 +410,20 @@
+@@ -410,6 +423,20 @@
  
      public void d(EntityHuman entityhuman) {
          if (!this.world.isClientSide && this.inGround && this.shake <= 0) {
@@ -66,7 +66,7 @@
              boolean flag = this.fromPlayer == EntityArrow.PickupStatus.ALLOWED || this.fromPlayer == EntityArrow.PickupStatus.CREATIVE_ONLY && entityhuman.abilities.canInstantlyBuild;
  
              if (this.fromPlayer == EntityArrow.PickupStatus.ALLOWED && !entityhuman.inventory.pickup(this.j())) {
-@@ -455,6 +482,12 @@
+@@ -468,6 +495,12 @@
          return (b0 & 1) != 0;
      }
  
diff --git a/nms-patches/EntityBoat.patch b/nms-patches/EntityBoat.patch
index 4b65945808..3ae4271f82 100644
--- a/nms-patches/EntityBoat.patch
+++ b/nms-patches/EntityBoat.patch
@@ -17,8 +17,8 @@
  
      private static final DataWatcherObject<Integer> a = DataWatcher.a(EntityBoat.class, DataWatcherRegistry.b);
 @@ -32,6 +41,14 @@
-     private EntityBoat.EnumStatus aH;
-     private double aI;
+     private EntityBoat.EnumStatus aI;
+     private double aJ;
  
 +    // CraftBukkit start
 +    // PAIL: Some of these haven't worked since a few updates, and since 1.9 they are less and less applicable.
@@ -39,7 +39,7 @@
      }
  
      protected boolean playStepSound() {
-@@ -91,6 +109,19 @@
+@@ -95,6 +113,19 @@
              if (damagesource instanceof EntityDamageSourceIndirect && damagesource.getEntity() != null && this.w(damagesource.getEntity())) {
                  return false;
              } else {
@@ -59,7 +59,7 @@
                  this.d(-this.q());
                  this.b(10);
                  this.setDamage(this.n() + f * 10.0F);
-@@ -98,6 +129,15 @@
+@@ -102,6 +133,15 @@
                  boolean flag = damagesource.getEntity() instanceof EntityHuman && ((EntityHuman) damagesource.getEntity()).abilities.canInstantlyBuild;
  
                  if (flag || this.n() > 40.0F) {
@@ -75,7 +75,7 @@
                      if (!flag && this.world.getGameRules().getBoolean("doEntityDrops")) {
                          this.a(this.j(), 1, 0.0F);
                      }
-@@ -115,9 +155,25 @@
+@@ -119,9 +159,25 @@
      public void collide(Entity entity) {
          if (entity instanceof EntityBoat) {
              if (entity.getBoundingBox().b < this.getBoundingBox().e) {
@@ -101,16 +101,16 @@
              super.collide(entity);
          }
  
-@@ -154,6 +210,8 @@
+@@ -158,6 +214,8 @@
          return this.getDirection().e();
      }
  
 +    private Location lastLocation; // CraftBukkit
 +
      public void m() {
-         this.aH = this.aG;
-         this.aG = this.t();
-@@ -174,7 +232,6 @@
+         this.aI = this.aH;
+         this.aH = this.t();
+@@ -178,7 +236,6 @@
          if (this.n() > 0.0F) {
              this.setDamage(this.n() - 1.0F);
          }
@@ -118,7 +118,7 @@
          this.lastX = this.locX;
          this.lastY = this.locY;
          this.lastZ = this.locZ;
-@@ -198,6 +255,22 @@
+@@ -202,6 +259,22 @@
              this.motZ = 0.0D;
          }
  
@@ -141,7 +141,7 @@
          for (int i = 0; i <= 1; ++i) {
              if (this.a(i)) {
                  this.f[i] = (float) ((double) this.f[i] + 0.01D);
-@@ -595,6 +668,11 @@
+@@ -599,6 +672,11 @@
  
                      this.e(this.fallDistance, 1.0F);
                      if (!this.world.isClientSide && !this.dead) {
@@ -153,7 +153,7 @@
                          this.die();
                          if (this.world.getGameRules().getBoolean("doEntityDrops")) {
                              int i;
-@@ -608,6 +686,7 @@
+@@ -612,6 +690,7 @@
                              }
                          }
                      }
diff --git a/nms-patches/EntityChicken.patch b/nms-patches/EntityChicken.patch
index ab00defec2..2dd746a413 100644
--- a/nms-patches/EntityChicken.patch
+++ b/nms-patches/EntityChicken.patch
@@ -10,15 +10,15 @@
 +        }
 +        // CraftBukkit end
          super.n();
-         this.bA = this.bw;
-         this.by = this.bx;
+         this.bB = this.bx;
+         this.bz = this.by;
 @@ -61,7 +66,9 @@
-         this.bw += this.bB * 2.0F;
-         if (!this.world.isClientSide && !this.isBaby() && !this.isChickenJockey() && --this.bC <= 0) {
+         this.bx += this.bC * 2.0F;
+         if (!this.world.isClientSide && !this.isBaby() && !this.isChickenJockey() && --this.bD <= 0) {
              this.a(SoundEffects.aa, 1.0F, (this.random.nextFloat() - this.random.nextFloat()) * 0.2F + 1.0F);
 +            this.forceDrops = true; // CraftBukkit
              this.a(Items.EGG, 1);
 +            this.forceDrops = false; // CraftBukkit
-             this.bC = this.random.nextInt(6000) + 6000;
+             this.bD = this.random.nextInt(6000) + 6000;
          }
  
diff --git a/nms-patches/EntityCow.patch b/nms-patches/EntityCow.patch
index 34570ca3b3..1593b85b4c 100644
--- a/nms-patches/EntityCow.patch
+++ b/nms-patches/EntityCow.patch
@@ -11,7 +11,7 @@
  
  public class EntityCow extends EntityAnimal {
  
-@@ -53,12 +57,22 @@
+@@ -57,12 +61,22 @@
  
      public boolean a(EntityHuman entityhuman, EnumHand enumhand, @Nullable ItemStack itemstack) {
          if (itemstack != null && itemstack.getItem() == Items.BUCKET && !entityhuman.abilities.canInstantlyBuild && !this.isBaby()) {
diff --git a/nms-patches/EntityCreature.patch b/nms-patches/EntityCreature.patch
index c1c0f98b3d..724b55d234 100644
--- a/nms-patches/EntityCreature.patch
+++ b/nms-patches/EntityCreature.patch
@@ -10,7 +10,7 @@
 +
  public abstract class EntityCreature extends EntityInsentient {
  
-     public static final UUID bu = UUID.fromString("E199AD21-BA8A-4C53-8D13-6182D5C69D3A");
+     public static final UUID bv = UUID.fromString("E199AD21-BA8A-4C53-8D13-6182D5C69D3A");
 @@ -71,6 +75,7 @@
  
              if (this instanceof EntityTameableAnimal && ((EntityTameableAnimal) this).isSitting()) {
@@ -26,4 +26,4 @@
 +                this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), EntityUnleashEvent.UnleashReason.DISTANCE)); // CraftBukkit
                  this.unleash(true, true);
              }
-         } else if (!this.isLeashed() && this.bw) {
+         } else if (!this.isLeashed() && this.bx) {
diff --git a/nms-patches/EntityCreeper.patch b/nms-patches/EntityCreeper.patch
index 2de4eedc23..9f413e379e 100644
--- a/nms-patches/EntityCreeper.patch
+++ b/nms-patches/EntityCreeper.patch
@@ -11,7 +11,7 @@
  
  public class EntityCreeper extends EntityMonster {
  
-@@ -119,7 +123,7 @@
+@@ -123,7 +127,7 @@
      }
  
      public void die(DamageSource damagesource) {
@@ -20,7 +20,7 @@
          if (this.world.getGameRules().getBoolean("doMobLoot")) {
              if (damagesource.getEntity() instanceof EntitySkeleton) {
                  int i = Item.getId(Items.RECORD_13);
-@@ -132,6 +136,7 @@
+@@ -136,6 +140,7 @@
                  this.a(new ItemStack(Items.SKULL, 1, 4), 0.0F);
              }
          }
@@ -28,7 +28,7 @@
  
      }
  
-@@ -158,9 +163,19 @@
+@@ -162,9 +167,19 @@
  
      public void onLightningStrike(EntityLightning entitylightning) {
          super.onLightningStrike(entitylightning);
@@ -48,19 +48,19 @@
 +
      protected boolean a(EntityHuman entityhuman, EnumHand enumhand, @Nullable ItemStack itemstack) {
          if (itemstack != null && itemstack.getItem() == Items.FLINT_AND_STEEL) {
-             this.world.a(entityhuman, this.locX, this.locY, this.locZ, SoundEffects.bx, this.bA(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F);
-@@ -180,9 +195,17 @@
+             this.world.a(entityhuman, this.locX, this.locY, this.locZ, SoundEffects.by, this.bC(), 1.0F, this.random.nextFloat() * 0.4F + 0.8F);
+@@ -184,9 +199,17 @@
              boolean flag = this.world.getGameRules().getBoolean("mobGriefing");
              float f = this.isPowered() ? 2.0F : 1.0F;
  
--            this.aU = true;
+-            this.aV = true;
 -            this.world.explode(this, this.locX, this.locY, this.locZ, (float) this.explosionRadius * f, flag);
 -            this.die();
 +            // CraftBukkit start
 +            ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), this.explosionRadius * f, false);
 +            this.world.getServer().getPluginManager().callEvent(event);
 +            if (!event.isCancelled()) {
-+                this.aU = true;
++                this.aV = true;
 +                this.world.createExplosion(this, this.locX, this.locY, this.locZ, event.getRadius(), event.getFire(), flag);
 +                this.die();
 +            } else {
diff --git a/nms-patches/EntityEgg.patch b/nms-patches/EntityEgg.patch
index 9b33c184c6..de81882486 100644
--- a/nms-patches/EntityEgg.patch
+++ b/nms-patches/EntityEgg.patch
@@ -13,7 +13,7 @@
  public class EntityEgg extends EntityProjectile {
  
      public EntityEgg(World world) {
-@@ -19,21 +26,37 @@
+@@ -23,21 +30,37 @@
              movingobjectposition.entity.damageEntity(DamageSource.projectile(this, this.getShooter()), 0.0F);
          }
  
diff --git a/nms-patches/EntityEnderDragon.patch b/nms-patches/EntityEnderDragon.patch
index 2973d62d98..59a4484fc8 100644
--- a/nms-patches/EntityEnderDragon.patch
+++ b/nms-patches/EntityEnderDragon.patch
@@ -12,11 +12,11 @@
 +// PAIL: Fixme
  public class EntityEnderDragon extends EntityInsentient implements IComplex, IMonster {
  
-     private static final Logger bI = LogManager.getLogger();
+     private static final Logger bJ = LogManager.getLogger();
 @@ -33,6 +38,7 @@
-     private final PathPoint[] bN = new PathPoint[24];
-     private final int[] bO = new int[24];
-     private final Path bP = new Path();
+     private final PathPoint[] bO = new PathPoint[24];
+     private final int[] bP = new int[24];
+     private final Path bQ = new Path();
 +    private Explosion explosionSource = new Explosion(null, this, Double.NaN, Double.NaN, Double.NaN, Float.NaN, true, true); // CraftBukkit - reusable source for CraftTNTPrimed.getSource()
  
      public EntityEnderDragon(World world) {
@@ -30,7 +30,7 @@
                          d0 = vec3d.x - this.locX;
                          d1 = vec3d.y - this.locY;
                          d2 = vec3d.z - this.locZ;
-@@ -309,7 +315,14 @@
+@@ -314,7 +320,14 @@
              if (this.currentEnderCrystal.dead) {
                  this.currentEnderCrystal = null;
              } else if (this.ticksLived % 10 == 0 && this.getHealth() < this.getMaxHealth()) {
@@ -46,7 +46,7 @@
              }
          }
  
-@@ -382,6 +395,10 @@
+@@ -387,6 +400,10 @@
          int j1 = MathHelper.floor(axisalignedbb.f);
          boolean flag = false;
          boolean flag1 = false;
@@ -57,7 +57,7 @@
  
          for (int k1 = i; k1 <= l; ++k1) {
              for (int l1 = j; l1 <= i1; ++l1) {
-@@ -395,7 +412,11 @@
+@@ -400,7 +417,11 @@
                              flag = true;
                          } else if (block != Blocks.BARRIER && block != Blocks.OBSIDIAN && block != Blocks.END_STONE && block != Blocks.BEDROCK && block != Blocks.END_PORTAL && block != Blocks.END_PORTAL_FRAME) {
                              if (block != Blocks.COMMAND_BLOCK && block != Blocks.dc && block != Blocks.dd && block != Blocks.IRON_BARS && block != Blocks.END_GATEWAY) {
@@ -70,7 +70,7 @@
                              } else {
                                  flag = true;
                              }
-@@ -407,6 +428,41 @@
+@@ -412,6 +433,41 @@
              }
          }
  
diff --git a/nms-patches/EntityEnderPearl.patch b/nms-patches/EntityEnderPearl.patch
index 7e5dfe53d8..62cc9bf68b 100644
--- a/nms-patches/EntityEnderPearl.patch
+++ b/nms-patches/EntityEnderPearl.patch
@@ -12,7 +12,7 @@
  public class EntityEnderPearl extends EntityProjectile {
  
      private EntityLiving d;
-@@ -51,21 +57,35 @@
+@@ -55,21 +61,35 @@
                  EntityPlayer entityplayer = (EntityPlayer) entityliving;
  
                  if (entityplayer.playerConnection.a().isConnected() && entityplayer.world == this.world && !entityplayer.isSleeping()) {
@@ -52,7 +52,7 @@
                      }
 -
 -                    if (entityliving.isPassenger()) {
--                        this.stopRiding();
+-                        entityliving.stopRiding();
 -                    }
 -
 -                    entityliving.enderTeleportTo(this.locX, this.locY, this.locZ);
diff --git a/nms-patches/EntityEnderman.patch b/nms-patches/EntityEnderman.patch
index 9b434da936..1c4a6acfba 100644
--- a/nms-patches/EntityEnderman.patch
+++ b/nms-patches/EntityEnderman.patch
@@ -36,7 +36,7 @@
  
      }
  
-@@ -309,8 +322,12 @@
+@@ -320,8 +333,12 @@
              boolean flag = movingobjectposition != null && movingobjectposition.a().equals(blockposition);
  
              if (EntityEnderman.c.contains(block) && flag) {
@@ -51,7 +51,7 @@
              }
  
          }
-@@ -340,8 +357,12 @@
+@@ -351,8 +368,12 @@
              IBlockData iblockdata2 = this.a.getCarried();
  
              if (iblockdata2 != null && this.a(world, blockposition, iblockdata2.getBlock(), iblockdata, iblockdata1)) {
diff --git a/nms-patches/EntityExperienceOrb.patch b/nms-patches/EntityExperienceOrb.patch
index c63e7c19b0..21c585c528 100644
--- a/nms-patches/EntityExperienceOrb.patch
+++ b/nms-patches/EntityExperienceOrb.patch
@@ -20,7 +20,7 @@
          if (this.c > 0) {
              --this.c;
          }
-@@ -65,6 +72,16 @@
+@@ -68,6 +75,16 @@
          }
  
          if (this.targetPlayer != null) {
@@ -34,10 +34,10 @@
 +            }
 +
 +            if (!cancelled && targetPlayer != null) {
-             double d1 = (this.targetPlayer.locX - this.locX) / d0;
-             double d2 = (this.targetPlayer.locY + (double) this.targetPlayer.getHeadHeight() / 2.0D - this.locY) / d0;
-             double d3 = (this.targetPlayer.locZ - this.locZ) / d0;
-@@ -77,6 +94,8 @@
+             double d1 = (this.targetPlayer.locX - this.locX) / 8.0D;
+             double d2 = (this.targetPlayer.locY + (double) this.targetPlayer.getHeadHeight() / 2.0D - this.locY) / 8.0D;
+             double d3 = (this.targetPlayer.locZ - this.locZ) / 8.0D;
+@@ -80,6 +97,8 @@
                  this.motY += d2 / d4 * d5 * 0.1D;
                  this.motZ += d3 / d4 * d5 * 0.1D;
              }
@@ -46,7 +46,7 @@
          }
  
          this.move(this.motX, this.motY, this.motZ);
-@@ -151,7 +170,7 @@
+@@ -154,7 +173,7 @@
                  }
  
                  if (this.value > 0) {
@@ -55,7 +55,7 @@
                  }
  
                  this.die();
-@@ -173,6 +192,24 @@
+@@ -176,6 +195,24 @@
      }
  
      public static int getOrbValue(int i) {
diff --git a/nms-patches/EntityFallingBlock.patch b/nms-patches/EntityFallingBlock.patch
index a57a6e9e46..2c1dcfd246 100644
--- a/nms-patches/EntityFallingBlock.patch
+++ b/nms-patches/EntityFallingBlock.patch
@@ -18,7 +18,7 @@
                      this.world.setAir(blockposition);
                  } else if (!this.world.isClientSide) {
                      this.die();
-@@ -85,7 +87,7 @@
+@@ -88,7 +90,7 @@
  
                      if (BlockFalling.i(this.world.getType(new BlockPosition(this.locX, this.locY - 0.009999999776482582D, this.locZ)))) {
                          this.onGround = false;
@@ -27,7 +27,7 @@
                      }
  
                      this.motX *= 0.699999988079071D;
-@@ -94,7 +96,13 @@
+@@ -97,7 +99,13 @@
                      if (iblockdata.getBlock() != Blocks.PISTON_EXTENSION) {
                          this.die();
                          if (!this.f) {
@@ -42,7 +42,7 @@
                                  if (block instanceof BlockFalling) {
                                      ((BlockFalling) block).a_(this.world, blockposition);
                                  }
-@@ -151,7 +159,9 @@
+@@ -154,7 +162,9 @@
                  while (iterator.hasNext()) {
                      Entity entity = (Entity) iterator.next();
  
diff --git a/nms-patches/EntityFireball.patch b/nms-patches/EntityFireball.patch
index c0780ae7f9..2f7072d8e4 100644
--- a/nms-patches/EntityFireball.patch
+++ b/nms-patches/EntityFireball.patch
@@ -17,7 +17,7 @@
  
      public EntityFireball(World world) {
          super(world);
-@@ -36,10 +40,17 @@
+@@ -36,12 +40,19 @@
      public EntityFireball(World world, EntityLiving entityliving, double d0, double d1, double d2) {
          super(world);
          this.shooter = entityliving;
@@ -25,7 +25,9 @@
          this.setSize(1.0F, 1.0F);
          this.setPositionRotation(entityliving.locX, entityliving.locY, entityliving.locZ, entityliving.yaw, entityliving.pitch);
          this.setPosition(this.locX, this.locY, this.locZ);
-         this.motX = this.motY = this.motZ = 0.0D;
+         this.motX = 0.0D;
+         this.motY = 0.0D;
+         this.motZ = 0.0D;
 +        // CraftBukkit start - Added setDirection method
 +        this.setDirection(d0, d1, d2);
 +    }
@@ -35,7 +37,7 @@
          d0 += this.random.nextGaussian() * 0.4D;
          d1 += this.random.nextGaussian() * 0.4D;
          d2 += this.random.nextGaussian() * 0.4D;
-@@ -83,6 +94,12 @@
+@@ -85,6 +96,12 @@
  
              if (movingobjectposition != null) {
                  this.a(movingobjectposition);
@@ -48,9 +50,9 @@
              }
  
              this.locX += this.motX;
-@@ -187,6 +204,11 @@
+@@ -191,6 +208,11 @@
          } else {
-             this.ao();
+             this.ap();
              if (damagesource.getEntity() != null) {
 +                // CraftBukkit start
 +                if (CraftEventFactory.handleNonLivingEntityDamageEvent(this, damagesource, f)) {
@@ -60,7 +62,7 @@
                  Vec3D vec3d = damagesource.getEntity().aB();
  
                  if (vec3d != null) {
-@@ -200,6 +222,7 @@
+@@ -204,6 +226,7 @@
  
                  if (damagesource.getEntity() instanceof EntityLiving) {
                      this.shooter = (EntityLiving) damagesource.getEntity();
diff --git a/nms-patches/EntityFishingHook.patch b/nms-patches/EntityFishingHook.patch
index e993146cfe..043d78d78b 100644
--- a/nms-patches/EntityFishingHook.patch
+++ b/nms-patches/EntityFishingHook.patch
@@ -22,9 +22,9 @@
                          this.hooked = movingobjectposition.entity;
                          this.getDataWatcher().set(EntityFishingHook.c, Integer.valueOf(this.hooked.getId() + 1));
 @@ -266,6 +273,10 @@
-                         if (this.av <= 0) {
+                         if (this.au <= 0) {
+                             this.av = 0;
                              this.aw = 0;
-                             this.ax = 0;
 +                            // CraftBukkit start
 +                            PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.owner.getBukkitEntity(), null, (Fish) this.getBukkitEntity(), PlayerFishEvent.State.FAILED_ATTEMPT);
 +                            this.world.getServer().getPluginManager().callEvent(playerFishEvent);
@@ -33,9 +33,9 @@
                      } else {
                          double d10;
 @@ -278,6 +289,13 @@
-                         if (this.ax > 0) {
-                             this.ax -= l;
-                             if (this.ax <= 0) {
+                         if (this.aw > 0) {
+                             this.aw -= l;
+                             if (this.aw <= 0) {
 +                                // CraftBukkit start
 +                                PlayerFishEvent playerFishEvent = new PlayerFishEvent((Player) this.owner.getBukkitEntity(), null, (Fish) this.getBukkitEntity(), PlayerFishEvent.State.BITE);
 +                                this.world.getServer().getPluginManager().callEvent(playerFishEvent);
@@ -46,7 +46,7 @@
                                  this.motY -= 0.20000000298023224D;
                                  this.a(SoundEffects.G, 0.25F, 1.0F + (this.random.nextFloat() - this.random.nextFloat()) * 0.4F);
                                  f2 = (float) MathHelper.floor(this.getBoundingBox().b);
-@@ -388,6 +406,14 @@
+@@ -390,6 +408,14 @@
              int i = 0;
  
              if (this.hooked != null) {
@@ -61,7 +61,7 @@
                  this.k();
                  this.world.broadcastEntityEffect(this, (byte) 31);
                  i = this.hooked instanceof EntityItem ? 3 : 5;
-@@ -400,6 +426,15 @@
+@@ -402,6 +428,15 @@
                  while (iterator.hasNext()) {
                      ItemStack itemstack = (ItemStack) iterator.next();
                      EntityItem entityitem = new EntityItem(this.world, this.locX, this.locY, this.locZ, itemstack);
@@ -77,9 +77,9 @@
                      double d0 = this.owner.locX - this.locX;
                      double d1 = this.owner.locY - this.locY;
                      double d2 = this.owner.locZ - this.locZ;
-@@ -410,15 +445,36 @@
-                     entityitem.motY = d1 * d4 + (double) MathHelper.sqrt(d3) * 0.08D;
-                     entityitem.motZ = d2 * d4;
+@@ -412,15 +447,36 @@
+                     entityitem.motY = d1 * 0.1D + (double) MathHelper.sqrt(d3) * 0.08D;
+                     entityitem.motZ = d2 * 0.1D;
                      this.world.addEntity(entityitem);
 -                    this.owner.world.addEntity(new EntityExperienceOrb(this.owner.world, this.owner.locX, this.owner.locY + 0.5D, this.owner.locZ + 0.5D, this.random.nextInt(6) + 1));
 +                    // CraftBukkit start - this.random.nextInt(6) + 1 -> playerFishEvent.getExpToDrop()
diff --git a/nms-patches/EntityGhast.patch b/nms-patches/EntityGhast.patch
index d48f0d421e..da45161b99 100644
--- a/nms-patches/EntityGhast.patch
+++ b/nms-patches/EntityGhast.patch
@@ -1,12 +1,12 @@
 --- a/net/minecraft/server/EntityGhast.java
 +++ b/net/minecraft/server/EntityGhast.java
-@@ -155,7 +155,8 @@
+@@ -159,7 +159,8 @@
                      world.a((EntityHuman) null, 1016, new BlockPosition(this.ghast), 0);
                      EntityLargeFireball entitylargefireball = new EntityLargeFireball(world, this.ghast, d2, d3, d4);
  
 -                    entitylargefireball.yield = this.ghast.getPower();
 +                    // CraftBukkit - set bukkitYield when setting explosionpower
 +                    entitylargefireball.bukkitYield = entitylargefireball.yield = this.ghast.getPower();
-                     entitylargefireball.locX = this.ghast.locX + vec3d.x * d1;
+                     entitylargefireball.locX = this.ghast.locX + vec3d.x * 4.0D;
                      entitylargefireball.locY = this.ghast.locY + (double) (this.ghast.length / 2.0F) + 0.5D;
-                     entitylargefireball.locZ = this.ghast.locZ + vec3d.z * d1;
+                     entitylargefireball.locZ = this.ghast.locZ + vec3d.z * 4.0D;
diff --git a/nms-patches/EntityHanging.patch b/nms-patches/EntityHanging.patch
index 88050c959e..b5936d9ac3 100644
--- a/nms-patches/EntityHanging.patch
+++ b/nms-patches/EntityHanging.patch
@@ -12,7 +12,7 @@
  public abstract class EntityHanging extends Entity {
  
      private static final Predicate<Entity> c = new Predicate() {
-@@ -40,30 +45,39 @@
+@@ -41,39 +46,44 @@
          this.updateBoundingBox();
      }
  
@@ -21,60 +21,63 @@
 -            double d0 = (double) this.blockPosition.getX() + 0.5D;
 -            double d1 = (double) this.blockPosition.getY() + 0.5D;
 -            double d2 = (double) this.blockPosition.getZ() + 0.5D;
-+    /* CraftBukkit start - bounding box calculation made static (for spawn usage)
-+
-+        l is from function l()
-+        m is from function m()
-+
-+        Placing here as it's more likely to be noticed as something which needs to be updated
-+        then something in a CraftBukkit file.
-+     */
-+    public static AxisAlignedBB calculateBoundingBox(Entity entity, BlockPosition blockPosition, EnumDirection direction, int width, int height) {
-+            double d0 = (double) blockPosition.getX() + 0.5D;
-+            double d1 = (double) blockPosition.getY() + 0.5D;
-+            double d2 = (double) blockPosition.getZ() + 0.5D;
-             double d3 = 0.46875D;
+-            double d3 = 0.46875D;
 -            double d4 = this.a(this.getWidth());
 -            double d5 = this.a(this.getHeight());
-+            double d4 = a(width);
-+            double d5 = a(height);
- 
+-
 -            d0 -= (double) this.direction.getAdjacentX() * 0.46875D;
 -            d2 -= (double) this.direction.getAdjacentZ() * 0.46875D;
-+            d0 -= (double) direction.getAdjacentX() * 0.46875D;
-+            d2 -= (double) direction.getAdjacentZ() * 0.46875D;
-             d1 += d5;
+-            d1 += d5;
 -            EnumDirection enumdirection = this.direction.f();
-+            EnumDirection enumdirection = direction.f();
++    // CraftBukkit start - break out BB calc into own method
++    public static AxisAlignedBB calculateBoundingBox(Entity entity, BlockPosition blockPosition, EnumDirection direction, int width, int height) {
++        double d0 = (double) blockPosition.getX() + 0.5D;
++        double d1 = (double) blockPosition.getY() + 0.5D;
++        double d2 = (double) blockPosition.getZ() + 0.5D;
++        double d3 = 0.46875D;
++        double d4 = width;
++        double d5 = height;
++
++        d0 -= (double) direction.getAdjacentX() * 0.46875D;
++        d2 -= (double) direction.getAdjacentZ() * 0.46875D;
++        d1 += d5;
++        EnumDirection enumdirection = direction.f();
++
++        d0 += d4 * (double) enumdirection.getAdjacentX();
++        d2 += d4 * (double) enumdirection.getAdjacentZ();
++
++        double d6 = (double) width;
++        double d7 = (double) height;
++        double d8 = (double) width;
  
-             d0 += d4 * (double) enumdirection.getAdjacentX();
-             d2 += d4 * (double) enumdirection.getAdjacentZ();
+-            d0 += d4 * (double) enumdirection.getAdjacentX();
+-            d2 += d4 * (double) enumdirection.getAdjacentZ();
 -            this.locX = d0;
 -            this.locY = d1;
 -            this.locZ = d2;
 -            double d6 = (double) this.getWidth();
 -            double d7 = (double) this.getHeight();
 -            double d8 = (double) this.getWidth();
-+        if (entity != null) {
-+            entity.locX = d0;
-+            entity.locY = d1;
-+            entity.locZ = d2;
-+        }
-+            double d6 = (double) width;
-+            double d7 = (double) height;
-+            double d8 = (double) width;
- 
+-
 -            if (this.direction.k() == EnumDirection.EnumAxis.Z) {
-+            if (direction.k() == EnumDirection.EnumAxis.Z) {
-                 d8 = 1.0D;
-             } else {
-                 d6 = 1.0D;
-@@ -72,11 +86,18 @@
-             d6 /= 32.0D;
-             d7 /= 32.0D;
-             d8 /= 32.0D;
+-                d8 = 1.0D;
+-            } else {
+-                d6 = 1.0D;
+-            }
++        if (direction.k() == EnumDirection.EnumAxis.Z) {
++            d8 = 1.0D;
++        } else {
++            d6 = 1.0D;
++        }
+ 
+-            d6 /= 32.0D;
+-            d7 /= 32.0D;
+-            d8 /= 32.0D;
 -            this.a(new AxisAlignedBB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8));
-+            return new AxisAlignedBB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8);
++        d6 /= 32.0D;
++        d7 /= 32.0D;
++        d8 /= 32.0D;
++        return new AxisAlignedBB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8);
 +    }
 +
 +    protected void updateBoundingBox() {
@@ -85,12 +88,7 @@
          }
      }
  
--    private double a(int i) {
-+    private static double a(int i) {
-         return i % 32 == 0 ? 0.5D : 0.0D;
-     }
- 
-@@ -87,6 +108,24 @@
+@@ -88,6 +98,24 @@
          if (this.d++ == 100 && !this.world.isClientSide) {
              this.d = 0;
              if (!this.dead && !this.survives()) {
@@ -115,7 +113,7 @@
                  this.die();
                  this.a((Entity) null);
              }
-@@ -137,6 +176,21 @@
+@@ -140,6 +168,21 @@
              return false;
          } else {
              if (!this.dead && !this.world.isClientSide) {
@@ -135,9 +133,9 @@
 +                // CraftBukkit end
 +
                  this.die();
-                 this.ao();
+                 this.ap();
                  this.a(damagesource.getEntity());
-@@ -148,6 +202,18 @@
+@@ -151,6 +194,18 @@
  
      public void move(double d0, double d1, double d2) {
          if (!this.world.isClientSide && !this.dead && d0 * d0 + d1 * d1 + d2 * d2 > 0.0D) {
@@ -156,7 +154,7 @@
              this.die();
              this.a((Entity) null);
          }
-@@ -155,7 +221,7 @@
+@@ -158,7 +213,7 @@
      }
  
      public void g(double d0, double d1, double d2) {
diff --git a/nms-patches/EntityHorse.patch b/nms-patches/EntityHorse.patch
index 0e047ddce6..b8d8829ff3 100644
--- a/nms-patches/EntityHorse.patch
+++ b/nms-patches/EntityHorse.patch
@@ -8,25 +8,25 @@
 +
  public class EntityHorse extends EntityAnimal implements IInventoryListener, IJumpable {
  
-     private static final Predicate<Entity> bC = new Predicate() {
-@@ -53,6 +55,7 @@
-     private String ce;
-     private String[] cf = new String[3];
-     private boolean cg = false;
+     private static final Predicate<Entity> bD = new Predicate() {
+@@ -52,6 +54,7 @@
+     private int ce;
+     private String cf;
+     private final String[] cg = new String[3];
 +    public int maxDomestication = 100; // CraftBukkit - store max domestication value
  
      public EntityHorse(World world) {
          super(world);
-@@ -321,7 +324,7 @@
+@@ -320,7 +323,7 @@
      public void loadChest() {
          InventoryHorseChest inventoryhorsechest = this.inventoryChest;
  
--        this.inventoryChest = new InventoryHorseChest("HorseChest", this.dJ());
-+        this.inventoryChest = new InventoryHorseChest("HorseChest", this.dJ(), this); // CraftBukkit
+-        this.inventoryChest = new InventoryHorseChest("HorseChest", this.dN());
++        this.inventoryChest = new InventoryHorseChest("HorseChest", this.dN(), this); // CraftBukkit
          this.inventoryChest.a(this.getName());
          if (inventoryhorsechest != null) {
              inventoryhorsechest.b(this);
-@@ -474,7 +477,7 @@
+@@ -473,7 +476,7 @@
      }
  
      public int getMaxDomestication() {
@@ -34,8 +34,8 @@
 +        return this.maxDomestication; // CraftBukkit - return stored max domestication instead of 100
      }
  
-     protected float ce() {
-@@ -564,7 +567,7 @@
+     protected float ch() {
+@@ -563,7 +566,7 @@
                      }
  
                      if (this.getHealth() < this.getMaxHealth() && f > 0.0F) {
@@ -44,7 +44,7 @@
                          flag = true;
                      }
  
-@@ -655,11 +658,11 @@
+@@ -654,11 +657,11 @@
      }
  
      public void die(DamageSource damagesource) {
@@ -58,7 +58,7 @@
      }
  
      public void n() {
-@@ -670,7 +673,7 @@
+@@ -669,7 +672,7 @@
          super.n();
          if (!this.world.isClientSide) {
              if (this.random.nextInt(900) == 0 && this.deathTicks == 0) {
@@ -66,8 +66,8 @@
 +                this.heal(1.0F, RegainReason.REGEN); // CraftBukkit
              }
  
-             if (!this.dn() && !this.isVehicle() && this.random.nextInt(300) == 0 && this.world.getType(new BlockPosition(MathHelper.floor(this.locX), MathHelper.floor(this.locY) - 1, MathHelper.floor(this.locZ))).getBlock() == Blocks.GRASS) {
-@@ -921,6 +924,7 @@
+             if (!this.dr() && !this.isVehicle() && this.random.nextInt(300) == 0 && this.world.getType(new BlockPosition(MathHelper.floor(this.locX), MathHelper.floor(this.locY) - 1, MathHelper.floor(this.locZ))).getBlock() == Blocks.GRASS) {
+@@ -929,6 +932,7 @@
          if (this.getOwnerUUID() != null) {
              nbttagcompound.setString("OwnerUUID", this.getOwnerUUID().toString());
          }
@@ -75,7 +75,7 @@
  
          if (this.hasChest()) {
              NBTTagList nbttaglist = new NBTTagList();
-@@ -976,6 +980,12 @@
+@@ -984,6 +988,12 @@
              this.setOwnerUUID(UUID.fromString(s));
          }
  
@@ -88,7 +88,7 @@
          AttributeInstance attributeinstance = this.getAttributeMap().a("Speed");
  
          if (attributeinstance != null) {
-@@ -1148,6 +1158,18 @@
+@@ -1156,6 +1166,18 @@
      }
  
      public void b(int i) {
diff --git a/nms-patches/EntityHuman.patch b/nms-patches/EntityHuman.patch
index 6c5c2bbe88..e988303a0c 100644
--- a/nms-patches/EntityHuman.patch
+++ b/nms-patches/EntityHuman.patch
@@ -26,11 +26,11 @@
      public Container activeContainer;
 -    protected FoodMetaData foodData = new FoodMetaData();
 +    protected FoodMetaData foodData = new FoodMetaData(this); // CraftBukkit - add "this" to constructor
-     protected int bw;
-     public float bx;
+     protected int bx;
      public float by;
-@@ -53,6 +66,17 @@
-     private final ItemCooldown bV = this.l();
+     public float bz;
+@@ -52,6 +65,17 @@
+     private final ItemCooldown bW = this.l();
      public EntityFishingHook hookedFish;
  
 +    // CraftBukkit start
@@ -47,7 +47,7 @@
      protected ItemCooldown l() {
          return new ItemCooldown();
      }
-@@ -302,7 +326,8 @@
+@@ -307,7 +331,8 @@
  
          if (this.world.getDifficulty() == EnumDifficulty.PEACEFUL && this.world.getGameRules().getBoolean("naturalRegeneration")) {
              if (this.getHealth() < this.getMaxHealth() && this.ticksLived % 20 == 0) {
@@ -57,7 +57,7 @@
              }
  
              if (this.foodData.c() && this.ticksLived % 10 == 0) {
-@@ -326,7 +351,7 @@
+@@ -331,7 +356,7 @@
  
          this.l((float) attributeinstance.getValue());
          float f = MathHelper.sqrt(this.motX * this.motX + this.motZ * this.motZ);
@@ -66,7 +66,7 @@
  
          if (f > 0.1F) {
              f = 0.1F;
-@@ -417,30 +442,36 @@
+@@ -423,28 +448,34 @@
      public void b(Entity entity, int i) {
          if (entity != this) {
              this.addScore(i);
@@ -91,12 +91,10 @@
  
              while (iterator.hasNext()) {
 -                ScoreboardObjective scoreboardobjective = (ScoreboardObjective) iterator.next();
--                ScoreboardScore scoreboardscore = this.getScoreboard().getPlayerScoreForObjective(this.getName(), scoreboardobjective);
 +                // CraftBukkit start
 +                // ScoreboardObjective scoreboardobjective = (ScoreboardObjective) iterator.next();
-+                // ScoreboardScore scoreboardscore = this.getScoreboard().getPlayerScoreForObjective(this.getName(), scoreboardobjective);
  
--                scoreboardscore.incrementScore();
+-                this.getScoreboard().getPlayerScoreForObjective(this.getName(), scoreboardobjective).incrementScore();
 +                iterator.next().incrementScore();
 +                // CraftBukkit end
              }
@@ -105,13 +103,11 @@
      }
  
 -    private Collection<ScoreboardObjective> d(Entity entity) {
--        String s = entity instanceof EntityHuman ? entity.getName() : entity.bd();
 +    private Collection<ScoreboardScore> d(Entity entity) { // CraftBukkit
-+        String s = entity instanceof EntityHuman ? entity.getName() : entity.getUniqueID().toString();
+         String s = entity instanceof EntityHuman ? entity.getName() : entity.bf();
          ScoreboardTeam scoreboardteam = this.getScoreboard().getPlayerTeam(this.getName());
  
-         if (scoreboardteam != null) {
-@@ -464,7 +495,10 @@
+@@ -469,7 +500,10 @@
              int j = scoreboardteam1.m().b();
  
              if (j >= 0 && j < IScoreboardCriteria.m.length) {
@@ -123,7 +119,7 @@
              }
          }
  
-@@ -473,6 +507,7 @@
+@@ -478,6 +512,7 @@
  
      @Nullable
      public EntityItem a(boolean flag) {
@@ -131,7 +127,7 @@
          return this.a(this.inventory.splitStack(this.inventory.itemInHandIndex, flag && this.inventory.getItemInHand() != null ? this.inventory.getItemInHand().count : 1), false, true);
      }
  
-@@ -517,6 +552,30 @@
+@@ -522,6 +557,30 @@
                  entityitem.motZ += Math.sin((double) f1) * (double) f;
              }
  
@@ -162,7 +158,7 @@
              ItemStack itemstack1 = this.a(entityitem);
  
              if (flag1) {
-@@ -615,6 +674,13 @@
+@@ -630,6 +689,13 @@
              this.a(true, true, false);
          }
  
@@ -176,7 +172,7 @@
          if (nbttagcompound.hasKeyOfType("SpawnX", 99) && nbttagcompound.hasKeyOfType("SpawnY", 99) && nbttagcompound.hasKeyOfType("SpawnZ", 99)) {
              this.e = new BlockPosition(nbttagcompound.getInt("SpawnX"), nbttagcompound.getInt("SpawnY"), nbttagcompound.getInt("SpawnZ"));
              this.f = nbttagcompound.getBoolean("SpawnForced");
-@@ -652,6 +718,12 @@
+@@ -667,6 +733,12 @@
          this.foodData.b(nbttagcompound);
          this.abilities.a(nbttagcompound);
          nbttagcompound.set("EnderItems", this.enderChest.h());
@@ -189,7 +185,7 @@
      }
  
      public boolean damageEntity(DamageSource damagesource, float f) {
-@@ -670,7 +742,7 @@
+@@ -685,7 +757,7 @@
  
                  if (damagesource.r()) {
                      if (this.world.getDifficulty() == EnumDifficulty.PEACEFUL) {
@@ -198,21 +194,19 @@
                      }
  
                      if (this.world.getDifficulty() == EnumDifficulty.EASY) {
-@@ -682,7 +754,7 @@
+@@ -697,16 +769,35 @@
                      }
                  }
  
--                if (f == 0.0F) {
-+                if (false && f == 0.0F) { // CraftBukkit - Don't filter out 0 damage
-                     return false;
-                 } else {
-                     Entity entity = damagesource.getEntity();
-@@ -698,10 +770,29 @@
+-                return f == 0.0F ? false : super.damageEntity(damagesource, f);
++                return super.damageEntity(damagesource, f); // CraftBukkit - Don't filter out 0 damage
+             }
+         }
      }
  
      public boolean a(EntityHuman entityhuman) {
--        ScoreboardTeamBase scoreboardteambase = this.aO();
--        ScoreboardTeamBase scoreboardteambase1 = entityhuman.aO();
+-        ScoreboardTeamBase scoreboardteambase = this.aQ();
+-        ScoreboardTeamBase scoreboardteambase1 = entityhuman.aQ();
 +        // CraftBukkit start - Change to check OTHER player's scoreboard team according to API
 +        // To summarize this method's logic, it's "Can parameter hurt this"
 +        org.bukkit.scoreboard.Team team;
@@ -240,7 +234,7 @@
      }
  
      protected void damageArmor(float f) {
-@@ -745,7 +836,12 @@
+@@ -750,7 +841,12 @@
          return (float) i / (float) this.inventory.armor.length;
      }
  
@@ -254,7 +248,7 @@
          if (!this.isInvulnerable(damagesource)) {
              f = this.applyArmorModifier(damagesource, f);
              f = this.applyMagicModifier(damagesource, f);
-@@ -765,6 +861,7 @@
+@@ -770,6 +866,7 @@
  
              }
          }
@@ -262,7 +256,7 @@
      }
  
      public void openSign(TileEntitySign tileentitysign) {}
-@@ -887,8 +984,15 @@
+@@ -894,8 +991,15 @@
                      if (entity instanceof EntityLiving) {
                          f3 = ((EntityLiving) entity).getHealth();
                          if (j > 0 && !entity.isBurning()) {
@@ -280,7 +274,7 @@
                          }
                      }
  
-@@ -918,8 +1022,11 @@
+@@ -925,8 +1029,11 @@
                                  EntityLiving entityliving = (EntityLiving) iterator.next();
  
                                  if (entityliving != this && entityliving != entity && !this.r(entityliving) && this.h(entityliving) < 9.0D) {
@@ -293,7 +287,7 @@
                                  }
                              }
  
-@@ -928,11 +1035,28 @@
+@@ -935,11 +1042,28 @@
                          }
  
                          if (entity instanceof EntityPlayer && entity.velocityChanged) {
@@ -322,7 +316,7 @@
                          }
  
                          if (flag2) {
-@@ -994,7 +1118,8 @@
+@@ -1001,7 +1125,8 @@
  
                          if (itemstack3 != null && object instanceof EntityLiving) {
                              itemstack3.a((EntityLiving) object, this);
@@ -332,7 +326,7 @@
                                  this.a(EnumHand.MAIN_HAND, (ItemStack) null);
                              }
                          }
-@@ -1004,7 +1129,14 @@
+@@ -1011,7 +1136,14 @@
  
                              this.a(StatisticList.y, Math.round(f5 * 10.0F));
                              if (j > 0) {
@@ -348,7 +342,7 @@
                              }
  
                              if (this.world instanceof WorldServer && f5 > 2.0F) {
-@@ -1093,6 +1225,20 @@
+@@ -1100,6 +1232,20 @@
              this.stopRiding();
          }
  
@@ -369,7 +363,7 @@
          this.setSize(0.2F, 0.2F);
          if (this.world.isLoaded(blockposition)) {
              EnumDirection enumdirection = (EnumDirection) this.world.getType(blockposition).get(BlockFacingHorizontal.FACING);
-@@ -1175,6 +1321,23 @@
+@@ -1184,6 +1330,23 @@
              this.world.everyoneSleeping();
          }
  
@@ -393,7 +387,7 @@
          this.sleepTicks = flag ? 0 : 100;
          if (flag2) {
              this.setRespawnPosition(this.bedPosition, false);
-@@ -1226,9 +1389,11 @@
+@@ -1235,9 +1398,11 @@
          if (blockposition != null) {
              this.e = blockposition;
              this.f = flag;
diff --git a/nms-patches/EntityInsentient.patch b/nms-patches/EntityInsentient.patch
index 832a598c5a..5cbb4fe442 100644
--- a/nms-patches/EntityInsentient.patch
+++ b/nms-patches/EntityInsentient.patch
@@ -16,7 +16,7 @@
  public abstract class EntityInsentient extends EntityLiving {
  
      private static final DataWatcherObject<Byte> a = DataWatcher.a(EntityInsentient.class, DataWatcherRegistry.a);
-@@ -61,6 +70,9 @@
+@@ -52,6 +61,9 @@
              this.r();
          }
  
@@ -26,20 +26,20 @@
      }
  
      protected void r() {}
-@@ -75,9 +87,10 @@
+@@ -66,9 +78,10 @@
      }
  
      public float a(PathType pathtype) {
--        Float float = (Float) this.bA.get(pathtype);
+-        Float float = (Float) this.bB.get(pathtype);
 +        // CraftBukkit - decompile error
-+        Float ofloat = (Float) this.bA.get(pathtype);
++        Float ofloat = (Float) this.bB.get(pathtype);
  
 -        return float == null ? pathtype.a() : float.floatValue();
 +        return ofloat == null ? pathtype.a() : ofloat.floatValue();
      }
  
      public void a(PathType pathtype, float f) {
-@@ -114,7 +127,38 @@
+@@ -105,7 +118,38 @@
      }
  
      public void setGoalTarget(@Nullable EntityLiving entityliving) {
@@ -78,14 +78,14 @@
      }
  
      public boolean d(Class<? extends EntityLiving> oclass) {
-@@ -327,11 +371,20 @@
+@@ -350,11 +394,20 @@
  
      public void a(NBTTagCompound nbttagcompound) {
          super.a(nbttagcompound);
 +
 +        // CraftBukkit start - If looting or persistence is false only use it if it was set after we started using it
          if (nbttagcompound.hasKeyOfType("CanPickUpLoot", 1)) {
--            this.l(nbttagcompound.getBoolean("CanPickUpLoot"));
+-            this.m(nbttagcompound.getBoolean("CanPickUpLoot"));
 +            boolean data = nbttagcompound.getBoolean("CanPickUpLoot");
 +            if (isLevelAtLeast(nbttagcompound, 1) || data) {
 +                this.l(data);
@@ -101,7 +101,7 @@
          NBTTagList nbttaglist;
          int i;
  
-@@ -556,11 +609,11 @@
+@@ -579,11 +632,11 @@
                  double d2 = entityhuman.locZ - this.locZ;
                  double d3 = d0 * d0 + d1 * d1 + d2 * d2;
  
@@ -115,7 +115,7 @@
                      this.die();
                  } else if (d3 < 1024.0D) {
                      this.ticksFarFromPlayer = 0;
-@@ -940,9 +993,21 @@
+@@ -965,9 +1018,21 @@
  
      public final boolean a(EntityHuman entityhuman, @Nullable ItemStack itemstack, EnumHand enumhand) {
          if (this.isLeashed() && this.getLeashHolder() == entityhuman) {
@@ -137,9 +137,9 @@
              this.setLeashHolder(entityhuman, true);
              --itemstack.count;
              return true;
-@@ -962,10 +1027,12 @@
+@@ -987,10 +1052,12 @@
  
-         if (this.bD) {
+         if (this.bE) {
              if (!this.isAlive()) {
 +                this.world.getServer().getPluginManager().callEvent(new EntityUnleashEvent(this.getBukkitEntity(), UnleashReason.PLAYER_UNLEASH)); // CraftBukkit
                  this.unleash(true, true);
@@ -150,8 +150,8 @@
                  this.unleash(true, true);
              }
          }
-@@ -976,7 +1043,9 @@
-             this.bD = false;
+@@ -1001,7 +1068,9 @@
+             this.bE = false;
              this.leashHolder = null;
              if (!this.world.isClientSide && flag1) {
 +                this.forceDrops = true; // CraftBukkit
@@ -160,7 +160,7 @@
              }
  
              if (!this.world.isClientSide && flag && this.world instanceof WorldServer) {
-@@ -1046,6 +1115,7 @@
+@@ -1071,6 +1140,7 @@
  
                  this.leashHolder = entityleash;
              } else {
diff --git a/nms-patches/EntityItem.patch b/nms-patches/EntityItem.patch
index 2c8a05d753..7fbea393b3 100644
--- a/nms-patches/EntityItem.patch
+++ b/nms-patches/EntityItem.patch
@@ -44,7 +44,7 @@
  
              this.lastX = this.locX;
              this.lastY = this.locY;
-@@ -93,12 +103,20 @@
+@@ -96,12 +106,20 @@
                  this.motY *= -0.5D;
              }
  
@@ -54,7 +54,7 @@
              }
 +            // Craftbukkit end */
  
-             this.aj();
+             this.ak();
              if (!this.world.isClientSide && this.age >= 6000) {
 +                // CraftBukkit start - fire ItemDespawnEvent
 +                if (org.bukkit.craftbukkit.event.CraftEventFactory.callItemDespawnEvent(this).isCancelled()) {
@@ -65,7 +65,7 @@
                  this.die();
              }
  
-@@ -140,6 +158,7 @@
+@@ -143,6 +161,7 @@
                      } else if (itemstack1.count + itemstack.count > itemstack1.getMaxStackSize()) {
                          return false;
                      } else {
@@ -73,7 +73,7 @@
                          itemstack1.count += itemstack.count;
                          entityitem.pickupDelay = Math.max(entityitem.pickupDelay, this.pickupDelay);
                          entityitem.age = Math.min(entityitem.age, this.age);
-@@ -186,6 +205,11 @@
+@@ -189,6 +208,11 @@
          } else if (this.getItemStack() != null && this.getItemStack().getItem() == Items.NETHER_STAR && damagesource.isExplosion()) {
              return false;
          } else {
@@ -82,10 +82,10 @@
 +                return false;
 +            }
 +            // CraftBukkit end
-             this.ao();
+             this.ap();
              this.f = (int) ((float) this.f - f);
              if (this.f <= 0) {
-@@ -231,7 +255,18 @@
+@@ -238,7 +262,18 @@
  
          NBTTagCompound nbttagcompound1 = nbttagcompound.getCompound("Item");
  
@@ -105,7 +105,7 @@
          if (this.getItemStack() == null) {
              this.die();
          }
-@@ -243,6 +278,26 @@
+@@ -250,6 +285,26 @@
              ItemStack itemstack = this.getItemStack();
              int i = itemstack.count;
  
diff --git a/nms-patches/EntityItemFrame.patch b/nms-patches/EntityItemFrame.patch
index a6450f8c70..c98af2f284 100644
--- a/nms-patches/EntityItemFrame.patch
+++ b/nms-patches/EntityItemFrame.patch
@@ -10,5 +10,5 @@
 +                }
 +                // CraftBukkit end
                  this.b(damagesource.getEntity(), false);
-                 this.a(SoundEffects.cS, 1.0F, 1.0F);
+                 this.a(SoundEffects.cX, 1.0F, 1.0F);
                  this.setItem((ItemStack) null);
diff --git a/nms-patches/EntityLargeFireball.patch b/nms-patches/EntityLargeFireball.patch
index 09d2680bc9..0fed3d4c2b 100644
--- a/nms-patches/EntityLargeFireball.patch
+++ b/nms-patches/EntityLargeFireball.patch
@@ -25,7 +25,7 @@
              this.die();
          }
  
-@@ -35,7 +45,8 @@
+@@ -39,7 +49,8 @@
      public void a(NBTTagCompound nbttagcompound) {
          super.a(nbttagcompound);
          if (nbttagcompound.hasKeyOfType("ExplosionPower", 99)) {
diff --git a/nms-patches/EntityLeash.patch b/nms-patches/EntityLeash.patch
index 9d251bda9a..bea9f62f72 100644
--- a/nms-patches/EntityLeash.patch
+++ b/nms-patches/EntityLeash.patch
@@ -33,7 +33,7 @@
 +                // CraftBukkit end
 +                if (true || entityhuman.abilities.canInstantlyBuild) { // CraftBukkit - Process for non-creative as well
                      d0 = 7.0D;
-                     list = this.world.a(EntityInsentient.class, new AxisAlignedBB(this.locX - d0, this.locY - d0, this.locZ - d0, this.locX + d0, this.locY + d0, this.locZ + d0));
+                     list = this.world.a(EntityInsentient.class, new AxisAlignedBB(this.locX - 7.0D, this.locY - 7.0D, this.locZ - 7.0D, this.locX + 7.0D, this.locY + 7.0D, this.locZ + 7.0D));
                      iterator = list.iterator();
 @@ -90,9 +101,20 @@
                      while (iterator.hasNext()) {
diff --git a/nms-patches/EntityLightning.patch b/nms-patches/EntityLightning.patch
index 560ab8d63c..b686086c39 100644
--- a/nms-patches/EntityLightning.patch
+++ b/nms-patches/EntityLightning.patch
@@ -49,9 +49,9 @@
      public void m() {
          super.m();
          if (this.lifeTicks == 2) {
--            this.world.a((EntityHuman) null, this.locX, this.locY, this.locZ, SoundEffects.di, SoundCategory.WEATHER, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F);
+-            this.world.a((EntityHuman) null, this.locX, this.locY, this.locZ, SoundEffects.dn, SoundCategory.WEATHER, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F);
 +            // CraftBukkit start - Use relative location for far away sounds
-+            // this.world.a((EntityHuman) null, this.locX, this.locY, this.locZ, SoundEffects.dc, SoundCategory.d, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F);
++            // this.world.a((EntityHuman) null, this.locX, this.locY, this.locZ, SoundEffects.dn, SoundCategory.WEATHER, 10000.0F, 0.8F + this.random.nextFloat() * 0.2F);
 +            float pitch = 0.8F + this.random.nextFloat() * 0.2F;
 +            int viewDistance = ((WorldServer) this.world).getServer().getViewDistance() * 16;
 +            for (EntityPlayer player : (List<EntityPlayer>) (List) this.world.players) {
@@ -62,13 +62,13 @@
 +                    double deltaLength = Math.sqrt(distanceSquared);
 +                    double relativeX = player.locX + (deltaX / deltaLength) * viewDistance;
 +                    double relativeZ = player.locZ + (deltaZ / deltaLength) * viewDistance;
-+                    player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.di, SoundCategory.WEATHER, relativeX, this.locY, relativeZ, 10000.0F, pitch));
++                    player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.dn, SoundCategory.WEATHER, relativeX, this.locY, relativeZ, 10000.0F, pitch));
 +                } else {
-+                    player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.di, SoundCategory.WEATHER, this.locX, this.locY, this.locZ, 10000.0F, pitch));
++                    player.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.dn, SoundCategory.WEATHER, this.locX, this.locY, this.locZ, 10000.0F, pitch));
 +                }
 +            }
 +            // CraftBukkit end
-             this.world.a((EntityHuman) null, this.locX, this.locY, this.locZ, SoundEffects.dh, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F);
+             this.world.a((EntityHuman) null, this.locX, this.locY, this.locZ, SoundEffects.dm, SoundCategory.WEATHER, 2.0F, 0.5F + this.random.nextFloat() * 0.2F);
          }
  
 @@ -57,13 +86,17 @@
diff --git a/nms-patches/EntityLiving.patch b/nms-patches/EntityLiving.patch
index a9d111ae9c..e98c137c56 100644
--- a/nms-patches/EntityLiving.patch
+++ b/nms-patches/EntityLiving.patch
@@ -23,10 +23,10 @@
  public abstract class EntityLiving extends Entity {
  
      private static final UUID a = UUID.fromString("662A6B8D-DA3E-4C1C-8813-96EA6097278D");
-@@ -81,6 +97,14 @@
-     protected int bo;
-     protected int bp;
-     private BlockPosition bD;
+@@ -83,6 +99,14 @@
+     private BlockPosition bE;
+     private DamageSource bF;
+     private long bG;
 +    // CraftBukkit start
 +    public int expToDrop;
 +    public int maxAirTicks = 300;
@@ -38,7 +38,7 @@
  
      public void Q() {
          this.damageEntity(DamageSource.OUT_OF_WORLD, Float.MAX_VALUE);
-@@ -89,7 +113,8 @@
+@@ -91,7 +115,8 @@
      public EntityLiving(World world) {
          super(world);
          this.initAttributes();
@@ -46,9 +46,9 @@
 +        // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor
 +        this.datawatcher.set(EntityLiving.HEALTH, (float) this.getAttributeInstance(GenericAttributes.maxHealth).getValue());
          this.i = true;
-         this.aM = (float) ((Math.random() + 1.0D) * 0.009999999776482582D);
+         this.aN = (float) ((Math.random() + 1.0D) * 0.009999999776482582D);
          this.setPosition(this.locX, this.locY, this.locZ);
-@@ -127,7 +152,13 @@
+@@ -129,7 +154,13 @@
                  double d1 = Math.min((double) (0.2F + f / 15.0F), 2.5D);
                  int i = (int) (150.0D * d1);
  
@@ -63,7 +63,7 @@
              }
          }
  
-@@ -189,7 +220,11 @@
+@@ -191,7 +222,11 @@
                      this.stopRiding();
                  }
              } else {
@@ -76,7 +76,7 @@
              }
  
              if (!this.world.isClientSide) {
-@@ -246,6 +281,18 @@
+@@ -248,6 +283,18 @@
          this.world.methodProfiler.b();
      }
  
@@ -95,9 +95,9 @@
      protected void b(BlockPosition blockposition) {
          int i = EnchantmentManager.a(Enchantments.j, this);
  
-@@ -261,19 +308,19 @@
+@@ -263,19 +310,19 @@
  
-     protected void bD() {
+     protected void bF() {
          ++this.deathTicks;
 -        if (this.deathTicks == 20) {
 +        if (this.deathTicks >= 20 && !this.dead) { // CraftBukkit - (this.deathTicks == 20) -> (this.deathTicks >= 20 && !this.dead)
@@ -124,7 +124,7 @@
  
              this.die();
  
-@@ -427,6 +474,17 @@
+@@ -430,6 +477,17 @@
              }
          }
  
@@ -132,9 +132,9 @@
 +        if (nbttagcompound.hasKey("Bukkit.MaxHealth")) {
 +            NBTBase nbtbase = nbttagcompound.get("Bukkit.MaxHealth");
 +            if (nbtbase.getTypeId() == 5) {
-+                this.getAttributeInstance(GenericAttributes.maxHealth).setValue((double) ((NBTTagFloat) nbtbase).c());
++                this.getAttributeInstance(GenericAttributes.maxHealth).setValue(((NBTTagFloat) nbtbase).h()); // PAIL: rename
 +            } else if (nbtbase.getTypeId() == 3) {
-+                this.getAttributeInstance(GenericAttributes.maxHealth).setValue((double) ((NBTTagInt) nbtbase).d());
++                this.getAttributeInstance(GenericAttributes.maxHealth).setValue(((NBTTagInt) nbtbase).h()); // PAIL: rename
 +            }
 +        }
 +        // CraftBukkit end
@@ -142,7 +142,7 @@
          if (nbttagcompound.hasKeyOfType("Health", 99)) {
              this.setHealth(nbttagcompound.getFloat("Health"));
          }
-@@ -442,9 +500,15 @@
+@@ -449,9 +507,15 @@
  
      }
  
@@ -158,7 +158,7 @@
          while (iterator.hasNext()) {
              MobEffectList mobeffectlist = (MobEffectList) iterator.next();
              MobEffect mobeffect = (MobEffect) this.effects.get(mobeffectlist);
-@@ -458,6 +522,16 @@
+@@ -465,6 +529,16 @@
                  this.a(mobeffect, false);
              }
          }
@@ -175,7 +175,7 @@
  
          if (this.updateEffects) {
              if (!this.world.isClientSide) {
-@@ -555,6 +629,12 @@
+@@ -562,6 +636,12 @@
      }
  
      public void addEffect(MobEffect mobeffect) {
@@ -188,7 +188,7 @@
          if (this.d(mobeffect)) {
              MobEffect mobeffect1 = (MobEffect) this.effects.get(mobeffect.getMobEffect());
  
-@@ -587,6 +667,12 @@
+@@ -594,6 +674,12 @@
  
      @Nullable
      public MobEffect c(@Nullable MobEffectList mobeffectlist) {
@@ -201,7 +201,7 @@
          return (MobEffect) this.effects.remove(mobeffectlist);
      }
  
-@@ -626,20 +712,52 @@
+@@ -633,20 +719,52 @@
  
      }
  
@@ -255,7 +255,7 @@
          this.datawatcher.set(EntityLiving.HEALTH, Float.valueOf(MathHelper.a(f, 0.0F, this.getMaxHealth())));
      }
  
-@@ -655,14 +773,16 @@
+@@ -662,14 +780,16 @@
              } else if (damagesource.o() && this.hasEffect(MobEffects.FIRE_RESISTANCE)) {
                  return false;
              } else {
@@ -275,7 +275,7 @@
                      this.k(f);
                      if (damagesource.a()) {
                          f = 0.0F;
-@@ -681,19 +801,38 @@
+@@ -688,20 +808,39 @@
  
                  if ((float) this.noDamageTicks > (float) this.maxNoDamageTicks / 2.0F) {
                      if (f <= this.lastDamage) {
@@ -301,7 +301,8 @@
 -                    this.damageEntity0(damagesource, f);
 +                    // this.damageEntity0(damagesource, f);
 +                    // CraftBukkit end
-                     this.hurtTicks = this.az = 10;
+                     this.aA = 10;
+                     this.hurtTicks = this.aA;
                  }
  
 +                // CraftBukkit start
@@ -313,10 +314,10 @@
 +                }
 +                // CraftBukkit end
 +
-                 this.aA = 0.0F;
+                 this.aB = 0.0F;
                  Entity entity = damagesource.getEntity();
  
-@@ -833,6 +972,12 @@
+@@ -855,6 +994,12 @@
                      boolean flag = this.lastDamageByPlayerTime > 0;
  
                      this.a(flag, i, damagesource);
@@ -329,7 +330,7 @@
                  }
              }
  
-@@ -922,8 +1067,13 @@
+@@ -944,8 +1089,13 @@
          int i = MathHelper.f((f - 3.0F - f2) * f1);
  
          if (i > 0) {
@@ -344,7 +345,7 @@
              int j = MathHelper.floor(this.locX);
              int k = MathHelper.floor(this.locY - 0.20000000298023224D);
              int l = MathHelper.floor(this.locZ);
-@@ -950,8 +1100,8 @@
+@@ -972,8 +1122,8 @@
  
      protected float applyArmorModifier(DamageSource damagesource, float f) {
          if (!damagesource.ignoresArmor()) {
@@ -355,7 +356,7 @@
          }
  
          return f;
-@@ -963,7 +1113,8 @@
+@@ -985,7 +1135,8 @@
          } else {
              int i;
  
@@ -365,7 +366,7 @@
                  i = (this.getEffect(MobEffects.RESISTANCE).getAmplifier() + 1) * 5;
                  int j = 25 - i;
                  float f1 = f * (float) j;
-@@ -984,22 +1135,127 @@
+@@ -1006,22 +1157,127 @@
          }
      }
  
@@ -503,15 +504,15 @@
      }
  
      public CombatTracker getCombatTracker() {
-@@ -1065,6 +1321,7 @@
+@@ -1088,6 +1344,7 @@
      public AttributeMapBase getAttributeMap() {
-         if (this.bq == null) {
-             this.bq = new AttributeMapServer();
-+            this.craftAttributes = new CraftAttributeMap(bq); // CraftBukkit
+         if (this.br == null) {
+             this.br = new AttributeMapServer();
++            this.craftAttributes = new CraftAttributeMap(br); // CraftBukkit // PAIL: rename
          }
  
-         return this.bq;
-@@ -1343,6 +1600,7 @@
+         return this.br;
+@@ -1376,6 +1633,7 @@
                  }
  
                  if (this.onGround && !this.world.isClientSide) {
@@ -519,7 +520,7 @@
                      this.setFlag(7, false);
                  }
              } else {
-@@ -1703,6 +1961,7 @@
+@@ -1736,6 +1994,7 @@
          }
  
          if (!this.world.isClientSide) {
@@ -527,7 +528,7 @@
              this.setFlag(7, flag);
          }
  
-@@ -1716,6 +1975,13 @@
+@@ -1749,6 +2008,13 @@
          if (!list.isEmpty()) {
              for (int i = 0; i < list.size(); ++i) {
                  Entity entity = (Entity) list.get(i);
@@ -541,7 +542,7 @@
  
                  this.C(entity);
              }
-@@ -1791,11 +2057,11 @@
+@@ -1824,11 +2090,11 @@
      }
  
      public boolean isInteractable() {
@@ -554,14 +555,14 @@
 +        return !this.dead && this.collides; // CraftBukkit
      }
  
-     protected void ao() {
-@@ -1932,7 +2198,22 @@
+     protected void ap() {
+@@ -1965,7 +2231,22 @@
      protected void v() {
-         if (this.bn != null && this.ct()) {
-             this.a(this.bn, 16);
--            ItemStack itemstack = this.bn.a(this.world, this);
+         if (this.bo != null && this.cx()) {
+             this.a(this.bo, 16);
+-            ItemStack itemstack = this.bo.a(this.world, this);
 +            // CraftBukkit start - fire PlayerItemConsumeEvent
-+            org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.bn); // PAIL: rename
++            org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.bo); // PAIL: rename
 +            PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem);
 +            world.getServer().getPluginManager().callEvent(event);
 +
@@ -574,12 +575,12 @@
 +                return;
 +            }
 +
-+            ItemStack itemstack = (craftItem.equals(event.getItem())) ? this.bn.a(this.world, this) : CraftItemStack.asNMSCopy(event.getItem()).a(world, this);
++            ItemStack itemstack = (craftItem.equals(event.getItem())) ? this.bo.a(this.world, this) : CraftItemStack.asNMSCopy(event.getItem()).a(world, this);
 +            // CraftBukkit end
  
              if (itemstack != null && itemstack.count == 0) {
                  itemstack = null;
-@@ -2017,7 +2298,17 @@
+@@ -2051,7 +2332,17 @@
              }
  
              if (flag1) {
diff --git a/nms-patches/EntityMinecartAbstract.patch b/nms-patches/EntityMinecartAbstract.patch
index 8b95934884..835b05a38a 100644
--- a/nms-patches/EntityMinecartAbstract.patch
+++ b/nms-patches/EntityMinecartAbstract.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/EntityMinecartAbstract.java
 +++ b/net/minecraft/server/EntityMinecartAbstract.java
-@@ -5,6 +5,15 @@
+@@ -6,6 +6,15 @@
  import java.util.Map;
  import javax.annotation.Nullable;
  
@@ -16,9 +16,9 @@
  public abstract class EntityMinecartAbstract extends Entity implements INamableTileEntity {
  
      private static final DataWatcherObject<Integer> a = DataWatcher.a(EntityMinecartAbstract.class, DataWatcherRegistry.b);
-@@ -22,6 +31,17 @@
-     private double ax;
+@@ -23,6 +32,17 @@
      private double ay;
+     private double az;
  
 +    // CraftBukkit start
 +    public boolean slowWhenEmpty = true;
@@ -34,7 +34,7 @@
      public EntityMinecartAbstract(World world) {
          super(world);
          this.i = true;
-@@ -89,6 +109,8 @@
+@@ -90,6 +110,8 @@
          this.lastX = d0;
          this.lastY = d1;
          this.lastZ = d2;
@@ -43,7 +43,7 @@
      }
  
      public double ay() {
-@@ -100,6 +122,19 @@
+@@ -101,6 +123,19 @@
              if (this.isInvulnerable(damagesource)) {
                  return false;
              } else {
@@ -62,8 +62,8 @@
 +                // CraftBukkit end
                  this.e(-this.u());
                  this.d(10);
-                 this.ao();
-@@ -107,6 +142,15 @@
+                 this.ap();
+@@ -108,6 +143,15 @@
                  boolean flag = damagesource.getEntity() instanceof EntityHuman && ((EntityHuman) damagesource.getEntity()).abilities.canInstantlyBuild;
  
                  if (flag || this.getDamage() > 40.0F) {
@@ -79,7 +79,7 @@
                      this.az();
                      if (flag && !this.hasCustomName()) {
                          this.die();
-@@ -149,6 +193,14 @@
+@@ -150,6 +194,14 @@
      }
  
      public void m() {
@@ -94,20 +94,19 @@
          if (this.getType() > 0) {
              this.d(this.getType() - 1);
          }
-@@ -169,7 +221,7 @@
+@@ -170,7 +222,7 @@
  
              i = this.V();
-             if (this.ak) {
+             if (this.al) {
 -                if (minecraftserver.getAllowNether()) {
 +                if (true || minecraftserver.getAllowNether()) { // CraftBukkit - multi-world should still allow teleport even if default vanilla nether disabled
-                     if (!this.isPassenger() && this.al++ >= i) {
-                         this.al = i;
-                         this.portalCooldown = this.aC();
-@@ -266,6 +318,20 @@
+                     if (!this.isPassenger() && this.am++ >= i) {
+                         this.am = i;
+                         this.portalCooldown = this.aE();
+@@ -270,6 +322,18 @@
              }
  
              this.setYawPitch(this.yaw, this.pitch);
-+
 +            // CraftBukkit start
 +            org.bukkit.World bworld = this.world.getWorld();
 +            Location from = new Location(bworld, prevX, prevY, prevZ, prevYaw, prevPitch);
@@ -120,11 +119,25 @@
 +                this.world.getServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleMoveEvent(vehicle, from, to));
 +            }
 +            // CraftBukkit end
-+
-             Iterator iterator = this.world.getEntities(this, this.getBoundingBox().grow(0.20000000298023224D, 0.0D, 0.20000000298023224D)).iterator();
+             if (this.v() == EntityMinecartAbstract.EnumMinecartType.RIDEABLE && this.motX * this.motX + this.motZ * this.motZ > 0.01D) {
+                 List list = this.world.getEntities(this, this.getBoundingBox().grow(0.20000000298023224D, 0.0D, 0.20000000298023224D), IEntitySelector.a(this));
  
-             while (iterator.hasNext()) {
-@@ -281,7 +347,7 @@
+@@ -278,6 +342,14 @@
+                         Entity entity = (Entity) list.get(l);
+ 
+                         if (!(entity instanceof EntityHuman) && !(entity instanceof EntityIronGolem) && !(entity instanceof EntityMinecartAbstract) && !this.isVehicle() && !entity.isPassenger()) {
++                            // CraftBukkit start
++                            VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, entity.getBukkitEntity());
++                            this.world.getServer().getPluginManager().callEvent(collisionEvent);
++
++                            if (collisionEvent.isCancelled()) {
++                                continue;
++                            }
++                            // CraftBukkit end
+                             entity.startRiding(this);
+                         } else {
+                             entity.collide(this);
+@@ -301,7 +373,7 @@
      }
  
      protected double o() {
@@ -133,7 +146,7 @@
      }
  
      public void a(int i, int j, int k, boolean flag) {}
-@@ -292,16 +358,20 @@
+@@ -312,16 +384,20 @@
          this.motX = MathHelper.a(this.motX, -d0, d0);
          this.motZ = MathHelper.a(this.motZ, -d0, d0);
          if (this.onGround) {
@@ -160,7 +173,7 @@
          }
  
      }
-@@ -490,7 +560,7 @@
+@@ -509,7 +585,7 @@
      }
  
      protected void r() {
@@ -169,35 +182,7 @@
              this.motX *= 0.996999979019165D;
              this.motY *= 0.0D;
              this.motZ *= 0.996999979019165D;
-@@ -602,6 +672,17 @@
-         if (!this.world.isClientSide) {
-             if (!entity.noclip && !this.noclip) {
-                 if (!this.w(entity)) {
-+                    // CraftBukkit start
-+                    Vehicle vehicle = (Vehicle) this.getBukkitEntity();
-+                    org.bukkit.entity.Entity hitEntity = (entity == null) ? null : entity.getBukkitEntity();
-+
-+                    VehicleEntityCollisionEvent collisionEvent = new VehicleEntityCollisionEvent(vehicle, hitEntity);
-+                    this.world.getServer().getPluginManager().callEvent(collisionEvent);
-+
-+                    if (collisionEvent.isCancelled()) {
-+                        return;
-+                    }
-+                    // CraftBukkit end
-                     if (entity instanceof EntityLiving && this.v() == EntityMinecartAbstract.EnumMinecartType.RIDEABLE && this.motX * this.motX + this.motZ * this.motZ > 0.01D && !(entity instanceof EntityHuman) && !(entity instanceof EntityIronGolem) && !this.isVehicle() && !entity.isPassenger()) {
-                         entity.startRiding(this);
-                     }
-@@ -610,7 +691,8 @@
-                     double d1 = entity.locZ - this.locZ;
-                     double d2 = d0 * d0 + d1 * d1;
- 
--                    if (d2 >= 9.999999747378752E-5D) {
-+                    // CraftBukkit - collision
-+                    if (d2 >= 9.999999747378752E-5D && !collisionEvent.isCollisionCancelled()) {
-                         d2 = (double) MathHelper.sqrt(d2);
-                         d0 /= d2;
-                         d1 /= d2;
-@@ -839,4 +921,26 @@
+@@ -854,4 +930,26 @@
  
          }
      }
diff --git a/nms-patches/EntityMonster.patch b/nms-patches/EntityMonster.patch
index 0a19ca7d49..5832a4dc02 100644
--- a/nms-patches/EntityMonster.patch
+++ b/nms-patches/EntityMonster.patch
@@ -8,7 +8,7 @@
  public abstract class EntityMonster extends EntityCreature implements IMonster {
  
      public EntityMonster(World world) {
-@@ -75,7 +77,14 @@
+@@ -79,7 +81,14 @@
              int j = EnchantmentManager.getFireAspectEnchantmentLevel(this);
  
              if (j > 0) {
diff --git a/nms-patches/EntityMushroomCow.patch b/nms-patches/EntityMushroomCow.patch
index 32b544d676..8a64125238 100644
--- a/nms-patches/EntityMushroomCow.patch
+++ b/nms-patches/EntityMushroomCow.patch
@@ -8,7 +8,7 @@
  
  public class EntityMushroomCow extends EntityCow {
  
-@@ -20,6 +21,14 @@
+@@ -24,6 +25,14 @@
  
              return true;
          } else if (itemstack != null && itemstack.getItem() == Items.SHEARS && this.getAge() >= 0) {
diff --git a/nms-patches/EntityOcelot.patch b/nms-patches/EntityOcelot.patch
index 69c08b9e23..7d433fa41a 100644
--- a/nms-patches/EntityOcelot.patch
+++ b/nms-patches/EntityOcelot.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/EntityOcelot.java
 +++ b/net/minecraft/server/EntityOcelot.java
-@@ -55,7 +55,7 @@
+@@ -57,7 +57,7 @@
      }
  
      protected boolean isTypeNotPersistent() {
@@ -9,7 +9,7 @@
      }
  
      protected void initAttributes() {
-@@ -97,6 +97,9 @@
+@@ -103,6 +103,9 @@
          return entity.damageEntity(DamageSource.mobAttack(this), 3.0F);
      }
  
@@ -19,7 +19,7 @@
      public boolean damageEntity(DamageSource damagesource, float f) {
          if (this.isInvulnerable(damagesource)) {
              return false;
-@@ -108,6 +111,7 @@
+@@ -114,6 +117,7 @@
              return super.damageEntity(damagesource, f);
          }
      }
@@ -27,7 +27,7 @@
  
      @Nullable
      protected MinecraftKey J() {
-@@ -125,7 +129,8 @@
+@@ -131,7 +135,8 @@
              }
  
              if (!this.world.isClientSide) {
@@ -37,7 +37,7 @@
                      this.setTamed(true);
                      this.setCatType(1 + this.world.random.nextInt(3));
                      this.setOwnerUUID(entityhuman.getUniqueID());
-@@ -234,7 +239,7 @@
+@@ -240,7 +245,7 @@
  
                  entityocelot.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, 0.0F);
                  entityocelot.setAgeRaw(-24000);
diff --git a/nms-patches/EntityPig.patch b/nms-patches/EntityPig.patch
index 557b39b1bc..a5618b021e 100644
--- a/nms-patches/EntityPig.patch
+++ b/nms-patches/EntityPig.patch
@@ -8,8 +8,8 @@
 +
  public class EntityPig extends EntityAnimal {
  
-     private static final DataWatcherObject<Boolean> bw = DataWatcher.a(EntityPig.class, DataWatcherRegistry.h);
-@@ -133,6 +135,12 @@
+     private static final DataWatcherObject<Boolean> bx = DataWatcher.a(EntityPig.class, DataWatcherRegistry.h);
+@@ -137,6 +139,12 @@
          if (!this.world.isClientSide && !this.dead) {
              EntityPigZombie entitypigzombie = new EntityPigZombie(this.world);
  
@@ -22,7 +22,7 @@
              entitypigzombie.setSlot(EnumItemSlot.MAINHAND, new ItemStack(Items.GOLDEN_SWORD));
              entitypigzombie.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, this.pitch);
              entitypigzombie.setAI(this.hasAI());
-@@ -141,7 +149,8 @@
+@@ -145,7 +153,8 @@
                  entitypigzombie.setCustomNameVisible(this.getCustomNameVisible());
              }
  
diff --git a/nms-patches/EntityPlayer.patch b/nms-patches/EntityPlayer.patch
index 2c1cc26dbe..d9f1f242ea 100644
--- a/nms-patches/EntityPlayer.patch
+++ b/nms-patches/EntityPlayer.patch
@@ -19,15 +19,8 @@
 +
  public class EntityPlayer extends EntityHuman implements ICrafting {
  
-     private static final Logger bR = LogManager.getLogger();
-@@ -38,12 +51,24 @@
-     private boolean ch = true;
-     private long ci = System.currentTimeMillis();
-     private Entity cj = null;
--    private boolean ck;
-+    protected boolean ck; // PAIL: private -> protected, rename worldChangeInvuln
-     private int containerCounter;
-     public boolean f;
+     private static final Logger bS = LogManager.getLogger();
+@@ -44,6 +57,18 @@
      public int ping;
      public boolean viewingCredits;
  
@@ -115,28 +108,26 @@
 @@ -193,7 +254,7 @@
              }
  
-             if (this.getHealth() != this.lastHealthSent || this.cc != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.cd) {
+             if (this.getHealth() != this.lastHealthSent || this.cd != this.foodData.getFoodLevel() || this.foodData.getSaturationLevel() == 0.0F != this.ce) {
 -                this.playerConnection.sendPacket(new PacketPlayOutUpdateHealth(this.getHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel()));
 +                this.playerConnection.sendPacket(new PacketPlayOutUpdateHealth(this.getBukkitEntity().getScaledHealth(), this.foodData.getFoodLevel(), this.foodData.getSaturationLevel())); // CraftBukkit
                  this.lastHealthSent = this.getHealth();
-                 this.cc = this.foodData.getFoodLevel();
-                 this.cd = this.foodData.getSaturationLevel() == 0.0F;
-@@ -214,10 +275,11 @@
-                 this.a(IScoreboardCriteria.i, MathHelper.f((float) this.bX));
+                 this.cd = this.foodData.getFoodLevel();
+                 this.ce = this.foodData.getSaturationLevel() == 0.0F;
+@@ -214,6 +275,12 @@
+                 this.a(IScoreboardCriteria.i, MathHelper.f((float) this.bY));
              }
  
--            if (this.getArmorStrength() != this.bY) {
--                this.bY = this.getArmorStrength();
--                this.a(IScoreboardCriteria.j, MathHelper.f((float) this.bY));
 +            // CraftBukkit start - Force max health updates
 +            if (this.maxHealthCache != this.getMaxHealth()) {
 +                this.getBukkitEntity().updateScaledHealth();
-             }
++            }
 +            // CraftBukkit end
- 
-             if (this.expTotal != this.ca) {
-                 this.ca = this.expTotal;
-@@ -238,6 +300,16 @@
++
+             if (this.getArmorStrength() != this.bZ) {
+                 this.bZ = this.getArmorStrength();
+                 this.a(IScoreboardCriteria.j, MathHelper.f((float) this.bZ));
+@@ -238,6 +305,16 @@
                  this.o();
              }
  
@@ -153,7 +144,7 @@
          } catch (Throwable throwable) {
              CrashReport crashreport = CrashReport.a(throwable, "Ticking player");
              CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Player being ticked");
-@@ -248,12 +320,11 @@
+@@ -248,12 +325,11 @@
      }
  
      private void a(IScoreboardCriteria iscoreboardcriteria, int i) {
@@ -168,12 +159,12 @@
  
              scoreboardscore.setScore(i);
          }
-@@ -302,30 +373,79 @@
+@@ -302,30 +378,79 @@
          boolean flag = this.world.getGameRules().getBoolean("showDeathMessages");
  
          this.playerConnection.sendPacket(new PacketPlayOutCombatEvent(this.getCombatTracker(), PacketPlayOutCombatEvent.EnumCombatEventType.ENTITY_DIED, flag));
 -        if (flag) {
--            ScoreboardTeamBase scoreboardteambase = this.aO();
+-            ScoreboardTeamBase scoreboardteambase = this.aQ();
 +        // CraftBukkit start - fire PlayerDeathEvent
 +        if (this.dead) {
 +            return;
@@ -200,20 +191,20 @@
 +        }
 +
 +        IChatBaseComponent chatmessage = this.getCombatTracker().getDeathMessage();
++
++        String deathmessage = chatmessage.toPlainText();
++        org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory);
  
 -            if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS) {
 -                if (scoreboardteambase.getDeathMessageVisibility() == ScoreboardTeamBase.EnumNameTagVisibility.HIDE_FOR_OTHER_TEAMS) {
 -                    this.server.getPlayerList().a((EntityHuman) this, this.getCombatTracker().getDeathMessage());
 -                } else if (scoreboardteambase.getDeathMessageVisibility() == ScoreboardTeamBase.EnumNameTagVisibility.HIDE_FOR_OWN_TEAM) {
 -                    this.server.getPlayerList().b((EntityHuman) this, this.getCombatTracker().getDeathMessage());
-+        String deathmessage = chatmessage.toPlainText();
-+        org.bukkit.event.entity.PlayerDeathEvent event = CraftEventFactory.callPlayerDeathEvent(this, loot, deathmessage, keepInventory);
-+
 +        String deathMessage = event.getDeathMessage();
 +
 +        if (deathMessage != null && deathMessage.length() > 0 && flag) { // TODO: allow plugins to override?
 +            if (deathMessage.equals(deathmessage)) {
-+                ScoreboardTeamBase scoreboardteambase = this.aO();
++                ScoreboardTeamBase scoreboardteambase = this.aQ();
 +
 +                if (scoreboardteambase != null && scoreboardteambase.getDeathMessageVisibility() != ScoreboardTeamBase.EnumNameTagVisibility.ALWAYS) {
 +                    if (scoreboardteambase.getDeathMessageVisibility() == ScoreboardTeamBase.EnumNameTagVisibility.HIDE_FOR_OTHER_TEAMS) {
@@ -261,7 +252,7 @@
  
              scoreboardscore.incrementScore();
          }
-@@ -382,13 +502,15 @@
+@@ -382,13 +507,15 @@
      }
  
      private boolean canPvP() {
@@ -272,14 +263,14 @@
  
      @Nullable
      public Entity c(int i) {
--        this.ck = true;
-+        //this.ck = true; // CraftBukkit - Moved down and into PlayerList#changeDimension
+-        this.worldChangeInvuln = true;
++        // this.worldChangeInvuln = true; // CraftBukkit - Moved down and into PlayerList#changeDimension
          if (this.dimension == 1 && i == 1) {
-+            this.ck = true; // CraftBukkit - Moved down from above
++            this.worldChangeInvuln = true; // CraftBukkit - Moved down from above
              this.world.kill(this);
              if (!this.viewingCredits) {
                  this.viewingCredits = true;
-@@ -409,7 +531,10 @@
+@@ -409,7 +536,10 @@
                  this.b((Statistic) AchievementList.y);
              }
  
@@ -291,7 +282,7 @@
              this.playerConnection.sendPacket(new PacketPlayOutWorldEvent(1032, BlockPosition.ZERO, 0, false));
              this.lastSentExp = -1;
              this.lastHealthSent = -1.0F;
-@@ -454,6 +579,7 @@
+@@ -454,6 +584,7 @@
      }
  
      public void a(boolean flag, boolean flag1, boolean flag2) {
@@ -299,7 +290,7 @@
          if (this.isSleeping()) {
              this.x().getTracker().sendPacketToEntity(this, new PacketPlayOutAnimation(this, 2));
          }
-@@ -532,23 +658,48 @@
+@@ -532,23 +663,48 @@
          this.playerConnection.sendPacket(new PacketPlayOutOpenSignEditor(tileentitysign.getPosition()));
      }
  
@@ -357,7 +348,7 @@
          if (iinventory instanceof ILootable && ((ILootable) iinventory).b() != null && this.isSpectator()) {
              this.sendMessage((new ChatMessage("container.spectatorCantOpen", new Object[0])).setChatModifier((new ChatModifier()).setColor(EnumChatFormat.RED)));
          } else {
-@@ -562,18 +713,21 @@
+@@ -562,18 +718,21 @@
                  if (itileinventory.x_() && !this.a(itileinventory.y_()) && !this.isSpectator()) {
                      this.playerConnection.sendPacket(new PacketPlayOutChat(new ChatMessage("container.isLocked", new Object[] { iinventory.getScoreboardDisplayName()}), (byte) 2));
                      this.playerConnection.sendPacket(new PacketPlayOutNamedSoundEffect(SoundEffects.W, SoundCategory.BLOCKS, this.locX, this.locY, this.locZ, 1.0F, 1.0F));
@@ -381,7 +372,7 @@
  
              this.activeContainer.windowId = this.containerCounter;
              this.activeContainer.addSlotListener(this);
-@@ -581,8 +735,14 @@
+@@ -581,8 +740,14 @@
      }
  
      public void openTrade(IMerchant imerchant) {
@@ -397,7 +388,7 @@
          this.activeContainer.windowId = this.containerCounter;
          this.activeContainer.addSlotListener(this);
          InventoryMerchant inventorymerchant = ((ContainerMerchant) this.activeContainer).e();
-@@ -601,14 +761,21 @@
+@@ -601,14 +766,21 @@
  
      }
  
@@ -421,7 +412,7 @@
          this.activeContainer.windowId = this.containerCounter;
          this.activeContainer.addSlotListener(this);
      }
-@@ -648,6 +815,11 @@
+@@ -645,6 +817,11 @@
      public void a(Container container, List<ItemStack> list) {
          this.playerConnection.sendPacket(new PacketPlayOutWindowItems(container.windowId, list));
          this.playerConnection.sendPacket(new PacketPlayOutSetSlot(-1, -1, this.inventory.getCarried()));
@@ -433,7 +424,7 @@
      }
  
      public void setContainerData(Container container, int i, int j) {
-@@ -662,6 +834,7 @@
+@@ -659,6 +836,7 @@
      }
  
      public void closeInventory() {
@@ -441,7 +432,7 @@
          this.playerConnection.sendPacket(new PacketPlayOutCloseWindow(this.activeContainer.windowId));
          this.s();
      }
-@@ -743,7 +916,16 @@
+@@ -740,7 +918,16 @@
  
      public void triggerHealthUpdate() {
          this.lastHealthSent = -1.0E8F;
@@ -458,24 +449,24 @@
  
      public void b(IChatBaseComponent ichatbasecomponent) {
          this.playerConnection.sendPacket(new PacketPlayOutChat(ichatbasecomponent));
-@@ -804,6 +986,8 @@
+@@ -801,6 +988,8 @@
      }
  
-     public void a(WorldSettings.EnumGamemode worldsettings_enumgamemode) {
-+        getBukkitEntity().setGameMode(org.bukkit.GameMode.getByValue(worldsettings_enumgamemode.getId()));
+     public void a(EnumGamemode enumgamemode) {
++        getBukkitEntity().setGameMode(org.bukkit.GameMode.getByValue(enumgamemode.getId()));
 +        /* CraftBukkit start - defer to our setGameMode
-         this.playerInteractManager.setGameMode(worldsettings_enumgamemode);
-         this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(3, (float) worldsettings_enumgamemode.getId()));
-         if (worldsettings_enumgamemode == WorldSettings.EnumGamemode.SPECTATOR) {
-@@ -814,6 +998,7 @@
+         this.playerInteractManager.setGameMode(enumgamemode);
+         this.playerConnection.sendPacket(new PacketPlayOutGameStateChange(3, (float) enumgamemode.getId()));
+         if (enumgamemode == EnumGamemode.SPECTATOR) {
+@@ -811,6 +1000,7 @@
  
          this.updateAbilities();
-         this.cr();
+         this.cv();
 +        // CraftBukkit end */
      }
  
      public boolean isSpectator() {
-@@ -829,6 +1014,7 @@
+@@ -826,6 +1016,7 @@
      }
  
      public boolean a(int i, String s) {
@@ -483,7 +474,7 @@
          if ("seed".equals(s) && !this.server.aa()) {
              return true;
          } else if (!"tell".equals(s) && !"help".equals(s) && !"me".equals(s) && !"trigger".equals(s)) {
-@@ -842,6 +1028,15 @@
+@@ -839,6 +1030,15 @@
          } else {
              return true;
          }
@@ -499,20 +490,20 @@
      }
  
      public String A() {
-@@ -853,6 +1048,12 @@
+@@ -850,6 +1050,12 @@
      }
  
      public void a(PacketPlayInSettings packetplayinsettings) {
 +        // CraftBukkit start
-+        if (getMainHand() != packetplayinsettings.f()) { // PAIL: rename
++        if (getMainHand() != packetplayinsettings.getMainHand()) {
 +            PlayerChangedMainHandEvent event = new PlayerChangedMainHandEvent(getBukkitEntity(), getMainHand() == EnumMainHand.LEFT ? MainHand.LEFT : MainHand.RIGHT);
 +            this.server.server.getPluginManager().callEvent(event);
 +        }
 +        // CraftBukkit end
          this.locale = packetplayinsettings.a();
-         this.cg = packetplayinsettings.c();
-         this.ch = packetplayinsettings.d();
-@@ -941,7 +1142,7 @@
+         this.ch = packetplayinsettings.c();
+         this.ci = packetplayinsettings.d();
+@@ -938,7 +1144,7 @@
  
      @Nullable
      public IChatBaseComponent getPlayerListName() {
@@ -521,7 +512,7 @@
      }
  
      public void a(EnumHand enumhand) {
-@@ -958,11 +1159,139 @@
+@@ -955,11 +1161,139 @@
      }
  
      public void M() {
diff --git a/nms-patches/EntityProjectile.patch b/nms-patches/EntityProjectile.patch
index 5f83ce9b1e..5e01a87cc7 100644
--- a/nms-patches/EntityProjectile.patch
+++ b/nms-patches/EntityProjectile.patch
@@ -8,7 +8,7 @@
      }
  
      protected void i() {}
-@@ -162,6 +163,11 @@
+@@ -164,6 +165,11 @@
                  this.e(movingobjectposition.a());
              } else {
                  this.a(movingobjectposition);
diff --git a/nms-patches/EntitySheep.patch b/nms-patches/EntitySheep.patch
index b2f7862892..c3ca71f737 100644
--- a/nms-patches/EntitySheep.patch
+++ b/nms-patches/EntitySheep.patch
@@ -12,7 +12,7 @@
 +
  public class EntitySheep extends EntityAnimal {
  
-     private static final DataWatcherObject<Byte> bw = DataWatcher.a(EntitySheep.class, DataWatcherRegistry.a);
+     private static final DataWatcherObject<Byte> bx = DataWatcher.a(EntitySheep.class, DataWatcherRegistry.a);
 @@ -12,6 +18,13 @@
          public boolean a(EntityHuman entityhuman) {
              return false;
@@ -25,8 +25,8 @@
 +        }
 +        // CraftBukkit end
      }, 2, 1);
-     private static final Map<EnumColor, float[]> by = Maps.newEnumMap(EnumColor.class);
-     private int bA;
+     private static final Map<EnumColor, float[]> bz = Maps.newEnumMap(EnumColor.class);
+     private int bB;
 @@ -26,6 +39,7 @@
          this.setSize(0.9F, 1.3F);
          this.container.setItem(0, new ItemStack(Items.DYE));
@@ -35,7 +35,7 @@
      }
  
      protected void r() {
-@@ -125,11 +139,22 @@
+@@ -126,11 +140,22 @@
      public boolean a(EntityHuman entityhuman, EnumHand enumhand, @Nullable ItemStack itemstack) {
          if (itemstack != null && itemstack.getItem() == Items.SHEARS && !this.isSheared() && !this.isBaby()) {
              if (!this.world.isClientSide) {
@@ -58,10 +58,10 @@
  
                      entityitem.motY += (double) (this.random.nextFloat() * 0.05F);
                      entityitem.motX += (double) ((this.random.nextFloat() - this.random.nextFloat()) * 0.1F);
-@@ -212,6 +237,12 @@
+@@ -217,6 +242,12 @@
      }
  
-     public void B() {
+     public void A() {
 +        // CraftBukkit start
 +        SheepRegrowWoolEvent event = new SheepRegrowWoolEvent((org.bukkit.entity.Sheep) this.getBukkitEntity());
 +        this.world.getServer().getPluginManager().callEvent(event);
diff --git a/nms-patches/EntitySilverfish.patch b/nms-patches/EntitySilverfish.patch
index 054cd7de1b..8c6982319e 100644
--- a/nms-patches/EntitySilverfish.patch
+++ b/nms-patches/EntitySilverfish.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/EntitySilverfish.java
 +++ b/net/minecraft/server/EntitySilverfish.java
-@@ -151,6 +151,11 @@
+@@ -156,6 +156,11 @@
                  IBlockData iblockdata = world.getType(blockposition);
  
                  if (BlockMonsterEggs.i(iblockdata)) {
@@ -12,7 +12,7 @@
                      world.setTypeAndData(blockposition, Blocks.MONSTER_EGG.getBlockData().set(BlockMonsterEggs.VARIANT, BlockMonsterEggs.EnumMonsterEggVarient.a(iblockdata)), 3);
                      this.silverfish.doSpawnEffect();
                      this.silverfish.die();
-@@ -194,6 +199,11 @@
+@@ -199,6 +204,11 @@
                              IBlockData iblockdata = world.getType(blockposition1);
  
                              if (iblockdata.getBlock() == Blocks.MONSTER_EGG) {
diff --git a/nms-patches/EntitySkeleton.patch b/nms-patches/EntitySkeleton.patch
index 63a27c52a0..2d8665663a 100644
--- a/nms-patches/EntitySkeleton.patch
+++ b/nms-patches/EntitySkeleton.patch
@@ -11,12 +11,12 @@
      private static final DataWatcherObject<Integer> a = DataWatcher.a(EntitySkeleton.class, DataWatcherRegistry.b);
      private static final DataWatcherObject<Boolean> b = DataWatcher.a(EntitySkeleton.class, DataWatcherRegistry.h);
      private final PathfinderGoalBowShoot c = new PathfinderGoalBowShoot(this, 1.0D, 20, 15.0F);
--    private final PathfinderGoalMeleeAttack bw = new PathfinderGoalMeleeAttack(this, 1.2D, flag) {
-+    private final PathfinderGoalMeleeAttack bw = new PathfinderGoalMeleeAttack(this, 1.2D, false) { // CraftBukkit decompile error flag -> false
+-    private final PathfinderGoalMeleeAttack bx = new PathfinderGoalMeleeAttack(this, 1.2D, flag) {
++    private final PathfinderGoalMeleeAttack bx = new PathfinderGoalMeleeAttack(this, 1.2D, false) { // CraftBukkit decompile error flag -> false
          public void d() {
              super.d();
              EntitySkeleton.this.a(false);
-@@ -103,7 +104,14 @@
+@@ -105,7 +106,14 @@
                  }
  
                  if (flag) {
@@ -32,7 +32,7 @@
                  }
              }
          }
-@@ -126,7 +134,7 @@
+@@ -128,7 +136,7 @@
      }
  
      public void die(DamageSource damagesource) {
@@ -41,18 +41,18 @@
          if (damagesource.i() instanceof EntityArrow && damagesource.getEntity() instanceof EntityHuman) {
              EntityHuman entityhuman = (EntityHuman) damagesource.getEntity();
              double d0 = entityhuman.locX - this.locX;
-@@ -139,6 +147,7 @@
+@@ -141,6 +149,7 @@
              ((EntityCreeper) damagesource.getEntity()).setCausedHeadDrop();
-             this.a(new ItemStack(Items.SKULL, 1, this.getSkeletonType() == 1 ? 1 : 0), 0.0F);
+             this.a(new ItemStack(Items.SKULL, 1, this.getSkeletonType() == EnumSkeletonType.WITHER ? 1 : 0), 0.0F);
          }
 +        super.die(damagesource); // CraftBukkit - moved from above
  
      }
  
-@@ -222,11 +231,30 @@
-         }
+@@ -234,7 +243,14 @@
  
-         if (EnchantmentManager.a(Enchantments.ARROW_FIRE, (EntityLiving) this) > 0 || this.getSkeletonType() == 1) {
+         flag = flag || EnchantmentManager.a(Enchantments.ARROW_FIRE, (EntityLiving) this) > 0;
+         if (flag) {
 -            entitytippedarrow.setOnFire(100);
 +            // CraftBukkit start - call EntityCombustEvent
 +            EntityCombustEvent event = new EntityCombustEvent(entitytippedarrow.getBukkitEntity(), 100);
@@ -62,8 +62,13 @@
 +                entitytippedarrow.setOnFire(event.getDuration());
 +            }
 +            // CraftBukkit end
-+        }
-+
+         }
+ 
+         ItemStack itemstack = this.b(EnumHand.OFF_HAND);
+@@ -245,8 +261,20 @@
+             entitytippedarrow.a(new MobEffect(MobEffects.SLOWER_MOVEMENT, 600));
+         }
+ 
 +        // CraftBukkit start
 +        org.bukkit.event.entity.EntityShootBowEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityShootBowEvent(this, this.getItemInMainHand(), entitytippedarrow, 0.8F);
 +        if (event.isCancelled()) {
@@ -73,12 +78,12 @@
 +
 +        if (event.getProjectile() == entitytippedarrow.getBukkitEntity()) {
 +            world.addEntity(entitytippedarrow);
-         }
++        }
 +        // CraftBukkit end
- 
-         this.a(SoundEffects.fo, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
++
+         this.a(SoundEffects.fz, 1.0F, 1.0F / (this.getRandom().nextFloat() * 0.4F + 0.8F));
 -        this.world.addEntity(entitytippedarrow);
 +        // this.world.addEntity(entitytippedarrow); // CraftBukkit - moved up
      }
  
-     public int getSkeletonType() {
+     public EnumSkeletonType getSkeletonType() {
diff --git a/nms-patches/EntitySlime.patch b/nms-patches/EntitySlime.patch
index c2696a145b..79e5fc2865 100644
--- a/nms-patches/EntitySlime.patch
+++ b/nms-patches/EntitySlime.patch
@@ -10,7 +10,7 @@
  
  public class EntitySlime extends EntityInsentient implements IMonster {
  
-@@ -136,6 +139,18 @@
+@@ -140,6 +143,18 @@
          if (!this.world.isClientSide && i > 1 && this.getHealth() <= 0.0F) {
              int j = 2 + this.random.nextInt(3);
  
@@ -29,7 +29,7 @@
              for (int k = 0; k < j; ++k) {
                  float f = ((float) (k % 2) - 0.5F) * (float) i / 4.0F;
                  float f1 = ((float) (k / 2) - 0.5F) * (float) i / 4.0F;
-@@ -151,7 +166,7 @@
+@@ -155,7 +170,7 @@
  
                  entityslime.setSize(i / 2);
                  entityslime.setPositionRotation(this.locX + (double) f, this.locY + 0.5D, this.locZ + (double) f1, this.random.nextFloat() * 360.0F, 0.0F);
diff --git a/nms-patches/EntitySmallFireball.patch b/nms-patches/EntitySmallFireball.patch
index 8e472c3285..5fed4bcdc7 100644
--- a/nms-patches/EntitySmallFireball.patch
+++ b/nms-patches/EntitySmallFireball.patch
@@ -8,7 +8,7 @@
  public class EntitySmallFireball extends EntityFireball {
  
      public EntitySmallFireball(World world) {
-@@ -26,7 +28,14 @@
+@@ -30,7 +32,14 @@
                      flag = movingobjectposition.entity.damageEntity(DamageSource.fireball(this, this.shooter), 5.0F);
                      if (flag) {
                          this.a(this.shooter, movingobjectposition.entity);
@@ -24,7 +24,7 @@
                      }
                  }
              } else {
-@@ -39,7 +48,11 @@
+@@ -43,7 +52,11 @@
                      BlockPosition blockposition = movingobjectposition.a().shift(movingobjectposition.direction);
  
                      if (this.world.isEmpty(blockposition)) {
diff --git a/nms-patches/EntitySnowman.patch b/nms-patches/EntitySnowman.patch
index 8edc685c07..6a190b6737 100644
--- a/nms-patches/EntitySnowman.patch
+++ b/nms-patches/EntitySnowman.patch
@@ -12,7 +12,7 @@
  
  public class EntitySnowman extends EntityGolem implements IRangedEntity {
  
-@@ -42,7 +47,7 @@
+@@ -46,7 +51,7 @@
              }
  
              if (this.world.getBiome(new BlockPosition(i, 0, k)).a(new BlockPosition(i, j, k)) > 1.0F) {
@@ -21,7 +21,7 @@
              }
  
              if (!this.world.getGameRules().getBoolean("mobGriefing")) {
-@@ -56,7 +61,17 @@
+@@ -60,7 +65,17 @@
                  BlockPosition blockposition = new BlockPosition(i, j, k);
  
                  if (this.world.getType(blockposition).getMaterial() == Material.AIR && this.world.getBiome(new BlockPosition(i, 0, k)).a(blockposition) < 0.8F && Blocks.SNOW_LAYER.canPlace(this.world, blockposition)) {
diff --git a/nms-patches/EntitySpider.patch b/nms-patches/EntitySpider.patch
index b9ba2b63fc..4c7b19b31e 100644
--- a/nms-patches/EntitySpider.patch
+++ b/nms-patches/EntitySpider.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/EntitySpider.java
 +++ b/net/minecraft/server/EntitySpider.java
-@@ -111,7 +111,7 @@
+@@ -115,7 +115,7 @@
  
              entityskeleton.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, 0.0F);
              entityskeleton.prepare(difficultydamagescaler, (GroupDataEntity) null);
diff --git a/nms-patches/EntityTNTPrimed.patch b/nms-patches/EntityTNTPrimed.patch
index 54037dc221..6b765dd848 100644
--- a/nms-patches/EntityTNTPrimed.patch
+++ b/nms-patches/EntityTNTPrimed.patch
@@ -15,7 +15,7 @@
  
      public EntityTNTPrimed(World world) {
          super(world);
-@@ -57,10 +61,13 @@
+@@ -60,10 +64,13 @@
  
          --this.c;
          if (this.c <= 0) {
@@ -28,9 +28,9 @@
 +            this.die();
 +            // CraftBukkit end
          } else {
-             this.aj();
+             this.ak();
              this.world.addParticle(EnumParticle.SMOKE_NORMAL, this.locX, this.locY + 0.5D, this.locZ, 0.0D, 0.0D, 0.0D, new int[0]);
-@@ -69,9 +76,18 @@
+@@ -72,9 +79,18 @@
      }
  
      private void explode() {
@@ -38,14 +38,14 @@
 +        // CraftBukkit start
 +        // float f = 4.0F;
  
--        this.world.explode(this, this.locX, this.locY + (double) (this.length / 16.0F), this.locZ, f, true);
+-        this.world.explode(this, this.locX, this.locY + (double) (this.length / 16.0F), this.locZ, 4.0F, true);
 +        org.bukkit.craftbukkit.CraftServer server = this.world.getServer();
 +
 +        ExplosionPrimeEvent event = new ExplosionPrimeEvent((org.bukkit.entity.Explosive) org.bukkit.craftbukkit.entity.CraftEntity.getEntity(server, this));
 +        server.getPluginManager().callEvent(event);
 +
 +        if (!event.isCancelled()) {
-+            this.world.createExplosion(this, this.locX, this.locY + (double) (this.length / 2.0F), this.locZ, event.getRadius(), event.getFire(), true);
++            this.world.createExplosion(this, this.locX, this.locY + (double) (this.length / 16.0F), this.locZ, event.getRadius(), event.getFire(), true);
 +        }
 +        // CraftBukkit end
      }
diff --git a/nms-patches/EntityThrownExpBottle.patch b/nms-patches/EntityThrownExpBottle.patch
index 42c72d7988..c3a19637cb 100644
--- a/nms-patches/EntityThrownExpBottle.patch
+++ b/nms-patches/EntityThrownExpBottle.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/EntityThrownExpBottle.java
 +++ b/net/minecraft/server/EntityThrownExpBottle.java
-@@ -20,9 +20,18 @@
+@@ -24,9 +24,18 @@
  
      protected void a(MovingObjectPosition movingobjectposition) {
          if (!this.world.isClientSide) {
diff --git a/nms-patches/EntityTippedArrow.patch b/nms-patches/EntityTippedArrow.patch
index 135274dad2..145287c67a 100644
--- a/nms-patches/EntityTippedArrow.patch
+++ b/nms-patches/EntityTippedArrow.patch
@@ -1,34 +1,25 @@
 --- a/net/minecraft/server/EntityTippedArrow.java
 +++ b/net/minecraft/server/EntityTippedArrow.java
-@@ -10,7 +10,7 @@
- 
-     private static final DataWatcherObject<Integer> f = DataWatcher.a(EntityTippedArrow.class, DataWatcherRegistry.b);
-     private PotionRegistry g;
--    private final Set<MobEffect> h;
-+    public final Set<MobEffect> h; // CraftBukkit private -> public
- 
-     public EntityTippedArrow(World world) {
-         super(world);
 @@ -98,6 +98,25 @@
          }
      }
  
 +    // CraftBukkit start accessor methods
 +    public void refreshEffects() {
-+        this.getDataWatcher().set(EntityTippedArrow.f, Integer.valueOf(PotionUtil.a((Collection) PotionUtil.a(this.g, (Collection) this.h)))); // PAIL: rename
++        this.getDataWatcher().set(EntityTippedArrow.f, Integer.valueOf(PotionUtil.a((Collection) PotionUtil.a(this.potionRegistry, (Collection) this.effects))));
 +    }
 +
 +    public String getType() {
-+        return ((MinecraftKey) PotionRegistry.a.b(this.g)).toString();
++        return ((MinecraftKey) PotionRegistry.a.b(this.potionRegistry)).toString();
 +    }
 +
 +    public void setType(String string) {
-+        this.g = PotionRegistry.a.get(new MinecraftKey(string));
-+        this.datawatcher.set(EntityTippedArrow.f, Integer.valueOf(PotionUtil.a((Collection) PotionUtil.a(this.g, (Collection) this.h)))); // PAIL: rename
++        this.potionRegistry = PotionRegistry.a.get(new MinecraftKey(string));
++        this.datawatcher.set(EntityTippedArrow.f, Integer.valueOf(PotionUtil.a((Collection) PotionUtil.a(this.potionRegistry, (Collection) this.effects))));
 +    }
 +
 +    public boolean isTipped() {
-+        return !(this.h.isEmpty() && this.g == Potions.a); // PAIL: rename
++        return !(this.effects.isEmpty() && this.potionRegistry == Potions.a); // PAIL: rename
 +    }
 +    // CraftBukkit end
 +
diff --git a/nms-patches/EntityTrackerEntry.patch b/nms-patches/EntityTrackerEntry.patch
index 295003e67d..db80f3e042 100644
--- a/nms-patches/EntityTrackerEntry.patch
+++ b/nms-patches/EntityTrackerEntry.patch
@@ -30,27 +30,27 @@
  
                  while (iterator.hasNext()) {
                      EntityHuman entityhuman = (EntityHuman) iterator.next();
-@@ -120,6 +126,19 @@
-                 boolean flag = k1 * k1 + l1 * l1 + i2 * i2 >= 128L || this.a % 60 == 0;
-                 boolean flag1 = Math.abs(i1 - this.yRot) >= 1 || Math.abs(j1 - this.xRot) >= 1;
+@@ -136,6 +142,19 @@
+                 boolean flag1 = l1 * l1 + i2 * i2 + j2 * j2 >= 128L || this.a % 60 == 0;
+                 boolean flag2 = Math.abs(j1 - this.yRot) >= 1 || Math.abs(k1 - this.xRot) >= 1;
  
 +                // CraftBukkit start - Code moved from below
-+                if (flag) {
-+                    this.xLoc = j;
-+                    this.yLoc = k;
-+                    this.zLoc = l;
++                if (flag1) {
++                    this.xLoc = k;
++                    this.yLoc = l;
++                    this.zLoc = i1;
 +                }
 +
-+                if (flag1) {
-+                    this.yRot = i1;
-+                    this.xRot = j1;
++                if (flag2) {
++                    this.yRot = j1;
++                    this.xRot = k1;
 +                }
 +                // CraftBukkit end
 +
                  if (this.a > 0 || this.tracker instanceof EntityArrow) {
-                     if (k1 >= -32768L && k1 < 32768L && l1 >= -32768L && l1 < 32768L && i2 >= -32768L && i2 < 32768L && this.v <= 400 && !this.x && this.y == this.tracker.onGround) {
-                         if ((!flag || !flag1) && !(this.tracker instanceof EntityArrow)) {
-@@ -134,6 +153,11 @@
+                     if (l1 >= -32768L && l1 < 32768L && i2 >= -32768L && i2 < 32768L && j2 >= -32768L && j2 < 32768L && this.v <= 400 && !this.x && this.y == this.tracker.onGround) {
+                         if ((!flag1 || !flag2) && !(this.tracker instanceof EntityArrow)) {
+@@ -150,6 +169,11 @@
                      } else {
                          this.y = this.tracker.onGround;
                          this.v = 0;
@@ -62,22 +62,22 @@
                          this.c();
                          object = new PacketPlayOutEntityTeleport(this.tracker);
                      }
-@@ -165,6 +189,7 @@
+@@ -181,6 +205,7 @@
                  }
  
                  this.d();
 +                /* CraftBukkit start - Code moved up
-                 if (flag) {
-                     this.xLoc = j;
-                     this.yLoc = k;
-@@ -175,6 +200,7 @@
-                     this.yRot = i1;
-                     this.xRot = j1;
+                 if (flag1) {
+                     this.xLoc = k;
+                     this.yLoc = l;
+@@ -191,6 +216,7 @@
+                     this.yRot = j1;
+                     this.xRot = k1;
                  }
 +                // CraftBukkit end */
  
                  this.x = false;
-             } else {
+             }
 @@ -206,7 +232,27 @@
  
          ++this.a;
diff --git a/nms-patches/EntityVillager.patch b/nms-patches/EntityVillager.patch
index 2d36fde80a..85102eecb3 100644
--- a/nms-patches/EntityVillager.patch
+++ b/nms-patches/EntityVillager.patch
@@ -40,7 +40,7 @@
                          }
                      }
  
-@@ -402,7 +417,20 @@
+@@ -429,7 +444,20 @@
              for (int l = 0; l < k; ++l) {
                  EntityVillager.IMerchantRecipeOption entityvillager_imerchantrecipeoption = aentityvillager_imerchantrecipeoption3[l];
  
diff --git a/nms-patches/EntityWither.patch b/nms-patches/EntityWither.patch
index 7acdbb789d..4ba2f41ddf 100644
--- a/nms-patches/EntityWither.patch
+++ b/nms-patches/EntityWither.patch
@@ -13,9 +13,9 @@
  public class EntityWither extends EntityMonster implements IRangedEntity {
  
      private static final DataWatcherObject<Integer> a = DataWatcher.a(EntityWither.class, DataWatcherRegistry.b);
-@@ -180,13 +186,38 @@
-         if (this.da() > 0) {
-             i = this.da() - 1;
+@@ -184,13 +190,38 @@
+         if (this.de() > 0) {
+             i = this.de() - 1;
              if (i <= 0) {
 -                this.world.createExplosion(this, this.locX, this.locY + (double) this.getHeadHeight(), this.locZ, 7.0F, false, this.world.getGameRules().getBoolean("mobGriefing"));
 -                this.world.a(1023, new BlockPosition(this), 0);
@@ -48,14 +48,14 @@
 +                // CraftBukkit end
              }
  
-             this.l(i);
+             this.g(i);
              if (this.ticksLived % 10 == 0) {
 -                this.heal(10.0F);
 +                this.heal(10.0F, EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); // CraftBukkit
              }
  
          } else {
-@@ -277,6 +308,11 @@
+@@ -281,6 +312,11 @@
                                  Block block = iblockdata.getBlock();
  
                                  if (iblockdata.getMaterial() != Material.AIR && a(block)) {
@@ -67,7 +67,7 @@
                                      flag = this.world.setAir(blockposition, true) || flag;
                                  }
                              }
-@@ -290,7 +326,7 @@
+@@ -294,7 +330,7 @@
              }
  
              if (this.ticksLived % 20 == 0) {
@@ -75,4 +75,4 @@
 +                this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit
              }
  
-             this.bF.setProgress(this.getHealth() / this.getMaxHealth());
+             this.bG.setProgress(this.getHealth() / this.getMaxHealth());
diff --git a/nms-patches/EntityWitherSkull.patch b/nms-patches/EntityWitherSkull.patch
index f51429c171..ba9d947856 100644
--- a/nms-patches/EntityWitherSkull.patch
+++ b/nms-patches/EntityWitherSkull.patch
@@ -8,19 +8,21 @@
  public class EntityWitherSkull extends EntityFireball {
  
      private static final DataWatcherObject<Boolean> e = DataWatcher.a(EntityWitherSkull.class, DataWatcherRegistry.h);
-@@ -37,9 +39,9 @@
+@@ -41,11 +43,11 @@
          if (!this.world.isClientSide) {
              if (movingobjectposition.entity != null) {
                  if (this.shooter != null) {
 -                    if (movingobjectposition.entity.damageEntity(DamageSource.mobAttack(this.shooter), 8.0F)) {
 +                    if (movingobjectposition.entity.damageEntity(DamageSource.projectile(this, shooter), 8.0F)) { // CraftBukkit
-                         if (!movingobjectposition.entity.isAlive()) {
+                         if (movingobjectposition.entity.isAlive()) {
+                             this.a(this.shooter, movingobjectposition.entity);
+                         } else {
 -                            this.shooter.heal(5.0F);
 +                            this.shooter.heal(5.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.WITHER); // CraftBukkit
-                         } else {
-                             this.a(this.shooter, movingobjectposition.entity);
                          }
-@@ -63,7 +65,15 @@
+                     }
+                 } else {
+@@ -67,7 +69,15 @@
                  }
              }
  
diff --git a/nms-patches/EntityWolf.patch b/nms-patches/EntityWolf.patch
index c37aeb64b8..da6feb89a2 100644
--- a/nms-patches/EntityWolf.patch
+++ b/nms-patches/EntityWolf.patch
@@ -12,7 +12,7 @@
  public class EntityWolf extends EntityTameableAnimal {
  
      private static final DataWatcherObject<Float> DATA_HEALTH = DataWatcher.a(EntityWolf.class, DataWatcherRegistry.c);
-@@ -60,6 +65,22 @@
+@@ -61,6 +66,22 @@
          this.getAttributeMap().b(GenericAttributes.ATTACK_DAMAGE).setValue(2.0D);
      }
  
@@ -35,7 +35,7 @@
      public void setGoalTarget(@Nullable EntityLiving entityliving) {
          super.setGoalTarget(entityliving);
          if (entityliving == null) {
-@@ -194,9 +215,10 @@
+@@ -199,9 +220,10 @@
              Entity entity = damagesource.getEntity();
  
              if (this.goalSit != null) {
@@ -48,7 +48,7 @@
              if (entity != null && !(entity instanceof EntityHuman) && !(entity instanceof EntityArrow)) {
                  f = (f + 1.0F) / 2.0F;
              }
-@@ -237,7 +259,7 @@
+@@ -242,7 +264,7 @@
                              --itemstack.count;
                          }
  
@@ -57,16 +57,16 @@
                          return true;
                      }
                  } else if (itemstack.getItem() == Items.DYE) {
-@@ -258,7 +280,7 @@
+@@ -263,7 +285,7 @@
                  this.goalSit.setSitting(!this.isSitting());
-                 this.bd = false;
+                 this.be = false;
                  this.navigation.o();
 -                this.setGoalTarget((EntityLiving) null);
 +                this.setGoalTarget((EntityLiving) null, TargetReason.FORGOT_TARGET, true); // CraftBukkit - reason
              }
          } else if (itemstack != null && itemstack.getItem() == Items.BONE && !this.isAngry()) {
              if (!entityhuman.abilities.canInstantlyBuild) {
-@@ -266,12 +288,14 @@
+@@ -271,12 +293,14 @@
              }
  
              if (!this.world.isClientSide) {
@@ -80,14 +80,5 @@
                      this.setHealth(20.0F);
 +                    this.setHealth(this.getMaxHealth()); // CraftBukkit - 20.0 -> getMaxHealth()
                      this.setOwnerUUID(entityhuman.getUniqueID());
-                     this.o(true);
+                     this.p(true);
                      this.world.broadcastEntityEffect(this, (byte) 7);
-@@ -353,7 +377,7 @@
-     }
- 
-     protected boolean isTypeNotPersistent() {
--        return !this.isTamed() && this.ticksLived > 2400;
-+        return !this.isTamed() /*&& this.ticksLived > 2400*/; // CraftBukkit
-     }
- 
-     public boolean a(EntityLiving entityliving, EntityLiving entityliving1) {
diff --git a/nms-patches/EntityZombie.patch b/nms-patches/EntityZombie.patch
index 0fe3d3c0e8..c4348eb1ab 100644
--- a/nms-patches/EntityZombie.patch
+++ b/nms-patches/EntityZombie.patch
@@ -15,9 +15,9 @@
  
      protected static final IAttribute a = (new AttributeRanged((IAttribute) null, "zombie.spawnReinforcements", 0.0D, 0.0D, 1.0D)).a("Spawn Reinforcements Chance");
 @@ -19,6 +26,7 @@
-     private boolean bC = false;
-     private float bD = -1.0F;
-     private float bE;
+     private boolean bD;
+     private float bE = -1.0F;
+     private float bF;
 +    private int lastTick = MinecraftServer.currentTick; // CraftBukkit - add field
  
      public EntityZombie(World world) {
@@ -59,25 +59,25 @@
 +            i *= elapsedTicks;
 +            // CraftBukkit end
  
-             this.bB -= i;
-             if (this.bB <= 0) {
-@@ -220,7 +240,14 @@
-             int i = this.world.getDifficulty().a();
+             this.bC -= i;
+             if (this.bC <= 0) {
+@@ -221,7 +241,14 @@
  
-             if (this.getItemInMainHand() == null && this.isBurning() && this.random.nextFloat() < (float) i * 0.3F) {
--                entity.setOnFire(2 * i);
+             if (this.getItemInMainHand() == null) {
+                 if (this.isBurning() && this.random.nextFloat() < f * 0.3F) {
+-                    entity.setOnFire(2 * (int) f);
 +                // CraftBukkit start
-+                EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 2 * i);
++                EntityCombustByEntityEvent event = new EntityCombustByEntityEvent(this.getBukkitEntity(), entity.getBukkitEntity(), 2 * (int) f); // PAIL: fixme
 +                this.world.getServer().getPluginManager().callEvent(event);
 +
 +                if (!event.isCancelled()) {
 +                    entity.setOnFire(event.getDuration());
 +                }
 +                // CraftBukkit end
-             }
-         }
+                 }
  
-@@ -323,7 +350,7 @@
+                 if (this.getVillagerType() == EnumZombieType.HUSK && entity instanceof EntityLiving) {
+@@ -335,7 +362,7 @@
                  entityzombie.setCustomNameVisible(entityvillager.getCustomNameVisible());
              }
  
@@ -86,16 +86,16 @@
              this.world.a((EntityHuman) null, 1026, new BlockPosition((int) this.locX, (int) this.locY, (int) this.locZ), 0);
          }
  
-@@ -377,7 +404,7 @@
+@@ -396,7 +423,7 @@
                      entitychicken1.setPositionRotation(this.locX, this.locY, this.locZ, this.yaw, 0.0F);
                      entitychicken1.prepare(difficultydamagescaler, (GroupDataEntity) null);
-                     entitychicken1.o(true);
+                     entitychicken1.p(true);
 -                    this.world.addEntity(entitychicken1);
 +                    this.world.addEntity(entitychicken1, CreatureSpawnEvent.SpawnReason.MOUNT); // CraftBukkit
                      this.startRiding(entitychicken1);
                  }
              }
-@@ -461,7 +488,7 @@
+@@ -480,7 +507,7 @@
              entityvillager.setCustomNameVisible(this.getCustomNameVisible());
          }
  
@@ -104,7 +104,7 @@
          entityvillager.addEffect(new MobEffect(MobEffects.CONFUSION, 200, 0));
          this.world.a((EntityHuman) null, 1027, new BlockPosition((int) this.locX, (int) this.locY, (int) this.locZ), 0);
      }
-@@ -517,11 +544,12 @@
+@@ -536,11 +563,12 @@
      }
  
      public void die(DamageSource damagesource) {
diff --git a/nms-patches/FoodMetaData.patch b/nms-patches/FoodMetaData.patch
index 3f9a0a9f3f..24d17772d4 100644
--- a/nms-patches/FoodMetaData.patch
+++ b/nms-patches/FoodMetaData.patch
@@ -64,7 +64,7 @@
                  this.a(f);
                  this.foodTickTimer = 0;
              }
-         } else if (flag && this.foodLevel >= 18 && entityhuman.cU()) {
+         } else if (flag && this.foodLevel >= 18 && entityhuman.cY()) {
              ++this.foodTickTimer;
              if (this.foodTickTimer >= 80) {
 -                entityhuman.heal(1.0F);
diff --git a/nms-patches/HandshakeListener.patch b/nms-patches/HandshakeListener.patch
index a03c85d9ca..c408ba7c1f 100644
--- a/nms-patches/HandshakeListener.patch
+++ b/nms-patches/HandshakeListener.patch
@@ -57,8 +57,8 @@
 +            }
 +            // CraftBukkit end
 +
-             if (packethandshakinginsetprotocol.b() > 110) {
-                 chatcomponenttext = new ChatComponentText("Outdated server! I\'m still on 1.9.4");
+             if (packethandshakinginsetprotocol.b() > 210) {
+                 chatcomponenttext = new ChatComponentText("Outdated server! I\'m still on 1.10");
                  this.b.sendPacket(new PacketLoginOutDisconnect(chatcomponenttext));
 @@ -26,6 +71,7 @@
                  this.b.close(chatcomponenttext);
diff --git a/nms-patches/InventoryCraftResult.patch b/nms-patches/InventoryCraftResult.patch
index 9434a528d8..a87e7e4214 100644
--- a/nms-patches/InventoryCraftResult.patch
+++ b/nms-patches/InventoryCraftResult.patch
@@ -12,7 +12,7 @@
  
  public class InventoryCraftResult implements IInventory {
  
-     private ItemStack[] items = new ItemStack[1];
+     private final ItemStack[] items = new ItemStack[1];
  
 +    // CraftBukkit start
 +    private int maxStack = MAX_STACK;
diff --git a/nms-patches/InventoryLargeChest.patch b/nms-patches/InventoryLargeChest.patch
index 17df409c36..253d591a84 100644
--- a/nms-patches/InventoryLargeChest.patch
+++ b/nms-patches/InventoryLargeChest.patch
@@ -15,8 +15,8 @@
  public class InventoryLargeChest implements ITileInventory {
  
 @@ -8,6 +15,48 @@
-     public ITileInventory left;
-     public ITileInventory right;
+     public final ITileInventory left;
+     public final ITileInventory right;
  
 +    // CraftBukkit start - add fields and methods
 +    public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>();
diff --git a/nms-patches/ItemArmor.patch b/nms-patches/ItemArmor.patch
index 28909e7558..ad7f06eaac 100644
--- a/nms-patches/ItemArmor.patch
+++ b/nms-patches/ItemArmor.patch
@@ -12,7 +12,7 @@
  public class ItemArmor extends Item {
  
      private static final int[] n = new int[] { 13, 15, 16, 11};
-@@ -36,7 +41,33 @@
+@@ -32,7 +37,33 @@
          } else {
              EntityLiving entityliving = (EntityLiving) list.get(0);
              EnumItemSlot enumitemslot = EntityInsentient.d(itemstack);
@@ -47,7 +47,7 @@
  
              itemstack1.count = 1;
              entityliving.setSlot(enumitemslot, itemstack1);
-@@ -44,7 +75,7 @@
+@@ -40,7 +71,7 @@
                  ((EntityInsentient) entityliving).a(enumitemslot, 2.0F);
              }
  
diff --git a/nms-patches/ItemChorusFruit.patch b/nms-patches/ItemChorusFruit.patch
index 2c528c32b0..24c4303823 100644
--- a/nms-patches/ItemChorusFruit.patch
+++ b/nms-patches/ItemChorusFruit.patch
@@ -12,7 +12,7 @@
  
  public class ItemChorusFruit extends ItemFood {
  
-@@ -22,7 +27,21 @@
+@@ -22,6 +27,20 @@
                  double d4 = MathHelper.a(entityliving.locY + (double) (entityliving.getRandom().nextInt(16) - 8), 0.0D, (double) (world.Z() - 1));
                  double d5 = entityliving.locZ + (entityliving.getRandom().nextDouble() - 0.5D) * 16.0D;
  
@@ -28,9 +28,8 @@
 +                    d4 = teleEvent.getTo().getY();
 +                    d5 = teleEvent.getTo().getZ();
 +                }
++                // CraftBukkit end
 +
-                 if (entityliving.k(d3, d4, d5)) {
-+                    // CraftBukkit end
-                     world.a((EntityHuman) null, d0, d1, d2, SoundEffects.af, SoundCategory.PLAYERS, 1.0F, 1.0F);
-                     entityliving.a(SoundEffects.af, 1.0F, 1.0F);
-                     break;
+                 if (entityliving.isPassenger()) {
+                     entityliving.stopRiding();
+                 }
diff --git a/nms-patches/ItemFireball.patch b/nms-patches/ItemFireball.patch
index 6368e6a696..ca644d64d4 100644
--- a/nms-patches/ItemFireball.patch
+++ b/nms-patches/ItemFireball.patch
@@ -12,6 +12,6 @@
 +                        return EnumInteractionResult.PASS;
 +                    }
 +                    // CraftBukkit end
-                     world.a((EntityHuman) null, blockposition, SoundEffects.bm, SoundCategory.BLOCKS, 1.0F, (ItemFireball.j.nextFloat() - ItemFireball.j.nextFloat()) * 0.2F + 1.0F);
+                     world.a((EntityHuman) null, blockposition, SoundEffects.bn, SoundCategory.BLOCKS, 1.0F, (ItemFireball.j.nextFloat() - ItemFireball.j.nextFloat()) * 0.2F + 1.0F);
                      world.setTypeUpdate(blockposition, Blocks.FIRE.getBlockData());
                  }
diff --git a/nms-patches/ItemFlintAndSteel.patch b/nms-patches/ItemFlintAndSteel.patch
index 928d8ce957..39a667dea0 100644
--- a/nms-patches/ItemFlintAndSteel.patch
+++ b/nms-patches/ItemFlintAndSteel.patch
@@ -10,6 +10,6 @@
 +                    return EnumInteractionResult.PASS;
 +                }
 +                // CraftBukkit end
-                 world.a(entityhuman, blockposition, SoundEffects.bx, SoundCategory.BLOCKS, 1.0F, ItemFlintAndSteel.j.nextFloat() * 0.4F + 0.8F);
+                 world.a(entityhuman, blockposition, SoundEffects.by, SoundCategory.BLOCKS, 1.0F, ItemFlintAndSteel.j.nextFloat() * 0.4F + 0.8F);
                  world.setTypeAndData(blockposition, Blocks.FIRE.getBlockData(), 11);
              }
diff --git a/nms-patches/ItemMonsterEgg.patch b/nms-patches/ItemMonsterEgg.patch
index 357a360353..cd535c79a4 100644
--- a/nms-patches/ItemMonsterEgg.patch
+++ b/nms-patches/ItemMonsterEgg.patch
@@ -1,11 +1,9 @@
 --- a/net/minecraft/server/ItemMonsterEgg.java
 +++ b/net/minecraft/server/ItemMonsterEgg.java
-@@ -130,7 +130,11 @@
-     }
+@@ -131,6 +131,10 @@
  
      @Nullable
--    public static Entity a(World world, @Nullable String s, double d0, double d1, double d2) {
-+    public static Entity a(World world, @Nullable String s, double d0, double d1, double d2) {        // CraftBukkit start - delegate to spawnCreature
+     public static Entity a(World world, @Nullable String s, double d0, double d1, double d2) {
 +        return spawnCreature(world, s, d0, d1, d2, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.SPAWNER_EGG);
 +    }
 +
@@ -14,8 +12,8 @@
              Entity entity = null;
  
 @@ -143,8 +147,13 @@
-                     entityinsentient.aP = entityinsentient.yaw;
-                     entityinsentient.aN = entityinsentient.yaw;
+                     entityinsentient.aQ = entityinsentient.yaw;
+                     entityinsentient.aO = entityinsentient.yaw;
                      entityinsentient.prepare(world.D(new BlockPosition(entityinsentient)), (GroupDataEntity) null);
 -                    world.addEntity(entity);
 -                    entityinsentient.D();
diff --git a/nms-patches/ItemSnowball.patch b/nms-patches/ItemSnowball.patch
index a247a662b0..e2a91644a6 100644
--- a/nms-patches/ItemSnowball.patch
+++ b/nms-patches/ItemSnowball.patch
@@ -10,7 +10,7 @@
              --itemstack.count;
          }
  
-         world.a((EntityHuman) null, entityhuman.locX, entityhuman.locY, entityhuman.locZ, SoundEffects.fH, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemSnowball.j.nextFloat() * 0.4F + 0.8F));
+         world.a((EntityHuman) null, entityhuman.locX, entityhuman.locY, entityhuman.locZ, SoundEffects.fS, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemSnowball.j.nextFloat() * 0.4F + 0.8F));
 +        */
          if (!world.isClientSide) {
              EntitySnowball entitysnowball = new EntitySnowball(world, entityhuman);
@@ -22,7 +22,7 @@
 +                    --itemstack.count;
 +                }
 +
-+                world.a((EntityHuman) null, entityhuman.locX, entityhuman.locY, entityhuman.locZ, SoundEffects.fH, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemSnowball.j.nextFloat() * 0.4F + 0.8F));
++                world.a((EntityHuman) null, entityhuman.locX, entityhuman.locY, entityhuman.locZ, SoundEffects.fS, SoundCategory.NEUTRAL, 0.5F, 0.4F / (ItemSnowball.j.nextFloat() * 0.4F + 0.8F));
 +            } else if (entityhuman instanceof EntityPlayer) {
 +                ((EntityPlayer) entityhuman).getBukkitEntity().updateInventory();
 +            }
diff --git a/nms-patches/ItemStack.patch b/nms-patches/ItemStack.patch
index 26e1bdd7b9..4101e90643 100644
--- a/nms-patches/ItemStack.patch
+++ b/nms-patches/ItemStack.patch
@@ -20,8 +20,8 @@
  public final class ItemStack {
  
      public static final DecimalFormat a = new DecimalFormat("#.##");
-@@ -47,10 +60,20 @@
-         this.k = false;
+@@ -43,10 +56,20 @@
+     public ItemStack(Item item, int i, int j) {
          this.item = item;
          this.count = i;
 -        this.damage = j;
@@ -44,7 +44,7 @@
  
      }
  
-@@ -85,11 +108,131 @@
+@@ -81,11 +104,131 @@
      }
  
      public EnumInteractionResult placeItem(EntityHuman entityhuman, World world, BlockPosition blockposition, EnumHand enumhand, EnumDirection enumdirection, float f, float f1, float f2) {
@@ -177,7 +177,7 @@
  
          return enuminteractionresult;
      }
-@@ -114,7 +257,7 @@
+@@ -110,7 +253,7 @@
          nbttagcompound.setByte("Count", (byte) this.count);
          nbttagcompound.setShort("Damage", (short) this.damage);
          if (this.tag != null) {
@@ -186,7 +186,7 @@
          }
  
          return nbttagcompound;
-@@ -123,13 +266,18 @@
+@@ -119,13 +262,18 @@
      public void c(NBTTagCompound nbttagcompound) {
          this.item = Item.d(nbttagcompound.getString("id"));
          this.count = nbttagcompound.getByte("Count");
@@ -206,7 +206,7 @@
              if (this.item != null) {
                  this.item.a(this.tag);
              }
-@@ -166,11 +314,30 @@
+@@ -162,11 +310,30 @@
      }
  
      public void setData(int i) {
@@ -239,7 +239,7 @@
      }
  
      public int j() {
-@@ -218,6 +385,12 @@
+@@ -214,6 +381,12 @@
                          this.count = 0;
                      }
  
@@ -252,7 +252,7 @@
                      this.damage = 0;
                  }
  
-@@ -518,6 +691,7 @@
+@@ -514,6 +687,7 @@
      @Deprecated
      public void setItem(Item item) {
          this.item = item;
diff --git a/nms-patches/LoginListener.patch b/nms-patches/LoginListener.patch
index 96ef85f2a7..ae5fb65559 100644
--- a/nms-patches/LoginListener.patch
+++ b/nms-patches/LoginListener.patch
@@ -14,7 +14,7 @@
  
      private static final AtomicInteger b = new AtomicInteger(0);
 @@ -32,6 +38,7 @@
-     private String j;
+     private final String j;
      private SecretKey loginKey;
      private EntityPlayer l;
 +    public String hostname = ""; // CraftBukkit - add field
@@ -99,18 +99,9 @@
 +                                }
 +                            }
 +                            // CraftBukkit end
-                             LoginListener.c.info("UUID of player " + LoginListener.this.i.getName() + " is " + LoginListener.this.i.getId());
+                             LoginListener.c.info("UUID of player {} is {}", new Object[] { LoginListener.this.i.getName(), LoginListener.this.i.getId()});
                              LoginListener.this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT;
                          } else if (LoginListener.this.server.R()) {
-@@ -156,7 +202,7 @@
-                             LoginListener.this.g = LoginListener.EnumProtocolState.READY_TO_ACCEPT;
-                         } else {
-                             LoginListener.this.disconnect("Failed to verify username!");
--                            LoginListener.c.error("Username \'" + gameprofile.getName() + "\' tried to join with an invalid session");
-+                            LoginListener.c.error("Username \'" + gameprofile.getName() + "\' tried to join with an invalid session"); // CraftBukkit - fix null pointer
-                         }
-                     } catch (AuthenticationUnavailableException authenticationunavailableexception) {
-                         if (LoginListener.this.server.R()) {
 @@ -167,6 +213,11 @@
                              LoginListener.this.disconnect("Authentication servers are down. Please try again later, sorry!");
                              LoginListener.c.error("Couldn\'t verify username because servers are unavailable");
diff --git a/nms-patches/MethodProfiler.patch b/nms-patches/MethodProfiler.patch
index 0b080a61ff..f190cb358a 100644
--- a/nms-patches/MethodProfiler.patch
+++ b/nms-patches/MethodProfiler.patch
@@ -49,10 +49,10 @@
 -            }
 -
 -            if (k > 100000000L) {
--                MethodProfiler.b.warn("Something\'s taking too long! \'" + this.e + "\' took aprox " + (double) k / 1000000.0D + " ms");
+-                MethodProfiler.b.warn("Something\'s taking too long! \'{}\' took aprox {} ms", new Object[] { this.e, Double.valueOf((double) k / 1000000.0D)});
 -            }
 -
--            this.e = !this.c.isEmpty() ? (String) this.c.get(this.c.size() - 1) : "";
+-            this.e = this.c.isEmpty() ? "" : (String) this.c.get(this.c.size() - 1);
 -        }
      }
  
diff --git a/nms-patches/MinecraftServer.patch b/nms-patches/MinecraftServer.patch
index 429c3f773c..f0a5cfb3a8 100644
--- a/nms-patches/MinecraftServer.patch
+++ b/nms-patches/MinecraftServer.patch
@@ -230,10 +230,10 @@
          this.l();
 @@ -212,25 +337,38 @@
          this.b("menu.generatingTerrain");
-         byte b0 = 0;
+         boolean flag4 = false;
  
--        MinecraftServer.LOGGER.info("Preparing start region for level " + b0);
--        WorldServer worldserver = this.worldServer[b0];
+-        MinecraftServer.LOGGER.info("Preparing start region for level 0");
+-        WorldServer worldserver = this.worldServer[0];
 -        BlockPosition blockposition = worldserver.getSpawn();
 -        long j = av();
 -
@@ -344,21 +344,22 @@
          }
  
          if (this.worldServer != null) {
-@@ -315,11 +474,13 @@
- 
-             this.saveChunks(false);
+@@ -321,12 +480,14 @@
+             aworldserver = this.worldServer;
+             i = aworldserver.length;
  
 +            /* CraftBukkit start - Handled in saveChunks
-             for (i = 0; i < this.worldServer.length; ++i) {
-                 if (this.worldServer[i] != null) {
-                     this.worldServer[i].saveLevel();
+             for (j = 0; j < i; ++j) {
+                 worldserver = aworldserver[j];
+                 if (worldserver != null) {
+                     worldserver.saveLevel();
                  }
              }
 +            // CraftBukkit end */
          }
  
          if (this.m.d()) {
-@@ -359,6 +520,7 @@
+@@ -366,6 +527,7 @@
                      long k = j - this.aa;
  
                      if (k > 2000L && this.aa - this.Q >= 15000L) {
@@ -366,7 +367,7 @@
                          MinecraftServer.LOGGER.warn("Can\'t keep up! Did the system time change, or is the server overloaded? Running {}ms behind, skipping {} tick(s)", new Object[] { Long.valueOf(k), Long.valueOf(k / 50L)});
                          k = 2000L;
                          this.Q = this.aa;
-@@ -371,11 +533,12 @@
+@@ -378,11 +540,12 @@
  
                      i += k;
                      this.aa = j;
@@ -380,7 +381,7 @@
                              i -= 50L;
                              this.C();
                          }
-@@ -413,6 +576,12 @@
+@@ -420,6 +583,12 @@
              } catch (Throwable throwable1) {
                  MinecraftServer.LOGGER.error("Exception stopping the server", throwable1);
              } finally {
@@ -393,16 +394,16 @@
                  this.B();
              }
  
-@@ -456,7 +625,7 @@
+@@ -463,7 +632,7 @@
  
-     protected void B() {}
+     public void B() {}
  
 -    protected void C() {
 +    protected void C() throws ExceptionWorldConflict { // CraftBukkit - added throws
          long i = System.nanoTime();
  
          ++this.ticks;
-@@ -482,7 +651,7 @@
+@@ -489,7 +658,7 @@
              this.q.b().a(agameprofile);
          }
  
@@ -411,7 +412,7 @@
              this.methodProfiler.a("save");
              this.v.savePlayers();
              this.saveChunks(true);
-@@ -517,20 +686,40 @@
+@@ -524,20 +693,40 @@
  
          this.methodProfiler.c("levels");
  
@@ -455,7 +456,7 @@
  
                  this.methodProfiler.a("tick");
  
-@@ -557,9 +746,9 @@
+@@ -564,9 +753,9 @@
                  worldserver.getTracker().updatePlayers();
                  this.methodProfiler.b();
                  this.methodProfiler.b();
@@ -467,7 +468,7 @@
          }
  
          this.methodProfiler.c("connection");
-@@ -583,10 +772,11 @@
+@@ -590,10 +779,11 @@
          this.o.add(itickable);
      }
  
@@ -480,7 +481,7 @@
              boolean flag = true;
              String s = null;
              String s1 = ".";
-@@ -631,13 +821,16 @@
+@@ -638,13 +828,16 @@
                      ++j;
                  }
              }
@@ -498,7 +499,7 @@
              if (s != null) {
                  dedicatedserver.i(s);
              }
-@@ -668,6 +861,25 @@
+@@ -675,6 +868,25 @@
                      dedicatedserver.stop();
                  }
              });
@@ -524,7 +525,7 @@
          } catch (Exception exception) {
              MinecraftServer.LOGGER.fatal("Failed to start the minecraft server", exception);
          }
-@@ -675,8 +887,10 @@
+@@ -682,8 +894,10 @@
      }
  
      public void F() {
@@ -535,7 +536,7 @@
      }
  
      public File d(String s) {
-@@ -692,7 +906,14 @@
+@@ -699,7 +913,14 @@
      }
  
      public WorldServer getWorldServer(int i) {
@@ -551,7 +552,7 @@
      }
  
      public String getVersion() {
-@@ -716,7 +937,7 @@
+@@ -723,7 +944,7 @@
      }
  
      public boolean isDebugging() {
@@ -560,7 +561,7 @@
      }
  
      public void g(String s) {
-@@ -731,7 +952,7 @@
+@@ -738,7 +959,7 @@
      }
  
      public String getServerModName() {
@@ -569,7 +570,7 @@
      }
  
      public CrashReport b(CrashReport crashreport) {
-@@ -760,6 +981,7 @@
+@@ -767,6 +988,7 @@
      }
  
      public List<String> tabCompleteCommand(ICommandListener icommandlistener, String s, @Nullable BlockPosition blockposition, boolean flag) {
@@ -577,7 +578,7 @@
          ArrayList arraylist = Lists.newArrayList();
          boolean flag1 = s.startsWith("/");
  
-@@ -802,10 +1024,13 @@
+@@ -809,10 +1031,13 @@
  
              return arraylist;
          }
@@ -592,35 +593,42 @@
      }
  
      public String getName() {
-@@ -861,8 +1086,10 @@
+@@ -868,11 +1093,13 @@
      }
  
      public void a(EnumDifficulty enumdifficulty) {
--        for (int i = 0; i < this.worldServer.length; ++i) {
--            WorldServer worldserver = this.worldServer[i];
+-        WorldServer[] aworldserver = this.worldServer;
+-        int i = aworldserver.length;
 +        // CraftBukkit start
-+        for (int i = 0; i < this.worlds.size(); ++i) {
-+            WorldServer worldserver = this.worlds.get(i);
++        // WorldServer[] aworldserver = this.worldServer;
++        int i = this.worlds.size();
+ 
+         for (int j = 0; j < i; ++j) {
+-            WorldServer worldserver = aworldserver[j];
++            WorldServer worldserver = this.worlds.get(j);
 +            // CraftBukkit end
  
              if (worldserver != null) {
                  if (worldserver.getWorldData().isHardcore()) {
-@@ -929,9 +1156,11 @@
+@@ -939,13 +1166,11 @@
          int i = 0;
  
          if (this.worldServer != null) {
--            for (int j = 0; j < this.worldServer.length; ++j) {
--                if (this.worldServer[j] != null) {
--                    WorldServer worldserver = this.worldServer[j];
+-            WorldServer[] aworldserver = this.worldServer;
+-            int j = aworldserver.length;
+-
+-            for (int k = 0; k < j; ++k) {
+-                WorldServer worldserver = aworldserver[k];
+-
 +            // CraftBukkit start
 +            for (int j = 0; j < this.worlds.size(); ++j) {
 +                WorldServer worldserver = this.worlds.get(j);
-+                if (worldserver != null) {
+                 if (worldserver != null) {
 +                    // CraftBukkit end
                      WorldData worlddata = worldserver.getWorldData();
  
                      mojangstatisticsgenerator.a("world[" + i + "][dimension]", Integer.valueOf(worldserver.worldProvider.getDimensionManager().getDimensionID()));
-@@ -964,7 +1193,7 @@
+@@ -978,7 +1203,7 @@
      public abstract boolean aa();
  
      public boolean getOnlineMode() {
@@ -629,19 +637,24 @@
      }
  
      public void setOnlineMode(boolean flag) {
-@@ -1036,8 +1265,9 @@
+@@ -1050,13 +1275,9 @@
      }
  
-     public void setGamemode(WorldSettings.EnumGamemode worldsettings_enumgamemode) {
--        for (int i = 0; i < this.worldServer.length; ++i) {
--            this.worldServer[i].getWorldData().setGameType(worldsettings_enumgamemode);
+     public void setGamemode(EnumGamemode enumgamemode) {
+-        WorldServer[] aworldserver = this.worldServer;
+-        int i = aworldserver.length;
+-
+-        for (int j = 0; j < i; ++j) {
+-            WorldServer worldserver = aworldserver[j];
+-
+-            worldserver.getWorldData().setGameType(enumgamemode);
 +        // CraftBukkit start
 +        for (int i = 0; i < this.worlds.size(); ++i) {
-+            worlds.get(i).getWorldData().setGameType(worldsettings_enumgamemode);
++            worlds.get(i).getWorldData().setGameType(enumgamemode);
          }
  
      }
-@@ -1069,7 +1299,7 @@
+@@ -1088,7 +1309,7 @@
      }
  
      public World getWorld() {
@@ -650,7 +663,7 @@
      }
  
      public Entity f() {
-@@ -1141,8 +1371,10 @@
+@@ -1160,8 +1381,10 @@
          WorldServer[] aworldserver = this.worldServer;
          int i = aworldserver.length;
  
@@ -663,7 +676,7 @@
  
              if (worldserver != null) {
                  Entity entity = worldserver.getEntity(uuid);
-@@ -1157,7 +1389,7 @@
+@@ -1176,7 +1399,7 @@
      }
  
      public boolean getSendCommandFeedback() {
@@ -672,7 +685,7 @@
      }
  
      public void a(CommandObjectiveExecutor.EnumCommandResult commandobjectiveexecutor_enumcommandresult, int i) {}
-@@ -1172,7 +1404,7 @@
+@@ -1191,7 +1414,7 @@
  
      public <V> ListenableFuture<V> a(Callable<V> callable) {
          Validate.notNull(callable);
@@ -681,7 +694,7 @@
              ListenableFutureTask listenablefuturetask = ListenableFutureTask.create(callable);
              Queue queue = this.j;
  
-@@ -1217,4 +1449,11 @@
+@@ -1236,4 +1459,11 @@
      public int a(@Nullable WorldServer worldserver) {
          return worldserver != null ? worldserver.getGameRules().c("spawnRadius") : 10;
      }
diff --git a/nms-patches/MobEffectList.patch b/nms-patches/MobEffectList.patch
index 5d91cf59d6..c2e9b5e2d2 100644
--- a/nms-patches/MobEffectList.patch
+++ b/nms-patches/MobEffectList.patch
@@ -53,8 +53,8 @@
 +                ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutUpdateHealth(((EntityPlayer) entityhuman).getBukkitEntity().getScaledHealth(), entityhuman.getFoodData().foodLevel, entityhuman.getFoodData().saturationLevel));
 +                // CraftBukkit end
              }
-         } else if ((this != MobEffects.HEAL || entityliving.bQ()) && (this != MobEffects.HARM || !entityliving.bQ())) {
-             if (this == MobEffects.HARM && !entityliving.bQ() || this == MobEffects.HEAL && entityliving.bQ()) {
+         } else if ((this != MobEffects.HEAL || entityliving.bS()) && (this != MobEffects.HARM || !entityliving.bS())) {
+             if (this == MobEffects.HARM && !entityliving.bS() || this == MobEffects.HEAL && entityliving.bS()) {
                  entityliving.damageEntity(DamageSource.MAGIC, (float) (6 << i));
              }
          } else {
@@ -77,8 +77,8 @@
          MobEffectList.REGISTRY.a(26, new MinecraftKey("luck"), (new MobEffectList(false, 3381504)).c("effect.luck").b(5, 2).j().a(GenericAttributes.i, "03C3C89D-7037-4B42-869F-B146BCB64D2E", 1.0D, 0));
          MobEffectList.REGISTRY.a(27, new MinecraftKey("unluck"), (new MobEffectList(true, 12624973)).c("effect.unluck").b(6, 2).a(GenericAttributes.i, "CC5AF142-2BD2-4215-B636-2605AED11727", -1.0D, 0));
 +        // CraftBukkit start
-+        for (MobEffectList effect : REGISTRY) {
-+            org.bukkit.potion.PotionEffectType.registerPotionEffectType(new org.bukkit.craftbukkit.potion.CraftPotionEffectType(effect));
++        for (Object effect : REGISTRY) {
++            org.bukkit.potion.PotionEffectType.registerPotionEffectType(new org.bukkit.craftbukkit.potion.CraftPotionEffectType((MobEffectList) effect));
 +        }
 +        // CraftBukkit end
      }
diff --git a/nms-patches/NameReferencingFileConverter.patch b/nms-patches/NameReferencingFileConverter.patch
index 82806a36dc..b591ecbb71 100644
--- a/nms-patches/NameReferencingFileConverter.patch
+++ b/nms-patches/NameReferencingFileConverter.patch
@@ -5,10 +5,10 @@
                  try {
                      gameprofilebanlist.load();
 -                } catch (FileNotFoundException filenotfoundexception) {
--                    NameReferencingFileConverter.e.warn("Could not load existing file " + gameprofilebanlist.c().getName(), filenotfoundexception);
+-                    NameReferencingFileConverter.e.warn("Could not load existing file {}", new Object[] { gameprofilebanlist.c().getName(), filenotfoundexception});
 +                // CraftBukkit start - FileNotFoundException -> IOException, don't print stacetrace
 +                } catch (IOException filenotfoundexception) {
-+                    NameReferencingFileConverter.e.warn("Could not load existing file " + gameprofilebanlist.c().getName());
++                    NameReferencingFileConverter.e.warn("Could not load existing file {}", new Object[] { gameprofilebanlist.c().getName()});
                  }
              }
  
@@ -17,10 +17,10 @@
                  try {
                      ipbanlist.load();
 -                } catch (FileNotFoundException filenotfoundexception) {
--                    NameReferencingFileConverter.e.warn("Could not load existing file " + ipbanlist.c().getName(), filenotfoundexception);
+-                    NameReferencingFileConverter.e.warn("Could not load existing file {}", new Object[] { ipbanlist.c().getName(), filenotfoundexception});
 +                // CraftBukkit start - FileNotFoundException -> IOException, don't print stacetrace
 +                } catch (IOException filenotfoundexception) {
-+                    NameReferencingFileConverter.e.warn("Could not load existing file " + ipbanlist.c().getName());
++                    NameReferencingFileConverter.e.warn("Could not load existing file {}", new Object[] { ipbanlist.c().getName()});
                  }
              }
  
@@ -29,10 +29,10 @@
                  try {
                      oplist.load();
 -                } catch (FileNotFoundException filenotfoundexception) {
--                    NameReferencingFileConverter.e.warn("Could not load existing file " + oplist.c().getName(), filenotfoundexception);
+-                    NameReferencingFileConverter.e.warn("Could not load existing file {}", new Object[] { oplist.c().getName(), filenotfoundexception});
 +                // CraftBukkit start - FileNotFoundException -> IOException, don't print stacetrace
 +                } catch (IOException filenotfoundexception) {
-+                    NameReferencingFileConverter.e.warn("Could not load existing file " + oplist.c().getName());
++                    NameReferencingFileConverter.e.warn("Could not load existing file {}", new Object[] { oplist.c().getName()});
                  }
              }
  
@@ -41,10 +41,10 @@
                  try {
                      whitelist.load();
 -                } catch (FileNotFoundException filenotfoundexception) {
--                    NameReferencingFileConverter.e.warn("Could not load existing file " + whitelist.c().getName(), filenotfoundexception);
+-                    NameReferencingFileConverter.e.warn("Could not load existing file {}", new Object[] { whitelist.c().getName(), filenotfoundexception});
 +                // CraftBukkit start - FileNotFoundException -> IOException, don't print stacetrace
 +                } catch (IOException filenotfoundexception) {
-+                    NameReferencingFileConverter.e.warn("Could not load existing file " + whitelist.c().getName());
++                    NameReferencingFileConverter.e.warn("Could not load existing file {}", new Object[] { whitelist.c().getName()});
                  }
              }
  
@@ -79,7 +79,16 @@
                          NameReferencingFileConverter.b(file);
                          if (!file1.renameTo(file3)) {
                              throw new NameReferencingFileConverter.FileConversionException("Could not convert file for " + s, null);
-@@ -467,7 +495,7 @@
+@@ -358,7 +386,7 @@
+ 
+                     private String a(GameProfile gameprofile) {
+                         String s = null;
+-                        String[] astring = astring1;
++                        // String[] astring = astring1; // CraftBukkit - decompile error
+                         int i = astring.length;
+ 
+                         for (int j = 0; j < i; ++j) {
+@@ -471,7 +499,7 @@
  
      private static File d(PropertyManager propertymanager) {
          String s = propertymanager.getString("level-name", "world");
diff --git a/nms-patches/PacketDataSerializer.patch b/nms-patches/PacketDataSerializer.patch
index 4be816eaf2..00bc7794f8 100644
--- a/nms-patches/PacketDataSerializer.patch
+++ b/nms-patches/PacketDataSerializer.patch
@@ -9,7 +9,7 @@
  public class PacketDataSerializer extends ByteBuf {
  
      private final ByteBuf a;
-@@ -120,7 +122,7 @@
+@@ -128,7 +130,7 @@
      }
  
      public <T extends Enum<T>> T a(Class<T> oclass) {
@@ -18,7 +18,7 @@
      }
  
      public PacketDataSerializer a(Enum<?> oenum) {
-@@ -197,7 +199,7 @@
+@@ -205,7 +207,7 @@
          } else {
              try {
                  NBTCompressedStreamTools.a(nbttagcompound, (DataOutput) (new ByteBufOutputStream(this)));
@@ -27,7 +27,7 @@
                  throw new EncoderException(ioexception);
              }
          }
-@@ -224,7 +226,7 @@
+@@ -232,7 +234,7 @@
      }
  
      public PacketDataSerializer a(@Nullable ItemStack itemstack) {
@@ -36,7 +36,7 @@
              this.writeShort(-1);
          } else {
              this.writeShort(Item.getId(itemstack.getItem()));
-@@ -253,6 +255,11 @@
+@@ -261,6 +263,11 @@
  
              itemstack = new ItemStack(Item.getById(short0), b0, short1);
              itemstack.setTag(this.j());
diff --git a/nms-patches/PathfinderGoalDefendVillage.patch b/nms-patches/PathfinderGoalDefendVillage.patch
index ab0ddc41ca..aa468d3474 100644
--- a/nms-patches/PathfinderGoalDefendVillage.patch
+++ b/nms-patches/PathfinderGoalDefendVillage.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/PathfinderGoalDefendVillage.java
 +++ b/net/minecraft/server/PathfinderGoalDefendVillage.java
-@@ -34,7 +34,7 @@
+@@ -32,7 +32,7 @@
      }
  
      public void c() {
diff --git a/nms-patches/PathfinderGoalHorseTrap.patch b/nms-patches/PathfinderGoalHorseTrap.patch
index 773ca83d4c..c20e929d7a 100644
--- a/nms-patches/PathfinderGoalHorseTrap.patch
+++ b/nms-patches/PathfinderGoalHorseTrap.patch
@@ -28,8 +28,8 @@
  
 @@ -61,7 +62,7 @@
  
-         EnchantmentManager.a(entityskeleton.getRandom(), entityskeleton.getItemInMainHand(), (int) (5.0F + difficultydamagescaler.c() * (float) entityskeleton.getRandom().nextInt(18)), false);
-         EnchantmentManager.a(entityskeleton.getRandom(), entityskeleton.getEquipment(EnumItemSlot.HEAD), (int) (5.0F + difficultydamagescaler.c() * (float) entityskeleton.getRandom().nextInt(18)), false);
+         EnchantmentManager.a(entityskeleton.getRandom(), entityskeleton.getItemInMainHand(), (int) (5.0F + difficultydamagescaler.d() * (float) entityskeleton.getRandom().nextInt(18)), false);
+         EnchantmentManager.a(entityskeleton.getRandom(), entityskeleton.getEquipment(EnumItemSlot.HEAD), (int) (5.0F + difficultydamagescaler.d() * (float) entityskeleton.getRandom().nextInt(18)), false);
 -        entityskeleton.world.addEntity(entityskeleton);
 +        if (!entityskeleton.world.addEntity(entityskeleton, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.JOCKEY)) return null; // CraftBukkit
          return entityskeleton;
diff --git a/nms-patches/PathfinderGoalHurtByTarget.patch b/nms-patches/PathfinderGoalHurtByTarget.patch
index c928c89204..bf9f166640 100644
--- a/nms-patches/PathfinderGoalHurtByTarget.patch
+++ b/nms-patches/PathfinderGoalHurtByTarget.patch
@@ -7,9 +7,9 @@
 -        this.e.setGoalTarget(this.e.getLastDamager());
 +        this.e.setGoalTarget(this.e.getLastDamager(), org.bukkit.event.entity.EntityTargetEvent.TargetReason.TARGET_ATTACKED_ENTITY, true); // CraftBukkit - reason
          this.g = this.e.getGoalTarget();
-         this.b = this.e.bI();
+         this.b = this.e.bK();
          this.h = 300;
-@@ -61,6 +61,6 @@
+@@ -66,6 +66,6 @@
      }
  
      protected void a(EntityCreature entitycreature, EntityLiving entityliving) {
diff --git a/nms-patches/PathfinderGoalMakeLove.patch b/nms-patches/PathfinderGoalMakeLove.patch
index 5edee4ccbb..400761c08f 100644
--- a/nms-patches/PathfinderGoalMakeLove.patch
+++ b/nms-patches/PathfinderGoalMakeLove.patch
@@ -1,7 +1,7 @@
 --- a/net/minecraft/server/PathfinderGoalMakeLove.java
 +++ b/net/minecraft/server/PathfinderGoalMakeLove.java
 @@ -87,7 +87,7 @@
-         this.b.r(false);
+         this.b.s(false);
          entityvillager.setAgeRaw(-24000);
          entityvillager.setPositionRotation(this.b.locX, this.b.locY, this.b.locZ, 0.0F, 0.0F);
 -        this.d.addEntity(entityvillager);
diff --git a/nms-patches/PathfinderGoalNearestAttackableTarget.patch b/nms-patches/PathfinderGoalNearestAttackableTarget.patch
index 268fcde9ba..09c3172eea 100644
--- a/nms-patches/PathfinderGoalNearestAttackableTarget.patch
+++ b/nms-patches/PathfinderGoalNearestAttackableTarget.patch
@@ -18,8 +18,8 @@
                  return true;
              }
          } else {
--            this.d = this.e.world.a(this.e.locX, this.e.locY + (double) this.e.getHeadHeight(), this.e.locZ, this.f(), this.f(), new Function() {
-+            this.d = (T) this.e.world.a(this.e.locX, this.e.locY + (double) this.e.getHeadHeight(), this.e.locZ, this.f(), this.f(), new Function<EntityHuman, Double>() { // CraftBukkit - fix decompile error
+-            this.d = this.e.world.a(this.e.locX, this.e.locY + (double) this.e.getHeadHeight(), this.e.locZ, this.i(), this.i(), new Function() {
++            this.d = (T) this.e.world.a(this.e.locX, this.e.locY + (double) this.e.getHeadHeight(), this.e.locZ, this.i(), this.i(), new Function<EntityHuman, Double>() { // CraftBukkit - fix decompile error
                  @Nullable
                  public Double a(@Nullable EntityHuman entityhuman) {
                      ItemStack itemstack = entityhuman.getEquipment(EnumItemSlot.HEAD);
diff --git a/nms-patches/PathfinderGoalPanic.patch b/nms-patches/PathfinderGoalPanic.patch
index 0ecc9b005e..41b58874ef 100644
--- a/nms-patches/PathfinderGoalPanic.patch
+++ b/nms-patches/PathfinderGoalPanic.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/PathfinderGoalPanic.java
 +++ b/net/minecraft/server/PathfinderGoalPanic.java
-@@ -46,6 +46,12 @@
+@@ -47,6 +47,12 @@
      }
  
      public boolean b() {
diff --git a/nms-patches/PlayerConnection.patch b/nms-patches/PlayerConnection.patch
index 57495a19d6..627b84a41e 100644
--- a/nms-patches/PlayerConnection.patch
+++ b/nms-patches/PlayerConnection.patch
@@ -1,14 +1,6 @@
 --- a/net/minecraft/server/PlayerConnection.java
 +++ b/net/minecraft/server/PlayerConnection.java
-@@ -3,7 +3,6 @@
- import com.google.common.collect.Lists;
- import com.google.common.primitives.Doubles;
- import com.google.common.primitives.Floats;
--import com.google.common.util.concurrent.Futures;
- import io.netty.buffer.Unpooled;
- import io.netty.util.concurrent.Future;
- import io.netty.util.concurrent.GenericFutureListener;
-@@ -17,6 +16,49 @@
+@@ -16,6 +16,49 @@
  import org.apache.logging.log4j.LogManager;
  import org.apache.logging.log4j.Logger;
  
@@ -58,7 +50,7 @@
  public class PlayerConnection implements PacketListenerPlayIn, ITickable {
  
      private static final Logger LOGGER = LogManager.getLogger();
-@@ -27,7 +69,10 @@
+@@ -26,7 +69,10 @@
      private int f;
      private long g;
      private long h;
@@ -70,7 +62,7 @@
      private int j;
      private final IntHashMap<Short> k = new IntHashMap();
      private double l;
-@@ -52,6 +97,7 @@
+@@ -51,6 +97,7 @@
      private int E;
      private int F;
      private int G;
@@ -78,7 +70,7 @@
  
      public PlayerConnection(MinecraftServer minecraftserver, NetworkManager networkmanager, EntityPlayer entityplayer) {
          this.minecraftServer = minecraftserver;
-@@ -59,7 +105,32 @@
+@@ -58,7 +105,32 @@
          networkmanager.setPacketListener(this);
          this.player = entityplayer;
          entityplayer.playerConnection = this;
@@ -109,9 +101,9 @@
 +    private final static HashSet<Integer> invalidItems = new HashSet<Integer>(java.util.Arrays.asList(8, 9, 10, 11, 26, 34, 36, 43, 51, 52, 55, 59, 60, 62, 63, 64, 68, 71, 74, 75, 83, 90, 92, 93, 94, 104, 105, 115, 117, 118, 119, 125, 127, 132, 140, 141, 142, 144)); // TODO: Check after every update.
 +    // CraftBukkit end
  
-     public void c() {
+     public void E_() {
          this.d();
-@@ -111,15 +182,21 @@
+@@ -110,15 +182,21 @@
          }
  
          this.minecraftServer.methodProfiler.b();
@@ -133,7 +125,7 @@
              this.disconnect("You have been idle for too long!");
          }
  
-@@ -139,19 +216,37 @@
+@@ -138,19 +216,37 @@
      }
  
      public void disconnect(String s) {
@@ -174,7 +166,7 @@
      }
  
      public void a(PacketPlayInSteerVehicle packetplayinsteervehicle) {
-@@ -190,7 +285,34 @@
+@@ -189,7 +285,34 @@
                  double d9 = entity.motX * entity.motX + entity.motY * entity.motY + entity.motZ * entity.motZ;
                  double d10 = d6 * d6 + d7 * d7 + d8 * d8;
  
@@ -207,10 +199,10 @@
 +
 +                if (d10 - d9 > Math.max(100, Math.pow((double) (10.0F * (float) i * speed), 2)) && (!this.minecraftServer.R() || !this.minecraftServer.Q().equals(entity.getName()))) {
 +                // CraftBukkit end
-                     PlayerConnection.LOGGER.warn(entity.getName() + " (vehicle of " + this.player.getName() + ") moved too quickly! " + d6 + "," + d7 + "," + d8);
+                     PlayerConnection.LOGGER.warn("{} (vehicle of {}) moved too quickly! {},{},{}", new Object[] { entity.getName(), this.player.getName(), Double.valueOf(d6), Double.valueOf(d7), Double.valueOf(d8)});
                      this.networkManager.sendPacket(new PacketPlayOutVehicleMove(entity));
                      return;
-@@ -228,6 +350,62 @@
+@@ -227,6 +350,62 @@
                      return;
                  }
  
@@ -273,7 +265,7 @@
                  this.minecraftServer.getPlayerList().d(this.player);
                  this.player.checkMovement(this.player.locX - d0, this.player.locY - d1, this.player.locZ - d2);
                  this.D = d11 >= -0.03125D && !this.minecraftServer.getAllowFlight() && !worldserver.d(entity.getBoundingBox().g(0.0625D).a(0.0D, -0.55D, 0.0D));
-@@ -262,7 +440,7 @@
+@@ -261,7 +440,7 @@
          } else {
              WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension);
  
@@ -282,7 +274,7 @@
                  if (this.e == 0) {
                      this.d();
                  }
-@@ -272,13 +450,21 @@
+@@ -271,13 +450,21 @@
                          this.A = this.e;
                          this.a(this.teleportPos.x, this.teleportPos.y, this.teleportPos.z, this.player.yaw, this.player.pitch);
                      }
@@ -305,18 +297,19 @@
                          double d0 = this.player.locX;
                          double d1 = this.player.locY;
                          double d2 = this.player.locZ;
-@@ -297,15 +483,33 @@
+@@ -296,15 +483,33 @@
                          ++this.F;
                          int i = this.F - this.G;
  
 -                        if (i > 5) {
+-                            PlayerConnection.LOGGER.debug("{} is sending move packets too frequently ({} packets since last tick)", new Object[] { this.player.getName(), Integer.valueOf(i)});
 +                        // CraftBukkit start - handle custom speeds and skipped ticks
 +                        this.allowedPlayerTicks += (System.currentTimeMillis() / 50) - this.lastTick;
 +                        this.allowedPlayerTicks = Math.max(this.allowedPlayerTicks, 1);
 +                        this.lastTick = (int) (System.currentTimeMillis() / 50);
 +
 +                        if (i > Math.max(this.allowedPlayerTicks, 5)) {
-                             PlayerConnection.LOGGER.debug(this.player.getName() + " is sending move packets too frequently (" + i + " packets since last tick)");
++                            PlayerConnection.LOGGER.debug(this.player.getName() + " is sending move packets too frequently (" + i + " packets since last tick)");
                              i = 1;
                          }
  
@@ -332,16 +325,16 @@
 +                            speed = player.abilities.walkSpeed * 10f;
 +                        }
 +
-                         if (!this.player.K() && (!this.player.x().getGameRules().getBoolean("disableElytraMovementCheck") || !this.player.cC())) {
-                             float f2 = this.player.cC() ? 300.0F : 100.0F;
+                         if (!this.player.K() && (!this.player.x().getGameRules().getBoolean("disableElytraMovementCheck") || !this.player.cG())) {
+                             float f2 = this.player.cG() ? 300.0F : 100.0F;
  
 -                            if (d11 - d10 > (double) (f2 * (float) i) && (!this.minecraftServer.R() || !this.minecraftServer.Q().equals(this.player.getName()))) {
 +                            if (d11 - d10 > Math.max(100, Math.pow((double) (10.0F * (float) i * speed), 2)) && (!this.minecraftServer.R() || !this.minecraftServer.Q().equals(this.player.getName()))) {
 +                        // CraftBukkit end
-                                 PlayerConnection.LOGGER.warn(this.player.getName() + " moved too quickly! " + d7 + "," + d8 + "," + d9);
+                                 PlayerConnection.LOGGER.warn("{} moved too quickly! {},{},{}", new Object[] { this.player.getName(), Double.valueOf(d7), Double.valueOf(d8), Double.valueOf(d9)});
                                  this.a(this.player.locX, this.player.locY, this.player.locZ, this.player.yaw, this.player.pitch);
                                  return;
-@@ -351,6 +555,69 @@
+@@ -350,6 +555,69 @@
                              }
                          }
  
@@ -410,8 +403,8 @@
 +
                          this.B = d12 >= -0.03125D;
                          this.B &= !this.minecraftServer.getAllowFlight() && !this.player.abilities.canFly;
-                         this.B &= !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.cC() && !worldserver.d(this.player.getBoundingBox().g(0.0625D).a(0.0D, -0.55D, 0.0D));
-@@ -367,15 +634,79 @@
+                         this.B &= !this.player.hasEffect(MobEffects.LEVITATION) && !this.player.cG() && !worldserver.d(this.player.getBoundingBox().g(0.0625D).a(0.0D, -0.55D, 0.0D));
+@@ -366,15 +634,79 @@
      }
  
      public void a(double d0, double d1, double d2, float f, float f1) {
@@ -447,8 +440,7 @@
 +        if (set.contains(PacketPlayOutPosition.EnumPlayerTeleportFlags.X_ROT)) {
 +            pitch += from.getPitch();
 +        }
- 
--        this.teleportPos = new Vec3D(d0 + d3, d1 + d4, d2 + d5);
++
 +
 +        Location to = new Location(this.getPlayer().getWorld(), x, y, z, yaw, pitch);
 +        PlayerTeleportEvent event = new PlayerTeleportEvent(player, from.clone(), to.clone(), PlayerTeleportEvent.TeleportCause.UNKNOWN);
@@ -466,7 +458,8 @@
 +
 +        this.internalTeleport(d0, d1, d2, f, f1, set);
 +    }
-+
+ 
+-        this.teleportPos = new Vec3D(d0 + d3, d1 + d4, d2 + d5);
 +    public void teleport(Location dest) {
 +        internalTeleport(dest.getX(), dest.getY(), dest.getZ(), dest.getYaw(), dest.getPitch(), Collections.emptySet());
 +    }
@@ -496,7 +489,7 @@
          float f2 = f;
          float f3 = f1;
  
-@@ -387,6 +718,14 @@
+@@ -386,6 +718,14 @@
              f3 = f1 + this.player.pitch;
          }
  
@@ -511,7 +504,7 @@
          if (++this.teleportAwait == Integer.MAX_VALUE) {
              this.teleportAwait = 0;
          }
-@@ -398,37 +737,61 @@
+@@ -397,37 +737,61 @@
  
      public void a(PacketPlayInBlockDig packetplayinblockdig) {
          PlayerConnectionUtils.ensureMainThread(packetplayinblockdig, this, this.player.x());
@@ -579,7 +572,7 @@
              this.player.clearActiveItem();
              itemstack = this.player.getItemInMainHand();
              if (itemstack != null && itemstack.count == 0) {
-@@ -437,9 +800,9 @@
+@@ -436,9 +800,9 @@
  
              return;
  
@@ -592,7 +585,7 @@
              double d0 = this.player.locX - ((double) blockposition.getX() + 0.5D);
              double d1 = this.player.locY - ((double) blockposition.getY() + 0.5D) + 1.5D;
              double d2 = this.player.locZ - ((double) blockposition.getZ() + 0.5D);
-@@ -454,7 +817,15 @@
+@@ -453,7 +817,15 @@
                      if (!this.minecraftServer.a(worldserver, blockposition, this.player) && worldserver.getWorldBorder().a(blockposition)) {
                          this.player.playerInteractManager.a(blockposition, packetplayinblockdig.b());
                      } else {
@@ -608,7 +601,7 @@
                      }
                  } else {
                      if (packetplayinblockdig.c() == PacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) {
-@@ -474,10 +845,12 @@
+@@ -473,10 +845,12 @@
          default:
              throw new IllegalArgumentException("Invalid player action");
          }
@@ -621,7 +614,7 @@
          WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension);
          EnumHand enumhand = packetplayinuseitem.c();
          ItemStack itemstack = this.player.b(enumhand);
-@@ -491,6 +864,13 @@
+@@ -490,6 +864,13 @@
              chatmessage.getChatModifier().setColor(EnumChatFormat.RED);
              this.player.playerConnection.sendPacket(new PacketPlayOutChat(chatmessage));
          } else if (this.teleportPos == null && this.player.e((double) blockposition.getX() + 0.5D, (double) blockposition.getY() + 0.5D, (double) blockposition.getZ() + 0.5D) < 64.0D && !this.minecraftServer.a(worldserver, blockposition, this.player) && worldserver.getWorldBorder().a(blockposition)) {
@@ -635,7 +628,7 @@
              this.player.playerInteractManager.a(this.player, worldserver, itemstack, enumhand, blockposition, enumdirection, packetplayinuseitem.d(), packetplayinuseitem.e(), packetplayinuseitem.f());
          }
  
-@@ -506,19 +886,55 @@
+@@ -504,19 +885,55 @@
  
      public void a(PacketPlayInBlockPlace packetplayinblockplace) {
          PlayerConnectionUtils.ensureMainThread(packetplayinblockplace, this, this.player.x());
@@ -666,7 +659,7 @@
 +            float f6 = MathHelper.sin(-f1 * 0.017453292F);
 +            float f7 = f4 * f5;
 +            float f8 = f3 * f5;
-+            double d3 = player.playerInteractManager.getGameMode() == WorldSettings.EnumGamemode.CREATIVE ? 5.0D : 4.5D;
++            double d3 = player.playerInteractManager.getGameMode()== EnumGamemode.CREATIVE ? 5.0D : 4.5D;
 +            Vec3D vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3);
 +            MovingObjectPosition movingobjectposition = this.player.world.rayTrace(vec3d, vec3d1, false);
 +
@@ -696,7 +689,7 @@
          }
      }
  
-@@ -529,8 +945,8 @@
+@@ -527,8 +944,8 @@
              WorldServer[] aworldserver = this.minecraftServer.worldServer;
              int i = aworldserver.length;
  
@@ -707,18 +700,18 @@
  
                  if (worldserver != null) {
                      entity = packetplayinspectate.a(worldserver);
-@@ -543,6 +959,8 @@
+@@ -541,6 +958,8 @@
              if (entity != null) {
                  this.player.setSpectatorTarget(this.player);
                  this.player.stopRiding();
 +
 +                /* CraftBukkit start - replace with bukkit handling for multi-world
-                 if (entity.world != this.player.world) {
-                     WorldServer worldserver1 = this.player.x();
-                     WorldServer worldserver2 = (WorldServer) entity.world;
-@@ -568,12 +986,19 @@
-                 } else {
+                 if (entity.world == this.player.world) {
                      this.player.enderTeleportTo(entity.locX, entity.locY, entity.locZ);
+                 } else {
+@@ -566,12 +985,19 @@
+                     this.minecraftServer.getPlayerList().b(this.player, worldserver2);
+                     this.minecraftServer.getPlayerList().updateClient(this.player);
                  }
 +                */
 +                this.player.getBukkitEntity().teleport(entity.getBukkitEntity(), PlayerTeleportEvent.TeleportCause.SPECTATE);
@@ -737,11 +730,11 @@
  
      public void a(PacketPlayInBoatMove packetplayinboatmove) {
          PlayerConnectionUtils.ensureMainThread(packetplayinboatmove, this, this.player.x());
-@@ -586,14 +1011,29 @@
+@@ -584,14 +1010,29 @@
      }
  
      public void a(IChatBaseComponent ichatbasecomponent) {
--        PlayerConnection.LOGGER.info(this.player.getName() + " lost connection: " + ichatbasecomponent);
+-        PlayerConnection.LOGGER.info("{} lost connection: {}", new Object[] { this.player.getName(), ichatbasecomponent});
 +        // CraftBukkit start - Rarely it would send a disconnect line twice
 +        if (this.processedDisconnect) {
 +            return;
@@ -749,7 +742,7 @@
 +            this.processedDisconnect = true;
 +        }
 +        // CraftBukkit end
-+        PlayerConnection.LOGGER.info(this.player.getName() + " lost connection: " + ichatbasecomponent.toPlainText()); // CraftBukkit: Don't toString().
++        PlayerConnection.LOGGER.info("{} lost connection: {}", new Object[] { this.player.getName(), ichatbasecomponent.toPlainText()});// CraftBukkit - Don't toString().
 +        // CraftBukkit start - Replace vanilla quit message handling with our own.
 +        /*
          this.minecraftServer.aC();
@@ -769,7 +762,7 @@
          if (this.minecraftServer.R() && this.player.getName().equals(this.minecraftServer.Q())) {
              PlayerConnection.LOGGER.info("Stopping singleplayer server as player logged out");
              this.minecraftServer.safeShutdown();
-@@ -615,6 +1055,15 @@
+@@ -613,6 +1054,15 @@
              }
          }
  
@@ -785,7 +778,7 @@
          try {
              this.networkManager.sendPacket(packet);
          } catch (Throwable throwable) {
-@@ -636,17 +1085,32 @@
+@@ -634,17 +1084,32 @@
  
      public void a(PacketPlayInHeldItemSlot packetplayinhelditemslot) {
          PlayerConnectionUtils.ensureMainThread(packetplayinhelditemslot, this, this.player.x());
@@ -802,7 +795,7 @@
              this.player.inventory.itemInHandIndex = packetplayinhelditemslot.a();
              this.player.resetIdleTimer();
          } else {
-             PlayerConnection.LOGGER.warn(this.player.getName() + " tried to set an invalid carried item");
+             PlayerConnection.LOGGER.warn("{} tried to set an invalid carried item", new Object[] { this.player.getName()});
 +            this.disconnect("Nope!"); // CraftBukkit
          }
      }
@@ -820,7 +813,7 @@
              ChatMessage chatmessage = new ChatMessage("chat.cannotSend", new Object[0]);
  
              chatmessage.getChatModifier().setColor(EnumChatFormat.RED);
-@@ -659,39 +1123,249 @@
+@@ -657,39 +1122,249 @@
  
              for (int i = 0; i < s.length(); ++i) {
                  if (!SharedConstants.isAllowedChatCharacter(s.charAt(i))) {
@@ -1033,7 +1026,7 @@
 +        float f6 = MathHelper.sin(-f1 * 0.017453292F);
 +        float f7 = f4 * f5;
 +        float f8 = f3 * f5;
-+        double d3 = player.playerInteractManager.getGameMode() == WorldSettings.EnumGamemode.CREATIVE ? 5.0D : 4.5D;
++        double d3 = player.playerInteractManager.getGameMode()== EnumGamemode.CREATIVE ? 5.0D : 4.5D;
 +        Vec3D vec3d1 = vec3d.add((double) f7 * d3, (double) f6 * d3, (double) f8 * d3);
 +        MovingObjectPosition movingobjectposition = this.player.world.rayTrace(vec3d, vec3d1, false);
 +
@@ -1078,7 +1071,7 @@
          this.player.resetIdleTimer();
          IJumpable ijumpable;
  
-@@ -761,6 +1435,7 @@
+@@ -759,6 +1434,7 @@
  
      public void a(PacketPlayInUseEntity packetplayinuseentity) {
          PlayerConnectionUtils.ensureMainThread(packetplayinuseentity, this, this.player.x());
@@ -1086,7 +1079,7 @@
          WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension);
          Entity entity = packetplayinuseentity.a((World) worldserver);
  
-@@ -777,22 +1452,72 @@
+@@ -775,22 +1451,72 @@
                  EnumHand enumhand;
                  ItemStack itemstack;
  
@@ -1160,7 +1153,7 @@
                  }
              }
          }
-@@ -808,7 +1533,8 @@
+@@ -806,7 +1532,8 @@
          case 1:
              if (this.player.viewingCredits) {
                  this.player.viewingCredits = false;
@@ -1170,7 +1163,7 @@
              } else {
                  if (this.player.getHealth() > 0.0F) {
                      return;
-@@ -834,14 +1560,20 @@
+@@ -832,14 +1559,20 @@
  
      public void a(PacketPlayInCloseWindow packetplayinclosewindow) {
          PlayerConnectionUtils.ensureMainThread(packetplayinclosewindow, this, this.player.x());
@@ -1192,7 +1185,7 @@
                  ArrayList arraylist = Lists.newArrayList();
  
                  for (int i = 0; i < this.player.activeContainer.c.size(); ++i) {
-@@ -850,8 +1582,275 @@
+@@ -848,8 +1581,275 @@
  
                  this.player.a(this.player.activeContainer, (List) arraylist);
              } else {
@@ -1201,10 +1194,10 @@
 +                if (packetplayinwindowclick.b() < -1 && packetplayinwindowclick.b() != -999) {
 +                    return;
 +                }
- 
++
 +                InventoryView inventory = this.player.activeContainer.getBukkitView();
 +                SlotType type = CraftInventoryView.getSlotType(inventory, packetplayinwindowclick.b());
-+
+ 
 +                InventoryClickEvent event;
 +                ClickType click = ClickType.UNKNOWN;
 +                InventoryAction action = InventoryAction.UNKNOWN;
@@ -1469,7 +1462,7 @@
                  if (ItemStack.matches(packetplayinwindowclick.e(), itemstack)) {
                      this.player.playerConnection.sendPacket(new PacketPlayOutTransaction(packetplayinwindowclick.a(), packetplayinwindowclick.d(), true));
                      this.player.f = true;
-@@ -880,6 +1879,7 @@
+@@ -878,6 +1878,7 @@
  
      public void a(PacketPlayInEnchantItem packetplayinenchantitem) {
          PlayerConnectionUtils.ensureMainThread(packetplayinenchantitem, this, this.player.x());
@@ -1477,7 +1470,7 @@
          this.player.resetIdleTimer();
          if (this.player.activeContainer.windowId == packetplayinenchantitem.a() && this.player.activeContainer.c(this.player) && !this.player.isSpectator()) {
              this.player.activeContainer.a(this.player, packetplayinenchantitem.b());
-@@ -913,8 +1913,48 @@
+@@ -911,8 +1912,48 @@
              }
  
              boolean flag1 = packetplayinsetcreativeslot.a() >= 1 && packetplayinsetcreativeslot.a() <= 45;
@@ -1527,7 +1520,7 @@
  
              if (flag1 && flag2 && flag3) {
                  if (itemstack == null) {
-@@ -938,6 +1978,7 @@
+@@ -936,6 +1977,7 @@
  
      public void a(PacketPlayInTransaction packetplayintransaction) {
          PlayerConnectionUtils.ensureMainThread(packetplayintransaction, this, this.player.x());
@@ -1535,7 +1528,7 @@
          Short oshort = (Short) this.k.get(this.player.activeContainer.windowId);
  
          if (oshort != null && packetplayintransaction.b() == oshort.shortValue() && this.player.activeContainer.windowId == packetplayintransaction.a() && !this.player.activeContainer.c(this.player) && !this.player.isSpectator()) {
-@@ -948,6 +1989,7 @@
+@@ -946,6 +1988,7 @@
  
      public void a(PacketPlayInUpdateSign packetplayinupdatesign) {
          PlayerConnectionUtils.ensureMainThread(packetplayinupdatesign, this, this.player.x());
@@ -1543,9 +1536,9 @@
          this.player.resetIdleTimer();
          WorldServer worldserver = this.minecraftServer.getWorldServer(this.player.dimension);
          BlockPosition blockposition = packetplayinupdatesign.a();
-@@ -964,14 +2006,30 @@
+@@ -962,14 +2005,30 @@
  
-             if (!tileentitysign.c() || tileentitysign.d() != this.player) {
+             if (!tileentitysign.d() || tileentitysign.e() != this.player) {
                  this.minecraftServer.warning("Player " + this.player.getName() + " just tried to change non-editable sign");
 +                this.sendPacket(tileentity.getUpdatePacket()); // CraftBukkit
                  return;
@@ -1575,7 +1568,7 @@
  
              tileentitysign.update();
              worldserver.notify(blockposition, iblockdata, iblockdata, 3);
-@@ -994,11 +2052,27 @@
+@@ -992,11 +2051,27 @@
  
      public void a(PacketPlayInAbilities packetplayinabilities) {
          PlayerConnectionUtils.ensureMainThread(packetplayinabilities, this, this.player.x());
@@ -1604,8 +1597,8 @@
          ArrayList arraylist = Lists.newArrayList();
          Iterator iterator = this.minecraftServer.tabCompleteCommand(this.player, packetplayintabcomplete.a(), packetplayintabcomplete.b(), packetplayintabcomplete.c()).iterator();
  
-@@ -1332,12 +2406,34 @@
-                             packetdataserializer.release();
+@@ -1334,12 +2409,34 @@
+                             PlayerConnection.LOGGER.error("Couldn\'t pick item", exception7);
                          }
                      }
 +                    // CraftBukkit start
diff --git a/nms-patches/PlayerInteractManager.patch b/nms-patches/PlayerInteractManager.patch
index 47b77f13d1..41658afddc 100644
--- a/nms-patches/PlayerInteractManager.patch
+++ b/nms-patches/PlayerInteractManager.patch
@@ -15,8 +15,8 @@
  public class PlayerInteractManager {
  
 @@ -28,7 +35,7 @@
-         this.gamemode = worldsettings_enumgamemode;
-         worldsettings_enumgamemode.a(this.player.abilities);
+         this.gamemode = enumgamemode;
+         enumgamemode.a(this.player.abilities);
          this.player.updateAbilities();
 -        this.player.server.getPlayerList().sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_GAME_MODE, new EntityPlayer[] { this.player}));
 +        this.player.server.getPlayerList().sendAll(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_GAME_MODE, new EntityPlayer[] { this.player}), this.player); // CraftBukkit
@@ -122,7 +122,7 @@
          }
  
      }
-@@ -192,12 +251,75 @@
+@@ -192,13 +251,76 @@
      }
  
      public boolean breakBlock(BlockPosition blockposition) {
@@ -188,6 +188,7 @@
              IBlockData iblockdata = this.world.getType(blockposition);
 +            if (iblockdata.getBlock() == Blocks.AIR) return false; // CraftBukkit - A plugin set block to air without cancelling
              TileEntity tileentity = this.world.getTileEntity(blockposition);
+             Block block = iblockdata.getBlock();
  
 +            // CraftBukkit start - Special case skulls, their item data comes from a tile entity
 +            if (iblockdata.getBlock() == Blocks.SKULL && !this.isCreative()) {
@@ -196,10 +197,10 @@
 +            }
 +            // CraftBukkit end
 +
-             if (iblockdata.getBlock() instanceof BlockCommand && !this.player.a(2, "")) {
+             if ((block instanceof BlockCommand || block instanceof BlockStructure) && !this.player.dh()) {
                  this.world.notify(blockposition, iblockdata, iblockdata, 3);
                  return false;
-@@ -242,6 +364,12 @@
+@@ -243,6 +365,12 @@
                      }
                  }
  
@@ -212,7 +213,7 @@
                  return flag;
              }
          }
-@@ -282,7 +410,13 @@
+@@ -283,7 +411,13 @@
          }
      }
  
@@ -223,11 +224,11 @@
 +
      public EnumInteractionResult a(EntityHuman entityhuman, World world, @Nullable ItemStack itemstack, EnumHand enumhand, BlockPosition blockposition, EnumDirection enumdirection, float f, float f1, float f2) {
 +        /* CraftBukkit start - whole method
-         if (this.gamemode == WorldSettings.EnumGamemode.SPECTATOR) {
+         if (this.gamemode == EnumGamemode.SPECTATOR) {
              TileEntity tileentity = world.getTileEntity(blockposition);
  
-@@ -331,6 +465,72 @@
-                 return itemstack.placeItem(entityhuman, world, blockposition, enumhand, enumdirection, f, f1, f2);
+@@ -340,6 +474,72 @@
+                 }
              }
          }
 +        // Interact event */
@@ -236,7 +237,7 @@
 +        if (blockdata.getBlock() != Blocks.AIR) {
 +            boolean cancelledBlock = false;
 +
-+            if (this.gamemode == WorldSettings.EnumGamemode.SPECTATOR) {
++            if (this.gamemode == EnumGamemode.SPECTATOR) {
 +                TileEntity tileentity = world.getTileEntity(blockposition);
 +                cancelledBlock = !(tileentity instanceof ITileInventory || tileentity instanceof IInventory);
 +            }
@@ -256,7 +257,7 @@
 +                    ((EntityPlayer) entityhuman).playerConnection.sendPacket(new PacketPlayOutBlockChange(world, bottom ? blockposition.up() : blockposition.down()));
 +                }
 +                result = (event.useItemInHand() != Event.Result.ALLOW) ? EnumInteractionResult.SUCCESS : EnumInteractionResult.PASS;
-+            } else if (this.gamemode == WorldSettings.EnumGamemode.SPECTATOR) {
++            } else if (this.gamemode == EnumGamemode.SPECTATOR) {
 +                TileEntity tileentity = world.getTileEntity(blockposition);
 +
 +                if (tileentity instanceof ITileInventory) {
diff --git a/nms-patches/PlayerInventory.patch b/nms-patches/PlayerInventory.patch
index 01e12abb25..1dfab01125 100644
--- a/nms-patches/PlayerInventory.patch
+++ b/nms-patches/PlayerInventory.patch
@@ -87,7 +87,7 @@
      public int getFirstEmptySlotIndex() {
          for (int i = 0; i < this.items.length; ++i) {
              if (this.items[i] == null) {
-@@ -459,7 +525,7 @@
+@@ -462,7 +528,7 @@
      }
  
      public int getMaxStackSize() {
@@ -96,7 +96,7 @@
      }
  
      public boolean b(IBlockData iblockdata) {
-@@ -516,6 +582,11 @@
+@@ -519,6 +585,11 @@
  
      @Nullable
      public ItemStack getCarried() {
diff --git a/nms-patches/PlayerList.patch b/nms-patches/PlayerList.patch
index c3ab6b965c..bc879ebdc3 100644
--- a/nms-patches/PlayerList.patch
+++ b/nms-patches/PlayerList.patch
@@ -69,9 +69,9 @@
              s1 = networkmanager.getSocketAddress().toString();
          }
  
--        PlayerList.f.info(entityplayer.getName() + "[" + s1 + "] logged in with entity id " + entityplayer.getId() + " at (" + entityplayer.locX + ", " + entityplayer.locY + ", " + entityplayer.locZ + ")");
+-        PlayerList.f.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[] { entityplayer.getName(), s1, Integer.valueOf(entityplayer.getId()), Double.valueOf(entityplayer.locX), Double.valueOf(entityplayer.locY), Double.valueOf(entityplayer.locZ)});
 +        // CraftBukkit - Moved message to after join
-+        // PlayerList.f.info(entityplayer.getName() + "[" + s1 + "] logged in with entity id " + entityplayer.getId() + " at (" + entityplayer.locX + ", " + entityplayer.locY + ", " + entityplayer.locZ + ")");
++        // PlayerList.f.info("{}[{}] logged in with entity id {} at ({}, {}, {})", new Object[] { entityplayer.getName(), s1, Integer.valueOf(entityplayer.getId()), Double.valueOf(entityplayer.locX), Double.valueOf(entityplayer.locY), Double.valueOf(entityplayer.locZ)});
          WorldServer worldserver = this.server.getWorldServer(entityplayer.dimension);
          WorldData worlddata = worldserver.getWorldData();
          BlockPosition blockposition = worldserver.getSpawn();
@@ -92,14 +92,14 @@
 +        // ChatMessage chatmessage;
  
 +        String joinMessage;
-         if (!entityplayer.getName().equalsIgnoreCase(s)) {
--            chatmessage = new ChatMessage("multiplayer.player.joined.renamed", new Object[] { entityplayer.getScoreboardDisplayName(), s});
-+            // chatmessage = new ChatMessage("multiplayer.player.joined.renamed", new Object[] { entityplayer.getScoreboardDisplayName(), s});
-+            joinMessage = "\u00A7e" + LocaleI18n.a("multiplayer.player.joined.renamed", entityplayer.getName(), s);
-         } else {
+         if (entityplayer.getName().equalsIgnoreCase(s)) {
 -            chatmessage = new ChatMessage("multiplayer.player.joined", new Object[] { entityplayer.getScoreboardDisplayName()});
 +            // chatmessage = new ChatMessage("multiplayer.player.joined", new Object[] { entityplayer.getScoreboardDisplayName()});
 +            joinMessage = "\u00A7e" + LocaleI18n.a("multiplayer.player.joined", entityplayer.getName());
+         } else {
+-            chatmessage = new ChatMessage("multiplayer.player.joined.renamed", new Object[] { entityplayer.getScoreboardDisplayName(), s});
++            // chatmessage = new ChatMessage("multiplayer.player.joined.renamed", new Object[] { entityplayer.getScoreboardDisplayName(), s});
++            joinMessage = "\u00A7e" + LocaleI18n.a("multiplayer.player.joined.renamed", entityplayer.getName(), s);
          }
  
 -        chatmessage.getChatModifier().setColor(EnumChatFormat.YELLOW);
@@ -391,7 +391,7 @@
  
          entityplayer1.playerConnection = entityplayer.playerConnection;
          entityplayer1.copyTo(entityplayer, flag);
-@@ -415,43 +578,157 @@
+@@ -415,43 +578,158 @@
              entityplayer1.a(s);
          }
  
@@ -422,13 +422,13 @@
 +                    entityplayer1.setRespawnPosition(null, true);
 +                    entityplayer1.playerConnection.sendPacket(new PacketPlayOutGameStateChange(0, 0.0F));
 +                }
-             }
++            }
 +
 +            if (location == null) {
 +                cworld = (CraftWorld) this.server.server.getWorlds().get(0);
 +                blockposition = cworld.getHandle().getSpawn();
 +                location = new Location(cworld, (double) ((float) blockposition.getX() + 0.5F), (double) ((float) blockposition.getY() + 0.1F), (double) ((float) blockposition.getZ() + 0.5F));
-+            }
+             }
 +
 +            Player respawnPlayer = cserver.getPlayer(entityplayer1);
 +            PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(respawnPlayer, location, isBedSpawn);
@@ -449,14 +449,14 @@
 +        while (avoidSuffocation && !worldserver.getCubes(entityplayer1, entityplayer1.getBoundingBox()).isEmpty() && entityplayer1.locY < 256.0D) {
              entityplayer1.setPosition(entityplayer1.locX, entityplayer1.locY + 1.0D, entityplayer1.locZ);
          }
--
--        entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(entityplayer1.dimension, entityplayer1.world.getDifficulty(), entityplayer1.world.getWorldData().getType(), entityplayer1.playerInteractManager.getGameMode()));
 +        // CraftBukkit start
 +        byte actualDimension = (byte) (worldserver.getWorld().getEnvironment().getId());
 +        // Force the client to refresh their chunk cache
 +        if (fromWorld.getEnvironment() == worldserver.getWorld().getEnvironment()) {
 +            entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn((byte) (actualDimension >= 0 ? -1 : 0), worldserver.getDifficulty(), worldserver.getWorldData().getType(), entityplayer.playerInteractManager.getGameMode()));
 +        }
+ 
+-        entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(entityplayer1.dimension, entityplayer1.world.getDifficulty(), entityplayer1.world.getWorldData().getType(), entityplayer1.playerInteractManager.getGameMode()));
 +        entityplayer1.playerConnection.sendPacket(new PacketPlayOutRespawn(actualDimension, worldserver.getDifficulty(), worldserver.getWorldData().getType(), entityplayer1.playerInteractManager.getGameMode()));
 +        entityplayer1.spawnIn(worldserver);
 +        entityplayer1.dead = false;
@@ -557,7 +557,7 @@
 +        exitWorld.getTravelAgent().adjustExit(entityplayer, exit, velocity);
 +
 +       
-+        entityplayer.ck = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds
++        entityplayer.worldChangeInvuln = true; // CraftBukkit - Set teleport invulnerability only if player changing worlds
 +        this.moveToWorld(entityplayer, exitWorld.dimension, true, exit, false); // Vanilla doesn't check for suffocation when handling portals, so neither should we
 +        if (entityplayer.motX != velocity.getX() || entityplayer.motY != velocity.getY() || entityplayer.motZ != velocity.getZ()) {
 +            entityplayer.getBukkitEntity().setVelocity(velocity);
@@ -567,7 +567,7 @@
      public void f(EntityPlayer entityplayer) {
          GameProfile gameprofile = entityplayer.getProfile();
          int i = this.isOp(gameprofile) ? this.operators.a(gameprofile) : 0;
-@@ -490,12 +767,111 @@
+@@ -490,12 +768,111 @@
      }
  
      public void changeWorld(Entity entity, int i, WorldServer worldserver, WorldServer worldserver1) {
@@ -677,9 +677,9 @@
 +        }
 +        /*
          if (entity.dimension == -1) {
-             d0 = MathHelper.a(d0 / d2, worldserver1.getWorldBorder().b() + 16.0D, worldserver1.getWorldBorder().d() - 16.0D);
-             d1 = MathHelper.a(d1 / d2, worldserver1.getWorldBorder().c() + 16.0D, worldserver1.getWorldBorder().e() - 16.0D);
-@@ -514,6 +890,8 @@
+             d0 = MathHelper.a(d0 / 8.0D, worldserver1.getWorldBorder().b() + 16.0D, worldserver1.getWorldBorder().d() - 16.0D);
+             d1 = MathHelper.a(d1 / 8.0D, worldserver1.getWorldBorder().c() + 16.0D, worldserver1.getWorldBorder().e() - 16.0D);
+@@ -514,6 +891,8 @@
              BlockPosition blockposition;
  
              if (i == 1) {
@@ -688,7 +688,7 @@
                  blockposition = worldserver1.getSpawn();
              } else {
                  blockposition = worldserver1.getDimensionSpawn();
-@@ -527,16 +905,27 @@
+@@ -527,16 +906,27 @@
                  worldserver.entityJoinedWorld(entity, false);
              }
          }
@@ -719,7 +719,7 @@
                  worldserver1.entityJoinedWorld(entity, false);
              }
  
-@@ -544,6 +933,7 @@
+@@ -544,6 +934,7 @@
          }
  
          entity.spawnIn(worldserver1);
@@ -727,7 +727,7 @@
      }
  
      public void tick() {
-@@ -561,6 +951,25 @@
+@@ -561,6 +952,25 @@
  
      }
  
@@ -753,7 +753,7 @@
      public void a(Packet<?> packet, int i) {
          for (int j = 0; j < this.players.size(); ++j) {
              EntityPlayer entityplayer = (EntityPlayer) this.players.get(j);
-@@ -659,11 +1068,23 @@
+@@ -659,11 +1069,23 @@
  
          this.operators.add(new OpListEntry(gameprofile, this.server.q(), this.operators.b(gameprofile)));
          this.b(this.a(gameprofile.getId()), i);
@@ -777,7 +777,7 @@
      }
  
      private void b(EntityPlayer entityplayer, int i) {
-@@ -688,7 +1109,7 @@
+@@ -688,7 +1110,7 @@
      }
  
      public boolean isOp(GameProfile gameprofile) {
@@ -786,7 +786,7 @@
      }
  
      @Nullable
-@@ -712,6 +1133,12 @@
+@@ -712,6 +1134,12 @@
          for (int j = 0; j < this.players.size(); ++j) {
              EntityPlayer entityplayer = (EntityPlayer) this.players.get(j);
  
@@ -799,7 +799,7 @@
              if (entityplayer != entityhuman && entityplayer.dimension == i) {
                  double d4 = d0 - entityplayer.locX;
                  double d5 = d1 - entityplayer.locY;
-@@ -759,21 +1186,26 @@
+@@ -759,21 +1187,26 @@
      public void reloadWhitelist() {}
  
      public void b(EntityPlayer entityplayer, WorldServer worldserver) {
@@ -831,7 +831,7 @@
          entityplayer.playerConnection.sendPacket(new PacketPlayOutHeldItemSlot(entityplayer.inventory.itemInHandIndex));
      }
  
-@@ -786,7 +1218,7 @@
+@@ -786,7 +1219,7 @@
      }
  
      public String[] getSeenPlayers() {
@@ -840,7 +840,7 @@
      }
  
      public boolean getHasWhitelist() {
-@@ -836,16 +1268,26 @@
+@@ -836,16 +1269,26 @@
  
      public void u() {
          for (int i = 0; i < this.players.size(); ++i) {
@@ -869,7 +869,7 @@
      }
  
      public void sendMessage(IChatBaseComponent ichatbasecomponent) {
-@@ -882,8 +1324,10 @@
+@@ -882,8 +1325,10 @@
              WorldServer[] aworldserver = this.server.worldServer;
              int j = aworldserver.length;
  
diff --git a/nms-patches/PortalTravelAgent.patch b/nms-patches/PortalTravelAgent.patch
index d44c947002..4311735233 100644
--- a/nms-patches/PortalTravelAgent.patch
+++ b/nms-patches/PortalTravelAgent.patch
@@ -12,10 +12,12 @@
  
  public class PortalTravelAgent {
  
-@@ -26,6 +31,19 @@
+@@ -26,8 +31,21 @@
              int i = MathHelper.floor(entity.locX);
              int j = MathHelper.floor(entity.locY) - 1;
              int k = MathHelper.floor(entity.locZ);
+-            boolean flag = true;
+-            boolean flag1 = false;
 +            // CraftBukkit start - Modularize end portal creation
 +            BlockPosition created = this.createEndPortal(entity.locX, entity.locY, entity.locZ);
 +            entity.setPositionRotation((double) created.getX(), (double) created.getY(), (double) created.getZ(), entity.yaw, 0.0F);
@@ -29,15 +31,19 @@
 +            int j = MathHelper.floor(y) - 1;
 +            int k = MathHelper.floor(z);
 +            // CraftBukkit end
-             byte b0 = 1;
-             byte b1 = 0;
++            byte b0 = 1;
++            byte b1 = 0;
  
-@@ -42,16 +60,63 @@
+             for (int l = -2; l <= 2; ++l) {
+                 for (int i1 = -2; i1 <= 2; ++i1) {
+@@ -42,18 +60,63 @@
                  }
              }
  
 -            entity.setPositionRotation((double) i, (double) j, (double) k, entity.yaw, 0.0F);
--            entity.motX = entity.motY = entity.motZ = 0.0D;
+-            entity.motX = 0.0D;
+-            entity.motY = 0.0D;
+-            entity.motZ = 0.0D;
 +        // CraftBukkit start
 +        return new BlockPosition(i, k, k);
 +    }
@@ -101,7 +107,7 @@
          boolean flag1 = true;
          Object object = BlockPosition.ZERO;
          long k = ChunkCoordIntPair.a(i, j);
-@@ -64,12 +129,12 @@
+@@ -66,12 +129,12 @@
              portaltravelagent_chunkcoordinatesportal.b = this.world.getTime();
              flag1 = false;
          } else {
@@ -117,7 +123,7 @@
                      for (BlockPosition blockposition2 = blockposition.a(l, this.world.Z() - 1 - blockposition.getY(), i1); blockposition2.getY() >= 0; blockposition2 = blockposition1) {
                          blockposition1 = blockposition2.down();
                          if (this.world.getType(blockposition2).getBlock() == Blocks.PORTAL) {
-@@ -93,6 +158,29 @@
+@@ -95,6 +158,29 @@
              if (flag1) {
                  this.c.put(k, new PortalTravelAgent.ChunkCoordinatesPortal((BlockPosition) object, this.world.getTime()));
              }
@@ -146,8 +152,8 @@
 +            // CraftBukkit end
  
              double d2 = (double) ((BlockPosition) object).getX() + 0.5D;
-             double d3 = (double) ((BlockPosition) object).getY() + 0.5D;
-@@ -131,30 +219,59 @@
+             double d3 = (double) ((BlockPosition) object).getZ() + 0.5D;
+@@ -132,30 +218,59 @@
                  f4 = 1.0F;
              }
  
@@ -158,9 +164,9 @@
 -            entity.motZ = d6 * (double) f3 + d7 * (double) f2;
 -            entity.yaw = f - (float) (entity.getPortalDirection().opposite().get2DRotationValue() * 90) + (float) (shapedetector_shapedetectorcollection.getFacing().get2DRotationValue() * 90);
 -            if (entity instanceof EntityPlayer) {
--                ((EntityPlayer) entity).playerConnection.a(d2, d3, d4, entity.yaw, entity.pitch);
+-                ((EntityPlayer) entity).playerConnection.a(d2, d5, d3, entity.yaw, entity.pitch);
 -            } else {
--                entity.setPositionRotation(d2, d3, d4, entity.yaw, entity.pitch);
+-                entity.setPositionRotation(d2, d5, d3, entity.yaw, entity.pitch);
 -            }
 -
 -            return true;
@@ -202,7 +208,7 @@
      }
  
      public boolean a(Entity entity) {
--        byte b0 = 16;
+-        boolean flag = true;
 +        // CraftBukkit start - Allow for portal creation to be based on coordinates instead of entity
 +        return this.createPortal(entity.locX, entity.locY, entity.locZ, 16);
 +    }
@@ -225,20 +231,20 @@
          int l = i;
          int i1 = j;
          int j1 = k;
-@@ -179,10 +296,10 @@
+@@ -180,10 +295,10 @@
          double d4;
  
-         for (i2 = i - b0; i2 <= i + b0; ++i2) {
+         for (i2 = i - 16; i2 <= i + 16; ++i2) {
 -            d1 = (double) i2 + 0.5D - entity.locX;
 +            d1 = (double) i2 + 0.5D - x; // CraftBukkit
  
-             for (j2 = k - b0; j2 <= k + b0; ++j2) {
+             for (j2 = k - 16; j2 <= k + 16; ++j2) {
 -                d2 = (double) j2 + 0.5D - entity.locZ;
 +                d2 = (double) j2 + 0.5D - z; // CraftBukkit
  
                  label271:
                  for (k2 = this.world.Z() - 1; k2 >= 0; --k2) {
-@@ -214,7 +331,7 @@
+@@ -215,7 +330,7 @@
                                  }
                              }
  
@@ -247,20 +253,20 @@
                              d4 = d1 * d1 + d3 * d3 + d2 * d2;
                              if (d0 < 0.0D || d4 < d0) {
                                  d0 = d4;
-@@ -231,10 +348,10 @@
+@@ -232,10 +347,10 @@
  
          if (d0 < 0.0D) {
-             for (i2 = i - b0; i2 <= i + b0; ++i2) {
+             for (i2 = i - 16; i2 <= i + 16; ++i2) {
 -                d1 = (double) i2 + 0.5D - entity.locX;
 +                d1 = (double) i2 + 0.5D - x; // CraftBukkit
  
-                 for (j2 = k - b0; j2 <= k + b0; ++j2) {
+                 for (j2 = k - 16; j2 <= k + 16; ++j2) {
 -                    d2 = (double) j2 + 0.5D - entity.locZ;
 +                    d2 = (double) j2 + 0.5D - z; // CraftBukkit
  
                      label219:
                      for (k2 = this.world.Z() - 1; k2 >= 0; --k2) {
-@@ -259,7 +376,7 @@
+@@ -260,7 +375,7 @@
                                      }
                                  }
  
@@ -269,7 +275,7 @@
                                  d4 = d1 * d1 + d3 * d3 + d2 * d2;
                                  if (d0 < 0.0D || d4 < d0) {
                                      d0 = d4;
-@@ -358,5 +475,10 @@
+@@ -359,5 +474,10 @@
              super(blockposition.getX(), blockposition.getY(), blockposition.getZ());
              this.b = i;
          }
diff --git a/nms-patches/RecipesBanner.patch b/nms-patches/RecipesBanner.patch
index 0afc40e2e8..09c32114e9 100644
--- a/nms-patches/RecipesBanner.patch
+++ b/nms-patches/RecipesBanner.patch
@@ -16,7 +16,7 @@
  
          public boolean a(InventoryCrafting inventorycrafting, World world) {
              boolean flag = false;
-@@ -215,9 +219,13 @@
+@@ -212,9 +216,13 @@
          }
      }
  
diff --git a/nms-patches/RecipesFurnace.patch b/nms-patches/RecipesFurnace.patch
index ae1f06f8c6..9c2f9bf80a 100644
--- a/nms-patches/RecipesFurnace.patch
+++ b/nms-patches/RecipesFurnace.patch
@@ -1,11 +1,12 @@
 --- a/net/minecraft/server/RecipesFurnace.java
 +++ b/net/minecraft/server/RecipesFurnace.java
-@@ -10,7 +10,9 @@
+@@ -9,8 +9,10 @@
+ public class RecipesFurnace {
  
      private static final RecipesFurnace a = new RecipesFurnace();
-     public Map<ItemStack, ItemStack> recipes = Maps.newHashMap();
--    private Map<ItemStack, Float> c = Maps.newHashMap();
-+    private Map<ItemStack, Float> c = Maps.newHashMap(); // PAIL: rename
+-    public final Map<ItemStack, ItemStack> recipes = Maps.newHashMap();
++    public Map<ItemStack, ItemStack> recipes = Maps.newHashMap();
+     private final Map<ItemStack, Float> experience = Maps.newHashMap();
 +    public Map<ItemStack,ItemStack> customRecipes = Maps.newHashMap(); // CraftBukkit - add field
 +    public Map<ItemStack,Float> customExperience = Maps.newHashMap(); // CraftBukkit - add field
  
@@ -54,7 +55,7 @@
      }
  
      public float b(ItemStack itemstack) {
--        Iterator iterator = this.c.entrySet().iterator();
+-        Iterator iterator = this.experience.entrySet().iterator();
 +        // CraftBukkit start - initialize to customRecipes
 +        boolean vanilla = false;
 +        Iterator<Entry<ItemStack, Float>> iterator = this.customExperience.entrySet().iterator();
@@ -66,8 +67,8 @@
              if (!iterator.hasNext()) {
 -                return 0.0F;
 +                // CraftBukkit start - fall back to vanilla recipes
-+                if (!vanilla && !this.c.isEmpty()) {
-+                    iterator = this.c.entrySet().iterator();
++                if (!vanilla && !this.experience.isEmpty()) {
++                    iterator = this.experience.entrySet().iterator();
 +                    vanilla = true;
 +                } else {
 +                    return 0.0F;
diff --git a/nms-patches/ScoreboardServer.patch b/nms-patches/ScoreboardServer.patch
index 500a4c9ca2..36e6f5ec59 100644
--- a/nms-patches/ScoreboardServer.patch
+++ b/nms-patches/ScoreboardServer.patch
@@ -93,7 +93,7 @@
          this.b();
      }
  
-@@ -161,6 +161,7 @@
+@@ -166,6 +166,7 @@
  
          while (iterator.hasNext()) {
              EntityPlayer entityplayer = (EntityPlayer) iterator.next();
@@ -101,7 +101,7 @@
              Iterator iterator1 = list.iterator();
  
              while (iterator1.hasNext()) {
-@@ -193,6 +194,7 @@
+@@ -198,6 +199,7 @@
  
          while (iterator.hasNext()) {
              EntityPlayer entityplayer = (EntityPlayer) iterator.next();
@@ -109,7 +109,7 @@
              Iterator iterator1 = list.iterator();
  
              while (iterator1.hasNext()) {
-@@ -216,4 +218,14 @@
+@@ -221,4 +223,14 @@
  
          return i;
      }
diff --git a/nms-patches/SecondaryWorldServer.patch b/nms-patches/SecondaryWorldServer.patch
index cde0aaa9d4..d3786952e8 100644
--- a/nms-patches/SecondaryWorldServer.patch
+++ b/nms-patches/SecondaryWorldServer.patch
@@ -2,7 +2,7 @@
 +++ b/net/minecraft/server/SecondaryWorldServer.java
 @@ -4,9 +4,12 @@
  
-     private WorldServer a;
+     private final WorldServer a;
  
 -    public SecondaryWorldServer(MinecraftServer minecraftserver, IDataManager idatamanager, int i, WorldServer worldserver, MethodProfiler methodprofiler) {
 -        super(minecraftserver, idatamanager, new SecondaryWorldData(worldserver.getWorldData()), i, methodprofiler);
diff --git a/nms-patches/SpawnerCreature.patch b/nms-patches/SpawnerCreature.patch
index 6f88265569..4da7817161 100644
--- a/nms-patches/SpawnerCreature.patch
+++ b/nms-patches/SpawnerCreature.patch
@@ -23,10 +23,10 @@
  
      public SpawnerCreature() {}
  
-@@ -36,18 +40,21 @@
-                     for (int i1 = -b0; i1 <= b0; ++i1) {
-                         for (k = -b0; k <= b0; ++k) {
-                             boolean flag3 = i1 == -b0 || i1 == b0 || k == -b0 || k == b0;
+@@ -36,15 +40,18 @@
+                     for (int i1 = -8; i1 <= 8; ++i1) {
+                         for (k = -8; k <= 8; ++k) {
+                             boolean flag4 = i1 == -8 || i1 == 8 || k == -8 || k == 8;
 -                            ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i1 + l, k + j);
 +                            // CraftBukkit start - use LongHash and LongHashSet
 +                            // ChunkCoordIntPair chunkcoordintpair = new ChunkCoordIntPair(i1 + l, k + j);
@@ -35,21 +35,18 @@
 +                            long chunkCoords = LongHash.toLong(i1 + l, k + j);
 +                            if (!this.b.contains(chunkCoords)) {
                                  ++i;
--                                if (!flag3 && worldserver.getWorldBorder().isInBounds(chunkcoordintpair)) {
+-                                if (!flag4 && worldserver.getWorldBorder().isInBounds(chunkcoordintpair)) {
 -                                    PlayerChunk playerchunk = worldserver.getPlayerChunkMap().getChunk(chunkcoordintpair.x, chunkcoordintpair.z);
-+                                if (!flag3 && worldserver.getWorldBorder().isInBounds(i1 + l, k + j)) { // CraftBukkit
++                                if (!flag4 && worldserver.getWorldBorder().isInBounds(i1 + l, k + j)) { // CraftBukkit
 +                                    PlayerChunk playerchunk = worldserver.getPlayerChunkMap().getChunk(i1 + l, k + j); // CraftBukkit
  
                                      if (playerchunk != null && playerchunk.e()) {
 -                                        this.b.add(chunkcoordintpair);
 +                                        this.b.add(chunkCoords);
++                                        // CraftBukkit end
                                      }
                                  }
                              }
-+                            // CraftBukkit end
-                         }
-                     }
-                 }
 @@ -62,9 +69,31 @@
              for (int k1 = 0; k1 < j; ++k1) {
                  EnumCreatureType enumcreaturetype = aenumcreaturetype[k1];
diff --git a/nms-patches/TileEntity.patch b/nms-patches/TileEntity.patch
index 6eac3cf780..d11d0ddde3 100644
--- a/nms-patches/TileEntity.patch
+++ b/nms-patches/TileEntity.patch
@@ -9,7 +9,7 @@
  public abstract class TileEntity {
  
      private static final Logger a = LogManager.getLogger();
-@@ -244,4 +246,13 @@
+@@ -256,4 +258,13 @@
          a(TileEntityEndGateway.class, "EndGateway");
          a(TileEntityCommand.class, "Control");
      }
diff --git a/nms-patches/TileEntityBanner.patch b/nms-patches/TileEntityBanner.patch
index 0819ccaead..caf443b037 100644
--- a/nms-patches/TileEntityBanner.patch
+++ b/nms-patches/TileEntityBanner.patch
@@ -3,7 +3,7 @@
 @@ -21,6 +21,11 @@
  
              if (nbttagcompound.hasKey("Patterns")) {
-                 this.patterns = (NBTTagList) nbttagcompound.getList("Patterns", 10).clone();
+                 this.patterns = nbttagcompound.getList("Patterns", 10).d();
 +                // CraftBukkit start
 +                while (this.patterns.size() > 20) {
 +                    this.patterns.remove(20);
diff --git a/nms-patches/TileEntityBrewingStand.patch b/nms-patches/TileEntityBrewingStand.patch
index f21726677d..a0b64d7f7c 100644
--- a/nms-patches/TileEntityBrewingStand.patch
+++ b/nms-patches/TileEntityBrewingStand.patch
@@ -83,7 +83,7 @@
  
          for (int i = 0; i < 3; ++i) {
              this.items[i] = PotionBrewer.d(itemstack, this.items[i]);
-@@ -221,7 +268,7 @@
+@@ -225,7 +272,7 @@
      }
  
      public int getMaxStackSize() {
diff --git a/nms-patches/TileEntityChest.patch b/nms-patches/TileEntityChest.patch
index f1f72a342b..1dfb8f1858 100644
--- a/nms-patches/TileEntityChest.patch
+++ b/nms-patches/TileEntityChest.patch
@@ -44,7 +44,7 @@
      public TileEntityChest(BlockChest.Type blockchest_type) {
          this.q = blockchest_type;
      }
-@@ -123,10 +153,11 @@
+@@ -127,10 +157,11 @@
      }
  
      public int getMaxStackSize() {
@@ -57,7 +57,7 @@
          return this.world.getTileEntity(this.position) != this ? false : entityhuman.e((double) this.position.getX() + 0.5D, (double) this.position.getY() + 0.5D, (double) this.position.getZ() + 0.5D) <= 64.0D;
      }
  
-@@ -303,9 +334,21 @@
+@@ -307,9 +338,21 @@
              if (this.l < 0) {
                  this.l = 0;
              }
@@ -79,7 +79,7 @@
              this.world.applyPhysics(this.position, this.getBlock());
              this.world.applyPhysics(this.position.down(), this.getBlock());
          }
-@@ -314,8 +357,20 @@
+@@ -318,8 +361,20 @@
  
      public void closeContainer(EntityHuman entityhuman) {
          if (!entityhuman.isSpectator() && this.getBlock() instanceof BlockChest) {
@@ -100,7 +100,7 @@
              this.world.applyPhysics(this.position, this.getBlock());
              this.world.applyPhysics(this.position.down(), this.getBlock());
          }
-@@ -372,6 +427,13 @@
+@@ -376,6 +431,13 @@
  
      }
  
diff --git a/nms-patches/TileEntityDispenser.patch b/nms-patches/TileEntityDispenser.patch
index 1c73bbd004..5080012fcf 100644
--- a/nms-patches/TileEntityDispenser.patch
+++ b/nms-patches/TileEntityDispenser.patch
@@ -53,7 +53,7 @@
                  i = k;
              }
          }
-@@ -135,7 +168,7 @@
+@@ -139,7 +172,7 @@
      }
  
      public int getMaxStackSize() {
diff --git a/nms-patches/TileEntityFurnace.patch b/nms-patches/TileEntityFurnace.patch
index 7b265b96fc..2c0539b77d 100644
--- a/nms-patches/TileEntityFurnace.patch
+++ b/nms-patches/TileEntityFurnace.patch
@@ -49,10 +49,10 @@
      public TileEntityFurnace() {}
  
      public int getSize() {
-@@ -122,11 +157,29 @@
+@@ -126,11 +161,29 @@
      }
  
-     public void c() {
+     public void E_() {
 -        boolean flag = this.isBurning();
 +        boolean flag = (this.getBlock() == Blocks.LIT_FURNACE); // CraftBukkit - SPIGOT-844 - Check if furnace block is lit using the block instead of burn time
          boolean flag1 = false;
@@ -81,12 +81,13 @@
          }
  
          if (!this.world.isClientSide) {
-@@ -135,9 +188,21 @@
+@@ -139,10 +192,21 @@
                      this.cookTime = MathHelper.clamp(this.cookTime - 2, 0, this.cookTimeTotal);
                  }
              } else {
 -                if (!this.isBurning() && this.canBurn()) {
--                    this.ticksForCurrentFuel = this.burnTime = fuelTime(this.items[1]);
+-                    this.burnTime = fuelTime(this.items[1]);
+-                    this.ticksForCurrentFuel = this.burnTime;
 -                    if (this.isBurning()) {
 +                // CraftBukkit start - Handle multiple elapsed ticks
 +                if (this.burnTime <= 0 && this.canBurn()) { // CraftBukkit - == to <=
@@ -106,7 +107,7 @@
                          flag1 = true;
                          if (this.items[1] != null) {
                              --this.items[1].count;
-@@ -150,6 +215,7 @@
+@@ -155,6 +219,7 @@
                      }
                  }
  
@@ -114,7 +115,7 @@
                  if (this.isBurning() && this.canBurn()) {
                      ++this.cookTime;
                      if (this.cookTime == this.cookTimeTotal) {
-@@ -161,11 +227,13 @@
+@@ -166,11 +231,13 @@
                  } else {
                      this.cookTime = 0;
                  }
@@ -128,7 +129,7 @@
              }
          }
  
-@@ -185,7 +253,8 @@
+@@ -190,7 +257,8 @@
          } else {
              ItemStack itemstack = RecipesFurnace.getInstance().getResult(this.items[0]);
  
@@ -138,7 +139,7 @@
          }
      }
  
-@@ -193,11 +262,38 @@
+@@ -198,11 +266,38 @@
          if (this.canBurn()) {
              ItemStack itemstack = RecipesFurnace.getInstance().getResult(this.items[0]);
  
diff --git a/nms-patches/TileEntityHopper.patch b/nms-patches/TileEntityHopper.patch
index 14489afc3d..32d757c8bc 100644
--- a/nms-patches/TileEntityHopper.patch
+++ b/nms-patches/TileEntityHopper.patch
@@ -46,8 +46,8 @@
 +
      public TileEntityHopper() {}
  
-     public void a(NBTTagCompound nbttagcompound) {
-@@ -105,7 +139,7 @@
+     public static void a(DataConverterManager dataconvertermanager) {
+@@ -109,7 +143,7 @@
      }
  
      public int getMaxStackSize() {
@@ -56,7 +56,7 @@
      }
  
      public boolean a(EntityHuman entityhuman) {
-@@ -201,10 +235,35 @@
+@@ -205,10 +239,35 @@
                  for (int i = 0; i < this.getSize(); ++i) {
                      if (this.getItem(i) != null) {
                          ItemStack itemstack = this.getItem(i).cloneItemStack();
@@ -94,7 +94,7 @@
                              return true;
                          }
  
-@@ -315,10 +374,41 @@
+@@ -330,10 +389,41 @@
  
          if (itemstack != null && b(iinventory, itemstack, i, enumdirection)) {
              ItemStack itemstack1 = itemstack.cloneItemStack();
@@ -138,7 +138,7 @@
                  return true;
              }
  
-@@ -334,6 +424,13 @@
+@@ -349,6 +439,13 @@
          if (entityitem == null) {
              return false;
          } else {
diff --git a/nms-patches/TileEntityPiston.patch b/nms-patches/TileEntityPiston.patch
index 0616921b3f..b7f7c9014c 100644
--- a/nms-patches/TileEntityPiston.patch
+++ b/nms-patches/TileEntityPiston.patch
@@ -1,9 +1,9 @@
 --- a/net/minecraft/server/TileEntityPiston.java
 +++ b/net/minecraft/server/TileEntityPiston.java
-@@ -132,6 +132,7 @@
+@@ -133,6 +133,7 @@
      }
  
-     public void c() {
+     public void E_() {
 +        if (this.world == null) return; // CraftBukkit
          this.j = this.i;
          if (this.j >= 1.0F) {
diff --git a/nms-patches/TileEntitySign.patch b/nms-patches/TileEntitySign.patch
index aa6f54d4ce..de4c416452 100644
--- a/nms-patches/TileEntitySign.patch
+++ b/nms-patches/TileEntitySign.patch
@@ -13,7 +13,7 @@
          this.i.b(nbttagcompound);
          return nbttagcompound;
      }
-@@ -70,14 +76,34 @@
+@@ -74,14 +80,34 @@
              }
          };
  
@@ -52,7 +52,7 @@
              }
          }
  
-@@ -164,7 +190,14 @@
+@@ -171,7 +197,14 @@
                  ChatClickable chatclickable = chatmodifier.h();
  
                  if (chatclickable.a() == ChatClickable.EnumClickAction.RUN_COMMAND) {
diff --git a/nms-patches/TileEntitySkull.patch b/nms-patches/TileEntitySkull.patch
deleted file mode 100644
index 0ca418a420..0000000000
--- a/nms-patches/TileEntitySkull.patch
+++ /dev/null
@@ -1,13 +0,0 @@
---- a/net/minecraft/server/TileEntitySkull.java
-+++ b/net/minecraft/server/TileEntitySkull.java
-@@ -135,4 +135,10 @@
-     public void setRotation(int i) {
-         this.rotation = i;
-     }
-+
-+    // CraftBukkit start - add method
-+    public int getRotation() {
-+        return this.rotation;
-+    }
-+    // CraftBukkit end
- }
diff --git a/nms-patches/UserCache.patch b/nms-patches/UserCache.patch
index 628fe72162..70ebb1ed10 100644
--- a/nms-patches/UserCache.patch
+++ b/nms-patches/UserCache.patch
@@ -4,8 +4,8 @@
      private static boolean c;
      private final Map<String, UserCache.UserCacheEntry> d = Maps.newHashMap();
      private final Map<UUID, UserCache.UserCacheEntry> e = Maps.newHashMap();
--    private final LinkedList<GameProfile> f = Lists.newLinkedList();
-+    private final java.util.Deque<GameProfile> f = new java.util.concurrent.LinkedBlockingDeque<GameProfile>(); // CraftBukkit
+-    private final Deque<GameProfile> f = Lists.newLinkedList();
++    private final Deque<GameProfile> f = new java.util.concurrent.LinkedBlockingDeque<GameProfile>(); // CraftBukkit
      private final GameProfileRepository g;
      protected final Gson b;
      private final File h;
diff --git a/nms-patches/World.patch b/nms-patches/World.patch
index 96a84cb6b1..66a3bd5a65 100644
--- a/nms-patches/World.patch
+++ b/nms-patches/World.patch
@@ -238,7 +238,7 @@
                  iblockdata.doPhysics(this, blockposition, block);
              } catch (Throwable throwable) {
                  CrashReport crashreport = CrashReport.a(throwable, "Exception while updating neighbours");
-@@ -526,6 +690,17 @@
+@@ -530,6 +694,17 @@
      }
  
      public IBlockData getType(BlockPosition blockposition) {
@@ -256,7 +256,7 @@
          if (this.E(blockposition)) {
              return Blocks.AIR.getBlockData();
          } else {
-@@ -724,6 +899,13 @@
+@@ -728,6 +903,13 @@
      }
  
      public boolean addEntity(Entity entity) {
@@ -270,7 +270,7 @@
          int i = MathHelper.floor(entity.locX / 16.0D);
          int j = MathHelper.floor(entity.locZ / 16.0D);
          boolean flag = entity.attachedToPlayer;
-@@ -732,6 +914,34 @@
+@@ -736,6 +918,34 @@
              flag = true;
          }
  
@@ -305,7 +305,7 @@
          if (!flag && !this.isChunkLoaded(i, j, false)) {
              return false;
          } else {
-@@ -754,6 +964,7 @@
+@@ -758,6 +968,7 @@
              ((IWorldAccess) this.u.get(i)).a(entity);
          }
  
@@ -313,7 +313,7 @@
      }
  
      protected void c(Entity entity) {
-@@ -761,6 +972,7 @@
+@@ -765,6 +976,7 @@
              ((IWorldAccess) this.u.get(i)).b(entity);
          }
  
@@ -321,7 +321,7 @@
      }
  
      public void kill(Entity entity) {
-@@ -796,7 +1008,15 @@
+@@ -800,7 +1012,15 @@
              this.getChunkAt(i, j).b(entity);
          }
  
@@ -338,7 +338,7 @@
          this.c(entity);
      }
  
-@@ -1044,6 +1264,11 @@
+@@ -1048,6 +1268,11 @@
  
          for (i = 0; i < this.j.size(); ++i) {
              entity = (Entity) this.j.get(i);
@@ -350,7 +350,7 @@
  
              try {
                  ++entity.ticksLived;
-@@ -1092,8 +1317,10 @@
+@@ -1096,8 +1321,10 @@
          CrashReportSystemDetails crashreportsystemdetails1;
          CrashReport crashreport1;
  
@@ -360,10 +360,10 @@
 +        for (this.tickPosition = 0; this.tickPosition < this.entityList.size(); ++this.tickPosition) {
 +            entity = (Entity) this.entityList.get(this.tickPosition);
 +            // CraftBukkit end
-             Entity entity1 = entity.bz();
+             Entity entity1 = entity.bB();
  
              if (entity1 != null) {
-@@ -1126,7 +1353,7 @@
+@@ -1130,7 +1357,7 @@
                      this.getChunkAt(j, l).b(entity);
                  }
  
@@ -372,7 +372,7 @@
                  this.c(entity);
              }
  
-@@ -1135,6 +1362,13 @@
+@@ -1139,6 +1366,13 @@
  
          this.methodProfiler.c("blockEntities");
          this.M = true;
@@ -386,16 +386,16 @@
          Iterator iterator = this.tileEntityListTick.iterator();
  
          while (iterator.hasNext()) {
-@@ -1145,7 +1379,7 @@
+@@ -1149,7 +1383,7 @@
  
                  if (this.isLoaded(blockposition) && this.N.a(blockposition)) {
                      try {
 -                        this.methodProfiler.a(tileentity.getClass().getSimpleName());
 +                        this.methodProfiler.a(""/*tileentity.getClass().getSimpleName()*/); // CraftBukkit: SPIGOT-1900
-                         ((ITickable) tileentity).c();
+                         ((ITickable) tileentity).E_();
                          this.methodProfiler.b();
                      } catch (Throwable throwable2) {
-@@ -1167,11 +1401,13 @@
+@@ -1171,11 +1405,13 @@
          }
  
          this.M = false;
@@ -409,7 +409,7 @@
  
          this.methodProfiler.c("pendingBlockEntities");
          if (!this.b.isEmpty()) {
-@@ -1179,9 +1415,11 @@
+@@ -1183,9 +1419,11 @@
                  TileEntity tileentity1 = (TileEntity) this.b.get(i1);
  
                  if (!tileentity1.x()) {
@@ -421,7 +421,7 @@
  
                      if (this.isLoaded(tileentity1.getPosition())) {
                          Chunk chunk = this.getChunkAtWorldCoords(tileentity1.getPosition());
-@@ -1189,6 +1427,12 @@
+@@ -1193,6 +1431,12 @@
  
                          chunk.a(tileentity1.getPosition(), tileentity1);
                          this.notify(tileentity1.getPosition(), iblockdata, iblockdata, 3);
@@ -434,11 +434,11 @@
                      }
                  }
              }
-@@ -1236,7 +1480,10 @@
+@@ -1240,7 +1484,10 @@
          int j = MathHelper.floor(entity.locZ);
-         byte b0 = 32;
+         boolean flag1 = true;
  
--        if (!flag || this.isAreaLoaded(i - b0, 0, j - b0, i + b0, 0, j + b0, true)) {
+-        if (!flag || this.isAreaLoaded(i - 32, 0, j - 32, i + 32, 0, j + 32, true)) {
 +        // CraftBukkit start - Use neighbor cache instead of looking up
 +        Chunk startingChunk = this.getChunkIfLoaded(i >> 4, j >> 4);
 +        if (!flag || (startingChunk != null && startingChunk.areNeighborsLoaded(2)) /* this.isAreaLoaded(i - b0, 0, j - b0, i + b0, 0, j + b0) */) {
@@ -446,7 +446,7 @@
              entity.M = entity.locX;
              entity.N = entity.locY;
              entity.O = entity.locZ;
-@@ -1575,11 +1822,18 @@
+@@ -1579,11 +1826,18 @@
          }
      }
  
@@ -465,22 +465,22 @@
              TileEntity tileentity = null;
  
              if (this.M) {
-@@ -1614,6 +1868,14 @@
+@@ -1618,6 +1872,14 @@
      public void setTileEntity(BlockPosition blockposition, @Nullable TileEntity tileentity) {
          if (!this.E(blockposition)) {
              if (tileentity != null && !tileentity.x()) {
 +            // CraftBukkit start
 +            if (captureBlockStates) {
 +                tileentity.a(this);
-+                tileentity.a(blockposition);
++                tileentity.setPosition(blockposition);
 +                capturedTileEntities.put(blockposition, tileentity);
 +                return;
 +            }
 +            // CraftBukkit end
                  if (this.M) {
-                     tileentity.a(blockposition);
+                     tileentity.setPosition(blockposition);
                      Iterator iterator = this.b.iterator();
-@@ -1769,6 +2031,14 @@
+@@ -1773,6 +2035,14 @@
                  }
  
                  this.o = MathHelper.a(this.o, 0.0F, 1.0F);
@@ -495,7 +495,7 @@
              }
          }
      }
-@@ -1900,7 +2170,10 @@
+@@ -1904,7 +2174,10 @@
      }
  
      public boolean c(EnumSkyBlock enumskyblock, BlockPosition blockposition) {
@@ -507,7 +507,7 @@
              return false;
          } else {
              int i = 0;
-@@ -2067,7 +2340,7 @@
+@@ -2071,7 +2344,7 @@
          while (iterator.hasNext()) {
              Entity entity = (Entity) iterator.next();
  
@@ -516,7 +516,7 @@
                  arraylist.add(entity);
              }
          }
-@@ -2082,7 +2355,7 @@
+@@ -2086,7 +2359,7 @@
          while (iterator.hasNext()) {
              Entity entity = (Entity) iterator.next();
  
@@ -525,7 +525,7 @@
                  arraylist.add(entity);
              }
          }
-@@ -2131,7 +2404,7 @@
+@@ -2135,7 +2408,7 @@
              }
          }
  
@@ -534,7 +534,7 @@
      }
  
      @Nullable
-@@ -2152,8 +2425,17 @@
+@@ -2156,8 +2429,17 @@
  
          while (iterator.hasNext()) {
              Entity entity = (Entity) iterator.next();
@@ -554,7 +554,7 @@
                  ++i;
              }
          }
-@@ -2162,12 +2444,18 @@
+@@ -2166,12 +2448,18 @@
      }
  
      public void a(Collection<Entity> collection) {
@@ -574,7 +574,7 @@
              this.b(entity);
          }
  
-@@ -2181,7 +2469,13 @@
+@@ -2185,7 +2473,13 @@
          IBlockData iblockdata = this.getType(blockposition);
          AxisAlignedBB axisalignedbb = flag ? null : block.getBlockData().d(this, blockposition);
  
@@ -589,7 +589,7 @@
      }
  
      public int K() {
-@@ -2284,6 +2578,11 @@
+@@ -2288,6 +2582,11 @@
  
          for (int i = 0; i < this.players.size(); ++i) {
              EntityHuman entityhuman1 = (EntityHuman) this.players.get(i);
@@ -601,7 +601,7 @@
  
              if ((IEntitySelector.d.apply(entityhuman1) || !flag) && (IEntitySelector.e.apply(entityhuman1) || flag)) {
                  double d5 = entityhuman1.e(d0, d1, d2);
-@@ -2452,6 +2751,16 @@
+@@ -2456,6 +2755,16 @@
  
      public void everyoneSleeping() {}
  
@@ -618,12 +618,12 @@
      public float h(float f) {
          return (this.p + (this.q - this.p) * f) * this.j(f);
      }
-@@ -2669,7 +2978,7 @@
+@@ -2673,7 +2982,7 @@
          int l = j * 16 + 8 - blockposition.getZ();
-         short short0 = 128;
+         boolean flag = true;
  
--        return k >= -short0 && k <= short0 && l >= -short0 && l <= short0;
-+        return k >= -short0 && k <= short0 && l >= -short0 && l <= short0 && this.keepSpawnInMemory; // CraftBukkit - Added 'this.keepSpawnInMemory'
+-        return k >= -128 && k <= 128 && l >= -128 && l <= 128;
++        return k >= -128 && k <= 128 && l >= -128 && l <= 128 && this.keepSpawnInMemory; // CraftBukkit - Added 'this.keepSpawnInMemory'
      }
  
      public void a(Packet<?> packet) {
diff --git a/nms-patches/WorldData.patch b/nms-patches/WorldData.patch
index 7fb47311eb..83b28f6679 100644
--- a/nms-patches/WorldData.patch
+++ b/nms-patches/WorldData.patch
@@ -20,7 +20,7 @@
  
      protected WorldData() {
          this.f = WorldType.NORMAL;
-@@ -441,6 +447,18 @@
+@@ -437,6 +443,18 @@
      }
  
      public void setThundering(boolean flag) {
@@ -39,7 +39,7 @@
          this.v = flag;
      }
  
-@@ -457,6 +475,18 @@
+@@ -453,6 +471,18 @@
      }
  
      public void setStorm(boolean flag) {
@@ -58,7 +58,7 @@
          this.t = flag;
      }
  
-@@ -602,6 +632,12 @@
+@@ -598,6 +628,12 @@
  
      public void setDifficulty(EnumDifficulty enumdifficulty) {
          this.C = enumdifficulty;
@@ -71,7 +71,7 @@
      }
  
      public boolean isDifficultyLocked() {
-@@ -720,4 +756,12 @@
+@@ -716,4 +752,12 @@
      public void a(DimensionManager dimensionmanager, NBTTagCompound nbttagcompound) {
          this.N.put(dimensionmanager, nbttagcompound);
      }
diff --git a/nms-patches/WorldGenGroundBush.patch b/nms-patches/WorldGenGroundBush.patch
index 6fa45dfbb1..bbd0306b2b 100644
--- a/nms-patches/WorldGenGroundBush.patch
+++ b/nms-patches/WorldGenGroundBush.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/WorldGenGroundBush.java
 +++ b/net/minecraft/server/WorldGenGroundBush.java
-@@ -47,7 +47,12 @@
+@@ -45,7 +45,12 @@
                      }
                  }
              }
diff --git a/nms-patches/WorldGenVillagePieces.patch b/nms-patches/WorldGenVillagePieces.patch
index 77e049f811..021d1768a3 100644
--- a/nms-patches/WorldGenVillagePieces.patch
+++ b/nms-patches/WorldGenVillagePieces.patch
@@ -1,6 +1,6 @@
 --- a/net/minecraft/server/WorldGenVillagePieces.java
 +++ b/net/minecraft/server/WorldGenVillagePieces.java
-@@ -282,10 +282,10 @@
+@@ -269,10 +269,10 @@
  
          protected void a(NBTTagCompound nbttagcompound) {
              super.a(nbttagcompound);
@@ -15,7 +15,7 @@
          }
  
          protected void b(NBTTagCompound nbttagcompound) {
-@@ -413,8 +413,8 @@
+@@ -402,8 +402,8 @@
  
          protected void a(NBTTagCompound nbttagcompound) {
              super.a(nbttagcompound);
@@ -26,12 +26,20 @@
          }
  
          protected void b(NBTTagCompound nbttagcompound) {
-@@ -1602,7 +1602,7 @@
-                     entityvillager.setPositionRotation((double) j1 + 0.5D, (double) k1, (double) l1 + 0.5D, 0.0F, 0.0F);
-                     entityvillager.prepare(world.D(new BlockPosition(entityvillager)), (GroupDataEntity) null);
-                     entityvillager.setProfession(this.c(i1, entityvillager.getProfession()));
--                    world.addEntity(entityvillager);
-+                    world.addEntity(entityvillager, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason
+@@ -1701,14 +1701,14 @@
+                         entityzombie.prepare(world.D(new BlockPosition(entityzombie)), (GroupDataEntity) null);
+                         entityzombie.setVillagerType(EnumZombieType.b(this.c(i1, 0)));
+                         entityzombie.cQ();
+-                        world.addEntity(entityzombie);
++                        world.addEntity(entityzombie, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason
+                     } else {
+                         EntityVillager entityvillager = new EntityVillager(world);
+ 
+                         entityvillager.setPositionRotation((double) j1 + 0.5D, (double) k1, (double) l1 + 0.5D, 0.0F, 0.0F);
+                         entityvillager.prepare(world.D(new BlockPosition(entityvillager)), (GroupDataEntity) null);
+                         entityvillager.setProfession(this.c(i1, entityvillager.getProfession()));
+-                        world.addEntity(entityvillager);
++                        world.addEntity(entityvillager, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.CHUNK_GEN); // CraftBukkit - add SpawnReason
+                     }
                  }
  
-             }
diff --git a/nms-patches/WorldMap.patch b/nms-patches/WorldMap.patch
index 84f4c0df61..40d2af9552 100644
--- a/nms-patches/WorldMap.patch
+++ b/nms-patches/WorldMap.patch
@@ -16,7 +16,7 @@
  
      public int centerX;
 @@ -19,8 +27,18 @@
-     private Map<EntityHuman, WorldMap.WorldMapHumanTracker> j = Maps.newHashMap();
+     private final Map<EntityHuman, WorldMap.WorldMapHumanTracker> j = Maps.newHashMap();
      public Map<String, MapIcon> decorations = Maps.newLinkedHashMap();
  
 +    // CraftBukkit start
diff --git a/nms-patches/WorldServer.patch b/nms-patches/WorldServer.patch
index 97ac2ba3bb..5629062e84 100644
--- a/nms-patches/WorldServer.patch
+++ b/nms-patches/WorldServer.patch
@@ -30,7 +30,7 @@
      private boolean O;
 @@ -38,14 +49,22 @@
      private int T;
-     private List<NextTickListEntry> U = Lists.newArrayList();
+     private final List<NextTickListEntry> U = Lists.newArrayList();
  
 -    public WorldServer(MinecraftServer minecraftserver, IDataManager idatamanager, WorldData worlddata, int i, MethodProfiler methodprofiler) {
 -        super(idatamanager, worlddata, DimensionManager.a(i).d(), methodprofiler, false);
@@ -258,7 +258,7 @@
              return false;
          } else {
 @@ -279,7 +418,7 @@
-                             entityhorse.x(true);
+                             entityhorse.y(true);
                              entityhorse.setAgeRaw(0);
                              entityhorse.setPosition((double) blockposition.getX(), (double) blockposition.getY(), (double) blockposition.getZ());
 -                            this.addEntity(entityhorse);
@@ -531,8 +531,8 @@
  
      private boolean i(Entity entity) {
          if (entity.dead) {
--            WorldServer.a.warn("Tried to add entity " + EntityTypes.b(entity) + " but it was marked as removed already");
-+            // WorldServer.a.warn("Tried to add entity " + EntityTypes.b(entity) + " but it was marked as removed already"); // CraftBukkit
+-            WorldServer.a.warn("Tried to add entity {} but it was marked as removed already", new Object[] { EntityTypes.b(entity)});
++            // WorldServer.a.warn("Tried to add entity {} but it was marked as removed already", new Object[] { EntityTypes.b(entity)}); // CraftBukkit
              return false;
          } else {
              UUID uuid = entity.getUniqueID();
@@ -540,12 +540,12 @@
                      this.f.remove(entity1);
                  } else {
                      if (!(entity instanceof EntityHuman)) {
--                        WorldServer.a.warn("Keeping entity " + EntityTypes.b(entity1) + " that already exists with UUID " + uuid.toString());
-+                        // WorldServer.a.warn("Keeping entity " + EntityTypes.b(entity1) + " that already exists with UUID " + uuid.toString()); // CraftBukkit
+-                        WorldServer.a.warn("Keeping entity {} that already exists with UUID {}", new Object[] { EntityTypes.b(entity1), uuid.toString()});
++                        // WorldServer.a.warn("Keeping entity {} that already exists with UUID {}", new Object[] { EntityTypes.b(entity1), uuid.toString()}); // CraftBukkit
                          return false;
                      }
  
-@@ -889,8 +1131,16 @@
+@@ -899,8 +1141,16 @@
      }
  
      public boolean strikeLightning(Entity entity) {
@@ -563,7 +563,7 @@
              return true;
          } else {
              return false;
-@@ -906,10 +1156,20 @@
+@@ -916,10 +1166,20 @@
      }
  
      public Explosion createExplosion(@Nullable Entity entity, double d0, double d1, double d2, float f, boolean flag, boolean flag1) {
@@ -584,7 +584,7 @@
          if (!flag1) {
              explosion.clearBlocks();
          }
-@@ -955,7 +1215,8 @@
+@@ -965,7 +1225,8 @@
                  BlockActionData blockactiondata = (BlockActionData) iterator.next();
  
                  if (this.a(blockactiondata)) {
@@ -594,7 +594,7 @@
                  }
              }
  
-@@ -978,6 +1239,7 @@
+@@ -988,6 +1249,7 @@
          boolean flag = this.W();
  
          super.t();
@@ -602,7 +602,7 @@
          if (this.n != this.o) {
              this.server.getPlayerList().a((Packet) (new PacketPlayOutGameStateChange(7, this.o)), this.worldProvider.getDimensionManager().getDimensionID());
          }
-@@ -996,6 +1258,21 @@
+@@ -1006,6 +1268,21 @@
              this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(7, this.o));
              this.server.getPlayerList().sendAll(new PacketPlayOutGameStateChange(8, this.q));
          }
@@ -624,7 +624,7 @@
  
      }
  
-@@ -1025,10 +1302,20 @@
+@@ -1035,10 +1312,20 @@
      }
  
      public void a(EnumParticle enumparticle, boolean flag, double d0, double d1, double d2, int i, double d3, double d4, double d5, double d6, int... aint) {
diff --git a/pom.xml b/pom.xml
index ead0dbf6d1..f0f21ec24f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,15 +4,15 @@
     <groupId>org.bukkit</groupId>
     <artifactId>craftbukkit</artifactId>
     <packaging>jar</packaging>
-    <version>1.9.4-R0.1-SNAPSHOT</version>
+    <version>1.10-R0.1-SNAPSHOT</version>
     <name>CraftBukkit</name>
     <url>http://www.bukkit.org</url>
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <api.version>unknown</api.version>
-        <minecraft.version>1.9.4</minecraft.version>
-        <minecraft_version>1_9_R2</minecraft_version>
+        <minecraft.version>1.10</minecraft.version>
+        <minecraft_version>1_10_R1</minecraft_version>
         <buildtag.prefix>git-Bukkit-</buildtag.prefix>
         <buildtag.suffix></buildtag.suffix>
         <maven.compiler.source>1.6</maven.compiler.source>
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index a7c7dca65f..a793b8f7cb 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -865,7 +865,7 @@ public final class CraftServer implements Server {
         WorldData worlddata = sdm.getWorldData();
         WorldSettings worldSettings = null;
         if (worlddata == null) {
-            worldSettings = new WorldSettings(creator.seed(), WorldSettings.EnumGamemode.getById(getDefaultGameMode().getValue()), generateStructures, hardcore, type);
+            worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(getDefaultGameMode().getValue()), generateStructures, hardcore, type);
             worldSettings.setGeneratorSettings(creator.generatorSettings());
             worlddata = new WorldData(worldSettings, name);
         }
@@ -1387,7 +1387,7 @@ public final class CraftServer implements Server {
         Validate.notNull(mode, "Mode cannot be null");
 
         for (World world : getWorlds()) {
-            ((CraftWorld) world).getHandle().worldData.setGameType(WorldSettings.EnumGamemode.getById(mode.getValue()));
+            ((CraftWorld) world).getHandle().worldData.setGameType(EnumGamemode.getById(mode.getValue()));
         }
     }
 
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftSound.java b/src/main/java/org/bukkit/craftbukkit/CraftSound.java
index 396ef4bf9c..8eb3945d5d 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftSound.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftSound.java
@@ -33,6 +33,7 @@ public enum CraftSound {
     BLOCK_DISPENSER_DISPENSE("block.dispenser.dispense"),
     BLOCK_DISPENSER_FAIL("block.dispenser.fail"),
     BLOCK_DISPENSER_LAUNCH("block.dispenser.launch"),
+    BLOCK_ENCHANTMENT_TABLE_USE("block.enchantment_table.use"),
     BLOCK_ENDERCHEST_CLOSE("block.enderchest.close"),
     BLOCK_ENDERCHEST_OPEN("block.enderchest.open"),
     BLOCK_END_GATEWAY_SPAWN("block.end_gateway.spawn"),
@@ -257,6 +258,10 @@ public enum CraftSound {
     ENTITY_HOSTILE_SMALL_FALL("entity.hostile.small_fall"),
     ENTITY_HOSTILE_SPLASH("entity.hostile.splash"),
     ENTITY_HOSTILE_SWIM("entity.hostile.swim"),
+    ENTITY_HUSK_AMBIENT("entity.husk.ambient"),
+    ENTITY_HUSK_DEATH("entity.husk.death"),
+    ENTITY_HUSK_HURT("entity.husk.hurt"),
+    ENTITY_HUSK_STEP("entity.husk.step"),
     ENTITY_IRONGOLEM_ATTACK("entity.irongolem.attack"),
     ENTITY_IRONGOLEM_DEATH("entity.irongolem.death"),
     ENTITY_IRONGOLEM_HURT("entity.irongolem.hurt"),
@@ -305,6 +310,12 @@ public enum CraftSound {
     ENTITY_PLAYER_SMALL_FALL("entity.player.small_fall"),
     ENTITY_PLAYER_SPLASH("entity.player.splash"),
     ENTITY_PLAYER_SWIM("entity.player.swim"),
+    ENTITY_POLAR_BEAR_AMBIENT("entity.polar_bear.ambient"),
+    ENTITY_POLAR_BEAR_BABY_AMBIENT("entity.polar_bear.baby_ambient"),
+    ENTITY_POLAR_BEAR_DEATH("entity.polar_bear.death"),
+    ENTITY_POLAR_BEAR_HURT("entity.polar_bear.hurt"),
+    ENTITY_POLAR_BEAR_STEP("entity.polar_bear.step"),
+    ENTITY_POLAR_BEAR_WARNING("entity.polar_bear.warning"),
     ENTITY_RABBIT_AMBIENT("entity.rabbit.ambient"),
     ENTITY_RABBIT_ATTACK("entity.rabbit.attack"),
     ENTITY_RABBIT_DEATH("entity.rabbit.death"),
@@ -363,6 +374,10 @@ public enum CraftSound {
     ENTITY_SQUID_AMBIENT("entity.squid.ambient"),
     ENTITY_SQUID_DEATH("entity.squid.death"),
     ENTITY_SQUID_HURT("entity.squid.hurt"),
+    ENTITY_STRAY_AMBIENT("entity.stray.ambient"),
+    ENTITY_STRAY_DEATH("entity.stray.death"),
+    ENTITY_STRAY_HURT("entity.stray.hurt"),
+    ENTITY_STRAY_STEP("entity.stray.step"),
     ENTITY_TNT_PRIMED("entity.tnt.primed"),
     ENTITY_VILLAGER_AMBIENT("entity.villager.ambient"),
     ENTITY_VILLAGER_DEATH("entity.villager.death"),
@@ -380,6 +395,10 @@ public enum CraftSound {
     ENTITY_WITHER_DEATH("entity.wither.death"),
     ENTITY_WITHER_HURT("entity.wither.hurt"),
     ENTITY_WITHER_SHOOT("entity.wither.shoot"),
+    ENTITY_WITHER_SKELETON_AMBIENT("entity.wither_skeleton.ambient"),
+    ENTITY_WITHER_SKELETON_DEATH("entity.wither_skeleton.death"),
+    ENTITY_WITHER_SKELETON_HURT("entity.wither_skeleton.hurt"),
+    ENTITY_WITHER_SKELETON_STEP("entity.wither_skeleton.step"),
     ENTITY_WITHER_SPAWN("entity.wither.spawn"),
     ENTITY_WOLF_AMBIENT("entity.wolf.ambient"),
     ENTITY_WOLF_DEATH("entity.wolf.death"),
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 85561dc10e..edeaae374b 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -1096,6 +1096,8 @@ public class CraftWorld implements World {
                 entity = new EntityGuardian(world);
             } else if (ArmorStand.class.isAssignableFrom(clazz)) {
                 entity = new EntityArmorStand(world, x, y, z);
+            } else if (PolarBear.class.isAssignableFrom(clazz)) {
+                entity = new EntityPolarBear(world);
             }
 
             if (entity != null) {
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftFlowerPot.java b/src/main/java/org/bukkit/craftbukkit/block/CraftFlowerPot.java
index e16f5efeed..cc388d2195 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftFlowerPot.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftFlowerPot.java
@@ -26,7 +26,7 @@ public class CraftFlowerPot extends CraftBlockState implements FlowerPot {
 
     @Override
     public MaterialData getContents() {
-        return (pot.d() == null) ? null : CraftMagicNumbers.getMaterial(pot.d()).getNewData((byte) pot.e()); // PAIL: rename
+        return (pot.d() == null) ? null : CraftMagicNumbers.getMaterial(pot.getItem()).getNewData((byte) pot.getData()); // PAIL: rename
     }
 
     @Override
diff --git a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java
index 90572f5a15..632d63172b 100644
--- a/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java
+++ b/src/main/java/org/bukkit/craftbukkit/block/CraftSkull.java
@@ -28,7 +28,7 @@ public class CraftSkull extends CraftBlockState implements Skull {
         skull = (TileEntitySkull) world.getTileEntityAt(getX(), getY(), getZ());
         profile = skull.getGameProfile();
         skullType = getSkullType(skull.getSkullType());
-        rotation = (byte) skull.getRotation();
+        rotation = (byte) skull.rotation;
     }
 
     public CraftSkull(final Material material, final TileEntitySkull te) {
@@ -36,7 +36,7 @@ public class CraftSkull extends CraftBlockState implements Skull {
         skull = te;
         profile = skull.getGameProfile();
         skullType = getSkullType(skull.getSkullType());
-        rotation = (byte) skull.getRotation();
+        rotation = (byte) skull.rotation;
     }
 
     static SkullType getSkullType(int id) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
index 06e2c18b83..8a6df02612 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java
@@ -149,17 +149,6 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand {
         getHandle().setBasePlate(!basePlate);
     }
 
-    @Override
-    public boolean hasGravity() {
-        return !getHandle().hasGravity();
-    }
-
-    @Override
-    public void setGravity(boolean gravity) {
-        getHandle().setGravity(!gravity);
-        getHandle().noclip = !gravity;
-    }
-
     @Override
     public boolean isVisible() {
         return !getHandle().isInvisible();
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 228ca2859e..a4f21b705b 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -67,6 +67,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
                     else if (entity instanceof EntitySheep) { return new CraftSheep(server, (EntitySheep) entity); }
                     else if (entity instanceof EntityHorse) { return new CraftHorse(server, (EntityHorse) entity); }
                     else if (entity instanceof EntityRabbit) { return new CraftRabbit(server, (EntityRabbit) entity); }
+                    else if (entity instanceof EntityPolarBear) { return new CraftPolarBear(server, (EntityPolarBear) entity); }
                     else  { return new CraftAnimals(server, (EntityAnimal) entity); }
                 }
                 // Monsters
@@ -564,14 +565,24 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
     }
 
     @Override
-	public boolean isSilent() {
-		return getHandle().ad(); // PAIL: Rename isSilent
-	}
+    public boolean isSilent() {
+        return getHandle().isSilent();
+    }
 
-	@Override
-	public void setSilent(boolean flag) {
-		getHandle().c(flag); // PAIL: Rename setSilent
-	}
+    @Override
+    public void setSilent(boolean flag) {
+        getHandle().setSilent(flag);
+    }
+
+    @Override
+    public boolean hasGravity() {
+        return !getHandle().isNoGravity();
+    }
+
+    @Override
+    public void setGravity(boolean gravity) {
+        getHandle().setNoGravity(!gravity);
+    }
 
     private static PermissibleBase getPermissibleBase() {
         if (perm == null) {
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 5bdf114caf..1df2579ede 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -363,7 +363,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
 
         IChatBaseComponent[] components = CraftSign.sanitizeLines(lines);
         TileEntitySign sign = new TileEntitySign();
-        sign.a(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ())); // PAIL: rename
+        sign.setPosition(new BlockPosition(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ()));
         System.arraycopy(components, 0, sign.lines, 0, sign.lines.length);
 
         getHandle().playerConnection.sendPacket(sign.getUpdatePacket());
@@ -756,7 +756,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
             }
             
             getHandle().setSpectatorTarget(getHandle());
-            getHandle().playerInteractManager.setGameMode(WorldSettings.EnumGamemode.getById(mode.getValue()));
+            getHandle().playerInteractManager.setGameMode(EnumGamemode.getById(mode.getValue()));
             getHandle().fallDistance = 0;
             getHandle().playerConnection.sendPacket(new PacketPlayOutGameStateChange(3, mode.getValue()));
         }
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java
new file mode 100644
index 0000000000..21129672ca
--- /dev/null
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPolarBear.java
@@ -0,0 +1,27 @@
+package org.bukkit.craftbukkit.entity;
+
+import net.minecraft.server.EntityPolarBear;
+import org.bukkit.craftbukkit.CraftServer;
+import org.bukkit.entity.EntityType;
+import org.bukkit.entity.PolarBear;
+
+public class CraftPolarBear extends CraftAnimals implements PolarBear {
+
+    public CraftPolarBear(CraftServer server, EntityPolarBear entity) {
+        super(server, entity);
+    }
+    @Override
+    public EntityPolarBear getHandle() {
+        return (EntityPolarBear) entity;
+    }
+
+    @Override
+    public String toString() {
+        return "CraftPolarBear";
+    }
+
+    @Override
+    public EntityType getType() {
+        return EntityType.POLAR_BEAR;
+    }
+}
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java
index 58da899412..db25681913 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSkeleton.java
@@ -1,6 +1,7 @@
 package org.bukkit.craftbukkit.entity;
 
 import net.minecraft.server.EntitySkeleton;
+import net.minecraft.server.EnumSkeletonType;
 
 import org.apache.commons.lang.Validate;
 import org.bukkit.craftbukkit.CraftServer;
@@ -28,11 +29,11 @@ public class CraftSkeleton extends CraftMonster implements Skeleton {
     }
 
     public SkeletonType getSkeletonType() {
-        return SkeletonType.getType(getHandle().getSkeletonType());
+        return SkeletonType.values()[getHandle().getSkeletonType().ordinal()];
     }
 
     public void setSkeletonType(SkeletonType type) {
         Validate.notNull(type);
-        getHandle().setSkeletonType(type.getId());
+        getHandle().setSkeletonType(EnumSkeletonType.a(type.ordinal())); // PAIL: rename
     }
 }
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
index ed94c5042b..f1725b8d9d 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftSnowman.java
@@ -12,12 +12,12 @@ public class CraftSnowman extends CraftGolem implements Snowman {
 
     @Override
     public boolean isDerp() {
-        return getHandle().o(); // PAIL: Rename
+        return getHandle().isDerp();
     }
 
     @Override
     public void setDerp(boolean derpMode) {
-        getHandle().a(derpMode); // PAIL: Rename
+        getHandle().setDerp(derpMode);
     }
 
     @Override
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java
index 79abae9c8d..7a5f50f430 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftTippedArrow.java
@@ -43,7 +43,7 @@ public class CraftTippedArrow extends CraftArrow implements TippedArrow {
     public boolean addCustomEffect(PotionEffect effect, boolean override) {
         int effectId = effect.getType().getId();
         MobEffect existing = null;
-        for (MobEffect mobEffect : getHandle().h) {
+        for (MobEffect mobEffect : getHandle().effects) {
             if (MobEffectList.getId(mobEffect.getMobEffect()) == effectId) {
                 existing = mobEffect;
             }
@@ -52,7 +52,7 @@ public class CraftTippedArrow extends CraftArrow implements TippedArrow {
             if (!override) {
                 return false;
             }
-            getHandle().h.remove(existing);
+            getHandle().effects.remove(existing);
         }
         getHandle().a(CraftPotionUtil.fromBukkit(effect));
         getHandle().refreshEffects();
@@ -62,14 +62,14 @@ public class CraftTippedArrow extends CraftArrow implements TippedArrow {
     @Override
     public void clearCustomEffects() {
         Validate.isTrue(getBasePotionData().getType() != PotionType.UNCRAFTABLE, "Tipped Arrows must have at least 1 effect");
-        getHandle().h.clear();
+        getHandle().effects.clear();
         getHandle().refreshEffects();
     }
 
     @Override
     public List<PotionEffect> getCustomEffects() {
         ImmutableList.Builder<PotionEffect> builder = ImmutableList.builder();
-        for (MobEffect effect : getHandle().h) {
+        for (MobEffect effect : getHandle().effects) {
             builder.add(CraftPotionUtil.toBukkit(effect));
         }
         return builder.build();
@@ -77,7 +77,7 @@ public class CraftTippedArrow extends CraftArrow implements TippedArrow {
 
     @Override
     public boolean hasCustomEffect(PotionEffectType type) {
-        for (MobEffect effect : getHandle().h) {
+        for (MobEffect effect : getHandle().effects) {
             if (CraftPotionUtil.equals(effect.getMobEffect(), type)) {
                 return true;
             }
@@ -87,14 +87,14 @@ public class CraftTippedArrow extends CraftArrow implements TippedArrow {
 
     @Override
     public boolean hasCustomEffects() {
-        return !getHandle().h.isEmpty();
+        return !getHandle().effects.isEmpty();
     }
 
     @Override
     public boolean removeCustomEffect(PotionEffectType effect) {
         int effectId = effect.getId();
         MobEffect existing = null;
-        for (MobEffect mobEffect : getHandle().h) {
+        for (MobEffect mobEffect : getHandle().effects) {
             if (MobEffectList.getId(mobEffect.getMobEffect()) == effectId) {
                 existing = mobEffect;
             }
@@ -102,8 +102,8 @@ public class CraftTippedArrow extends CraftArrow implements TippedArrow {
         if (existing == null) {
             return false;
         }
-        Validate.isTrue(getBasePotionData().getType() != PotionType.UNCRAFTABLE || getHandle().h.size() != 1, "Tipped Arrows must have at least 1 effect");
-        getHandle().h.remove(existing);
+        Validate.isTrue(getBasePotionData().getType() != PotionType.UNCRAFTABLE || !getHandle().effects.isEmpty(), "Tipped Arrows must have at least 1 effect");
+        getHandle().effects.remove(existing);
         getHandle().refreshEffects();
         return true;
     }
@@ -111,7 +111,7 @@ public class CraftTippedArrow extends CraftArrow implements TippedArrow {
     @Override
     public void setBasePotionData(PotionData data) {
         Validate.notNull(data, "PotionData cannot be null");
-        Validate.isTrue(data.getType() != PotionType.UNCRAFTABLE || !getHandle().h.isEmpty(), "Tipped Arrows must have at least 1 effect");
+        Validate.isTrue(data.getType() != PotionType.UNCRAFTABLE || !getHandle().effects.isEmpty(), "Tipped Arrows must have at least 1 effect");
         getHandle().setType(CraftPotionUtil.fromBukkit(data));
     }
 
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
index 7bb21dbbae..04919b2c46 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftVillager.java
@@ -39,12 +39,12 @@ public class CraftVillager extends CraftAgeable implements Villager, InventoryHo
     }
 
     public Profession getProfession() {
-        return Profession.getProfession(getHandle().getProfession());
+        return Profession.values()[getHandle().getProfession()];
     }
 
     public void setProfession(Profession profession) {
         Validate.notNull(profession);
-        getHandle().setProfession(profession.getId());
+        getHandle().setProfession(profession.ordinal());
     }
 
     @Override
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
index 6431d041a1..3e1fc532d7 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftZombie.java
@@ -1,6 +1,7 @@
 package org.bukkit.craftbukkit.entity;
 
 import net.minecraft.server.EntityZombie;
+import net.minecraft.server.EnumZombieType;
 
 import org.bukkit.craftbukkit.CraftServer;
 import org.bukkit.entity.EntityType;
@@ -40,25 +41,17 @@ public class CraftZombie extends CraftMonster implements Zombie {
     }
 
     public void setVillager(boolean flag) {
-        if (flag) {
-            getHandle().setVillagerType(0);
-        } else {
-            getHandle().clearVillagerType();
-        }
+        getHandle().setVillagerType(flag ? EnumZombieType.NORMAL : EnumZombieType.VILLAGER_FARMER);
     }
 
     @Override
     public void setVillagerProfession(Villager.Profession profession) {
-        if (profession == null) {
-            getHandle().clearVillagerType();
-        } else {
-            getHandle().setVillagerType(profession.getId());
-        }
+        getHandle().setVillagerType(profession == null ? EnumZombieType.NORMAL : EnumZombieType.a(profession.ordinal()));
     }
 
     @Override
     public Villager.Profession getVillagerProfession() {
-        if (!isVillager()) return null;
-        return Villager.Profession.getProfession(getHandle().getVillagerType());
+        if (!isVillager()) return Villager.Profession.NORMAL;
+        return Villager.Profession.values()[getHandle().getVillagerType().ordinal()];
     }
 }
diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
index edfd031100..2961e0dc70 100644
--- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
+++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java
@@ -493,10 +493,10 @@ public class CraftEventFactory {
             DamageCause cause = null;
             Block damager = blockDamage;
             blockDamage = null;
-            if (source == DamageSource.CACTUS) {
+            if (source == DamageSource.CACTUS || source == DamageSource.HOT_FLOOR) {
                 cause = DamageCause.CONTACT;
             } else {
-                throw new AssertionError(String.format("Unhandled damage of %s by %s from %s", entity, damager, source.translationIndex));
+                throw new IllegalStateException(String.format("Unhandled damage of %s by %s from %s", entity, damager, source.translationIndex));
             }
             EntityDamageEvent event = callEvent(new EntityDamageByBlockEvent(damager, entity.getBukkitEntity(), cause, modifiers, modifierFunctions));
             if (!event.isCancelled()) {
@@ -516,7 +516,7 @@ public class CraftEventFactory {
             } else if (source == DamageSource.DRAGON_BREATH) {
                 cause = DamageCause.DRAGON_BREATH;
             } else {
-                throw new AssertionError(String.format("Unhandled damage of %s by %s from %s", entity, damager.getHandle(), source.translationIndex));
+                throw new IllegalStateException(String.format("Unhandled damage of %s by %s from %s", entity, damager.getHandle(), source.translationIndex));
             }
             EntityDamageEvent event = callEvent(new EntityDamageByEntityEvent(damager, entity.getBukkitEntity(), cause, modifiers, modifierFunctions));
             if (!event.isCancelled()) {
@@ -556,7 +556,7 @@ public class CraftEventFactory {
             return callEntityDamageEvent(null, entity, cause, modifiers, modifierFunctions);
         }
 
-        throw new AssertionError(String.format("Unhandled damage of %s from %s", entity, source.translationIndex));
+        throw new IllegalStateException(String.format("Unhandled damage of %s from %s", entity, source.translationIndex));
     }
 
     private static EntityDamageEvent callEntityDamageEvent(Entity damager, Entity damagee, DamageCause cause, Map<DamageModifier, Double> modifiers, Map<DamageModifier, Function<? super Double, Double>> modifierFunctions) {
diff --git a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java
index f0f891daa8..ee36785e9e 100644
--- a/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java
+++ b/src/main/java/org/bukkit/craftbukkit/inventory/CraftMetaBlockState.java
@@ -194,7 +194,7 @@ public class CraftMetaBlockState extends CraftMetaItem implements BlockStateMeta
         if (blockEntityTag != null && material == Material.SHIELD) {
             blockEntityTag.setString("id", "Banner"); // Hack
         }
-        TileEntity te = blockEntityTag == null ? null : TileEntity.c(blockEntityTag);
+        TileEntity te = (blockEntityTag == null) ? null : TileEntity.a(null, blockEntityTag);
 
         switch (material) {
         case SIGN:
diff --git a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java
index 5a8b77a01b..8483cd85d9 100644
--- a/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java
+++ b/src/main/java/org/bukkit/craftbukkit/potion/CraftPotionUtil.java
@@ -1,5 +1,6 @@
 package org.bukkit.craftbukkit.potion;
 
+import com.google.common.base.Preconditions;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.ImmutableBiMap;
 
@@ -58,13 +59,17 @@ public class CraftPotionUtil {
             .build();
 
     public static String fromBukkit(PotionData data) {
+        String type;
         if (data.isUpgraded()) {
-            return upgradeable.get(data.getType());
+            type = upgradeable.get(data.getType());
+        } else if (data.isExtended()) {
+            type = extendable.get(data.getType());
+        } else {
+            type = regular.get(data.getType());
         }
-        if (data.isExtended()) {
-            return extendable.get(data.getType());
-        }
-        return regular.get(data.getType());
+        Preconditions.checkNotNull(type, "Unknown potion type from data " + data);
+
+        return "minecraft:" + type;
     }
 
     public static PotionData toBukkit(String type) {
diff --git a/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java b/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
index 057ae24335..744da023de 100644
--- a/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
+++ b/src/main/java/org/bukkit/craftbukkit/projectiles/CraftBlockProjectileSource.java
@@ -71,7 +71,7 @@ public class CraftBlockProjectileSource implements BlockProjectileSource {
         SourceBlock isourceblock = new SourceBlock(dispenserBlock.getWorld(), dispenserBlock.getPosition());
         // Copied from DispenseBehaviorProjectile
         IPosition iposition = BlockDispenser.a(isourceblock);
-        EnumDirection enumdirection = BlockDispenser.e(isourceblock.f());
+        EnumDirection enumdirection = (EnumDirection) isourceblock.e().get(BlockDispenser.FACING);
         net.minecraft.server.World world = dispenserBlock.getWorld();
         net.minecraft.server.Entity launch = null;
 
diff --git a/src/test/java/org/bukkit/BiomeTest.java b/src/test/java/org/bukkit/BiomeTest.java
index 0dcfc56b65..17a8005a2b 100644
--- a/src/test/java/org/bukkit/BiomeTest.java
+++ b/src/test/java/org/bukkit/BiomeTest.java
@@ -18,8 +18,8 @@ public class BiomeTest extends AbstractTestingBase {
 
     @Test
     public void testMinecraftToBukkit() {
-        for (BiomeBase biome : BiomeBase.REGISTRY_ID) {
-            Assert.assertNotNull("No Bukkit mapping for " + biome, CraftBlock.biomeBaseToBiome(biome));
+        for (Object biome : BiomeBase.REGISTRY_ID) {
+            Assert.assertNotNull("No Bukkit mapping for " + biome, CraftBlock.biomeBaseToBiome((BiomeBase) biome));
         }
     }
 }
diff --git a/src/test/java/org/bukkit/potion/PotionTest.java b/src/test/java/org/bukkit/potion/PotionTest.java
index 77d858bc0b..e46429a59b 100644
--- a/src/test/java/org/bukkit/potion/PotionTest.java
+++ b/src/test/java/org/bukkit/potion/PotionTest.java
@@ -17,8 +17,8 @@ public class PotionTest extends AbstractTestingBase {
     @Test
     public void testEffectCompleteness() throws Throwable {
         Map<PotionType, String> effects = new EnumMap(PotionType.class);
-        for (PotionRegistry reg : PotionRegistry.a) {
-            List<MobEffect> eff = reg.a();
+        for (Object reg : PotionRegistry.a) {
+            List<MobEffect> eff = ((PotionRegistry)reg).a();
             if (eff.size() != 1) continue;
             int id = MobEffectList.getId(eff.get(0).getMobEffect());
             PotionEffectType type = PotionEffectType.getById(id);
diff --git a/src/test/java/org/bukkit/support/AbstractTestingBase.java b/src/test/java/org/bukkit/support/AbstractTestingBase.java
index 7978f4aa08..86c2b97135 100644
--- a/src/test/java/org/bukkit/support/AbstractTestingBase.java
+++ b/src/test/java/org/bukkit/support/AbstractTestingBase.java
@@ -68,7 +68,6 @@ public abstract class AbstractTestingBase {
                     Material.PURPUR_DOUBLE_SLAB,
                     Material.BEETROOT_BLOCK,
                     Material.END_GATEWAY,
-                    Material.STRUCTURE_BLOCK,
                     Material.BURNING_FURNACE,
                     Material.FROSTED_ICE
             ).build();