--- ../src-base/minecraft/net/minecraft/world/World.java
+++ ../src-work/minecraft/net/minecraft/world/World.java
@@ -56,8 +56,30 @@
 import net.minecraftforge.fml.relauncher.Side;
 import net.minecraftforge.fml.relauncher.SideOnly;
 
+import net.minecraftforge.fml.common.FMLLog;
+import com.google.common.collect.ImmutableSetMultimap;
+import net.minecraftforge.client.ForgeHooksClient;
+import net.minecraftforge.common.ForgeChunkManager;
+import net.minecraftforge.common.ForgeChunkManager.Ticket;
+import net.minecraftforge.common.ForgeModContainer;
+import net.minecraftforge.common.ForgeHooks;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.common.WorldSpecificSaveHandler;
+import net.minecraftforge.event.entity.EntityEvent;
+import net.minecraftforge.event.entity.EntityJoinWorldEvent;
+import net.minecraftforge.event.world.WorldEvent;
+import net.minecraftforge.event.entity.PlaySoundAtEntityEvent;
+import net.minecraft.entity.EnumCreatureType;
+
 public abstract class World implements IBlockAccess
 {
+   /**
+     * Used in the getEntitiesWithinAABB functions to expand the search area for entities.
+     * Modders should change this variable to a higher value if it is less then the radius
+     * of one of there entities.
+     */
+    public static double MAX_ENTITY_RADIUS = 2.0D;
+
     protected boolean field_72999_e;
     public final List field_72996_f = Lists.newArrayList();
     protected final List field_72997_g = Lists.newArrayList();
@@ -99,6 +121,10 @@
     int[] field_72994_J;
     private static final String __OBFID = "CL_00000140";
 
+    public boolean restoringBlockSnapshots = false;
+    public boolean captureBlockSnapshots = false;
+    public ArrayList<net.minecraftforge.common.util.BlockSnapshot> capturedBlockSnapshots = new ArrayList<net.minecraftforge.common.util.BlockSnapshot>();
+
     protected World(ISaveHandler p_i45749_1_, WorldInfo p_i45749_2_, WorldProvider p_i45749_3_, Profiler p_i45749_4_, boolean p_i45749_5_)
     {
         this.field_72990_M = this.field_73012_v.nextInt(12000);
@@ -111,6 +137,7 @@
         this.field_73011_w = p_i45749_3_;
         this.field_72995_K = p_i45749_5_;
         this.field_175728_M = p_i45749_3_.func_177501_r();
+        perWorldStorage = new MapStorage((ISaveHandler)null);
     }
 
     public World func_175643_b()
@@ -120,13 +147,18 @@
 
     public BiomeGenBase func_180494_b(final BlockPos p_180494_1_)
     {
-        if (this.func_175667_e(p_180494_1_))
+        return this.field_73011_w.getBiomeGenForCoords(p_180494_1_);
+    }
+
+    public BiomeGenBase getBiomeGenForCoordsBody(final BlockPos pos)
+    {
+        if (this.func_175667_e(pos))
         {
-            Chunk chunk = this.func_175726_f(p_180494_1_);
+            Chunk chunk = this.func_175726_f(pos);
 
             try
             {
-                return chunk.func_177411_a(p_180494_1_, this.field_73011_w.func_177499_m());
+                return chunk.func_177411_a(pos, this.field_73011_w.func_177499_m());
             }
             catch (Throwable throwable)
             {
@@ -137,7 +169,7 @@
                     private static final String __OBFID = "CL_00000141";
                     public String call()
                     {
-                        return CrashReportCategory.func_180522_a(p_180494_1_);
+                        return CrashReportCategory.func_180522_a(pos);
                     }
                 });
                 throw new ReportedException(crashreport);
@@ -145,7 +177,7 @@
         }
         else
         {
-            return this.field_73011_w.func_177499_m().func_180300_a(p_180494_1_, BiomeGenBase.field_76772_c);
+            return this.field_73011_w.func_177499_m().func_180300_a(pos, BiomeGenBase.field_76772_c);
         }
     }
 
@@ -186,7 +218,7 @@
 
     public boolean func_175623_d(BlockPos p_175623_1_)
     {
-        return this.func_180495_p(p_175623_1_).func_177230_c().func_149688_o() == Material.field_151579_a;
+        return this.func_180495_p(p_175623_1_).func_177230_c().isAir(this, p_175623_1_);
     }
 
     public boolean func_175667_e(BlockPos p_175667_1_)
@@ -286,6 +318,14 @@
         {
             Chunk chunk = this.func_175726_f(p_180501_1_);
             Block block = p_180501_2_.func_177230_c();
+
+            net.minecraftforge.common.util.BlockSnapshot blockSnapshot = null;
+            if (this.captureBlockSnapshots && !this.field_72995_K)
+            {
+                blockSnapshot = net.minecraftforge.common.util.BlockSnapshot.getBlockSnapshot(this, p_180501_1_, p_180501_3_);
+                this.capturedBlockSnapshots.add(blockSnapshot);
+            }
+
             IBlockState iblockstate1 = chunk.func_177436_a(p_180501_1_, p_180501_2_);
 
             if (iblockstate1 == null)
@@ -294,6 +334,12 @@
             }
             else
             {
+                if (blockSnapshot != null)
+                {
+                    this.capturedBlockSnapshots.remove(blockSnapshot);
+                    blockSnapshot = null;
+                }
+
                 Block block1 = iblockstate1.func_177230_c();
 
                 if (block.func_149717_k() != block1.func_149717_k() || block.func_149750_m() != block1.func_149750_m())
@@ -303,22 +349,31 @@
                     this.field_72984_F.func_76319_b();
                 }
 
-                if ((p_180501_3_ & 2) != 0 && (!this.field_72995_K || (p_180501_3_ & 4) == 0) && chunk.func_150802_k())
+                if (blockSnapshot == null) // Don't notify clients or update physics while capturing blockstates
                 {
-                    this.func_175689_h(p_180501_1_);
+                    this.markAndNotifyBlock(p_180501_1_, chunk, iblockstate1, p_180501_2_, p_180501_3_); // Modularize client and physic updates
                 }
 
-                if (!this.field_72995_K && (p_180501_3_ & 1) != 0)
-                {
-                    this.func_175722_b(p_180501_1_, iblockstate1.func_177230_c());
+                return true;
+            }
+        }
+    }
 
-                    if (block.func_149740_M())
-                    {
-                        this.func_175666_e(p_180501_1_, block);
-                    }
-                }
+    // Split off from original setBlockState(BlockPos, IBlockState Block p_147465_4_, int) method in order to directly send client and physic updates
+    public void markAndNotifyBlock(BlockPos pos, Chunk chunk, IBlockState old, IBlockState new_, int flags)
+    {
+        if ((flags & 2) != 0 && (!this.field_72995_K || (flags & 4) == 0) && chunk.func_150802_k())
+        {
+            this.func_175689_h(pos);
+        }
 
-                return true;
+        if (!this.field_72995_K && (flags & 1) != 0)
+        {
+            this.func_175722_b(pos, old.func_177230_c());
+
+            if (new_.func_177230_c().func_149740_M())
+            {
+                this.func_175666_e(pos, new_.func_177230_c());
             }
         }
     }
@@ -782,7 +837,7 @@
 
     public boolean func_72935_r()
     {
-        return this.field_73008_k < 4;
+        return this.field_73011_w.isDaytime();
     }
 
     public MovingObjectPosition func_72933_a(Vec3 p_72933_1_, Vec3 p_72933_2_)
@@ -978,6 +1033,8 @@
 
     public void func_72956_a(Entity p_72956_1_, String p_72956_2_, float p_72956_3_, float p_72956_4_)
     {
+        p_72956_2_ = net.minecraftforge.event.ForgeEventFactory.onPlaySoundAt(p_72956_1_, p_72956_2_, p_72956_3_, p_72956_4_);
+        if (p_72956_2_ == null) return;
         for (int i = 0; i < this.field_73021_x.size(); ++i)
         {
             ((IWorldAccess)this.field_73021_x.get(i)).func_72704_a(p_72956_2_, p_72956_1_.field_70165_t, p_72956_1_.field_70163_u, p_72956_1_.field_70161_v, p_72956_3_, p_72956_4_);
@@ -986,6 +1043,8 @@
 
     public void func_85173_a(EntityPlayer p_85173_1_, String p_85173_2_, float p_85173_3_, float p_85173_4_)
     {
+        p_85173_2_ = net.minecraftforge.event.ForgeEventFactory.onPlaySoundAt(p_85173_1_, p_85173_2_, p_85173_3_, p_85173_4_);
+        if (p_85173_2_ == null) return;
         for (int i = 0; i < this.field_73021_x.size(); ++i)
         {
             ((IWorldAccess)this.field_73021_x.get(i)).func_85102_a(p_85173_1_, p_85173_2_, p_85173_1_.field_70165_t, p_85173_1_.field_70163_u, p_85173_1_.field_70161_v, p_85173_3_, p_85173_4_);
@@ -1037,6 +1096,9 @@
 
     public boolean func_72838_d(Entity p_72838_1_)
     {
+        // do not drop any items while restoring blocksnapshots. Prevents dupes
+        if (!this.field_72995_K && (p_72838_1_ == null || (p_72838_1_ instanceof net.minecraft.entity.item.EntityItem && this.restoringBlockSnapshots))) return false;
+
         int i = MathHelper.func_76128_c(p_72838_1_.field_70165_t / 16.0D);
         int j = MathHelper.func_76128_c(p_72838_1_.field_70161_v / 16.0D);
         boolean flag = p_72838_1_.field_98038_p;
@@ -1059,6 +1121,8 @@
                 this.func_72854_c();
             }
 
+            if (net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(p_72838_1_, this)) && !flag) return false;
+
             this.func_72964_e(i, j).func_76612_a(p_72838_1_);
             this.field_72996_f.add(p_72838_1_);
             this.func_72923_a(p_72838_1_);
@@ -1271,17 +1335,29 @@
 
     public int func_72967_a(float p_72967_1_)
     {
+        float f2 = field_73011_w.getSunBrightnessFactor(p_72967_1_);
+        f2 = 1.0F - f2;
+        return (int)(f2 * 11.0F);
+    }
+
+    /**
+     * The current sun brightness factor for this dimension.
+     * 0.0f means no light at all, and 1.0f means maximum sunlight.
+     * Highly recommended for sunlight detection like solar panel.
+     *
+     * @return The current brightness factor
+     * */
+    public float getSunBrightnessFactor(float p_72967_1_)
+    {
         float f1 = this.func_72826_c(p_72967_1_);
         float f2 = 1.0F - (MathHelper.func_76134_b(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F);
         f2 = MathHelper.func_76131_a(f2, 0.0F, 1.0F);
         f2 = 1.0F - f2;
         f2 = (float)((double)f2 * (1.0D - (double)(this.func_72867_j(p_72967_1_) * 5.0F) / 16.0D));
         f2 = (float)((double)f2 * (1.0D - (double)(this.func_72819_i(p_72967_1_) * 5.0F) / 16.0D));
-        f2 = 1.0F - f2;
-        return (int)(f2 * 11.0F);
+        return f2;
     }
 
-    @SideOnly(Side.CLIENT)
     public void func_72848_b(IWorldAccess p_72848_1_)
     {
         this.field_73021_x.remove(p_72848_1_);
@@ -1290,6 +1366,12 @@
     @SideOnly(Side.CLIENT)
     public float func_72971_b(float p_72971_1_)
     {
+        return this.field_73011_w.getSunBrightness(p_72971_1_);
+    }
+
+    @SideOnly(Side.CLIENT)
+    public float getSunBrightnessBody(float p_72971_1_)
+    {
         float f1 = this.func_72826_c(p_72971_1_);
         float f2 = 1.0F - (MathHelper.func_76134_b(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.2F);
         f2 = MathHelper.func_76131_a(f2, 0.0F, 1.0F);
@@ -1302,6 +1384,12 @@
     @SideOnly(Side.CLIENT)
     public Vec3 func_72833_a(Entity p_72833_1_, float p_72833_2_)
     {
+        return this.field_73011_w.getSkyColor(p_72833_1_, p_72833_2_);
+    }
+
+    @SideOnly(Side.CLIENT)
+    public Vec3 getSkyColorBody(Entity p_72833_1_, float p_72833_2_)
+    {
         float f1 = this.func_72826_c(p_72833_2_);
         float f2 = MathHelper.func_76134_b(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F;
         f2 = MathHelper.func_76131_a(f2, 0.0F, 1.0F);
@@ -1309,9 +1397,7 @@
         int j = MathHelper.func_76128_c(p_72833_1_.field_70163_u);
         int k = MathHelper.func_76128_c(p_72833_1_.field_70161_v);
         BlockPos blockpos = new BlockPos(i, j, k);
-        BiomeGenBase biomegenbase = this.func_180494_b(blockpos);
-        float f3 = biomegenbase.func_180626_a(blockpos);
-        int l = biomegenbase.func_76731_a(f3);
+        int l = net.minecraftforge.client.ForgeHooksClient.getSkyBlendColour(this, blockpos);
         float f4 = (float)(l >> 16 & 255) / 255.0F;
         float f5 = (float)(l >> 8 & 255) / 255.0F;
         float f6 = (float)(l & 255) / 255.0F;
@@ -1373,6 +1459,11 @@
 
     public float func_130001_d()
     {
+        return field_73011_w.getCurrentMoonPhaseFactor();
+    }
+
+    public float getCurrentMoonPhaseFactorBody()
+    {
         return WorldProvider.field_111203_a[this.field_73011_w.func_76559_b(this.field_72986_A.func_76073_f())];
     }
 
@@ -1385,6 +1476,12 @@
     @SideOnly(Side.CLIENT)
     public Vec3 func_72824_f(float p_72824_1_)
     {
+        return this.field_73011_w.drawClouds(p_72824_1_);
+    }
+
+    @SideOnly(Side.CLIENT)
+    public Vec3 drawCloudsBody(float p_72824_1_)
+    {
         float f1 = this.func_72826_c(p_72824_1_);
         float f2 = MathHelper.func_76134_b(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.5F;
         f2 = MathHelper.func_76131_a(f2, 0.0F, 1.0F);
@@ -1442,9 +1539,9 @@
         for (blockpos1 = new BlockPos(p_175672_1_.func_177958_n(), chunk.func_76625_h() + 16, p_175672_1_.func_177952_p()); blockpos1.func_177956_o() >= 0; blockpos1 = blockpos2)
         {
             blockpos2 = blockpos1.func_177977_b();
-            Material material = chunk.func_177428_a(blockpos2).func_149688_o();
+            Block block = chunk.func_177428_a(blockpos2);
 
-            if (material.func_76230_c() && material != Material.field_151584_j)
+            if (block.func_149688_o().func_76230_c() && block.isLeaves(this, blockpos2) && !block.isFoliage(this, blockpos2))
             {
                 break;
             }
@@ -1456,6 +1553,12 @@
     @SideOnly(Side.CLIENT)
     public float func_72880_h(float p_72880_1_)
     {
+        return this.field_73011_w.getStarBrightness(p_72880_1_);
+    }
+
+    @SideOnly(Side.CLIENT)
+    public float getStarBrightnessBody(float p_72880_1_)
+    {
         float f1 = this.func_72826_c(p_72880_1_);
         float f2 = 1.0F - (MathHelper.func_76134_b(f1 * (float)Math.PI * 2.0F) * 2.0F + 0.25F);
         f2 = MathHelper.func_76131_a(f2, 0.0F, 1.0F);
@@ -1500,7 +1603,15 @@
                     entity.func_85029_a(crashreportcategory);
                 }
 
-                throw new ReportedException(crashreport);
+                if (ForgeModContainer.removeErroringEntities)
+                {
+                    FMLLog.severe(crashreport.func_71502_e());
+                    func_72900_e(entity);
+                }
+                else
+                {
+                    throw new ReportedException(crashreport);
+                }
             }
 
             if (entity.field_70128_L)
@@ -1562,7 +1673,16 @@
                     crashreport = CrashReport.func_85055_a(throwable1, "Ticking entity");
                     crashreportcategory = crashreport.func_85058_a("Entity being ticked");
                     entity.func_85029_a(crashreportcategory);
-                    throw new ReportedException(crashreport);
+                    if (ForgeModContainer.removeErroringEntities)
+                    {
+                        FMLLog.severe(crashreport.func_71502_e());
+                        func_72900_e(entity);
+                    }
+                    else
+                    {
+                        throw new ReportedException(crashreport);
+                    }
+
                 }
             }
 
@@ -1609,7 +1729,16 @@
                         CrashReport crashreport1 = CrashReport.func_85055_a(throwable, "Ticking block entity");
                         CrashReportCategory crashreportcategory1 = crashreport1.func_85058_a("Block entity being ticked");
                         tileentity.func_145828_a(crashreportcategory1);
-                        throw new ReportedException(crashreport1);
+                        if (ForgeModContainer.removeErroringTileEntities)
+                        {
+                            FMLLog.severe(crashreport1.func_71502_e());
+                            tileentity.func_145843_s();
+                            this.func_175713_t(tileentity.func_174877_v());
+                        }
+                        else
+                        {
+                            throw new ReportedException(crashreport1);
+                        }
                     }
                 }
             }
@@ -1628,6 +1757,10 @@
 
         if (!this.field_147483_b.isEmpty())
         {
+            for (Object tile : field_147483_b)
+            {
+               ((TileEntity)tile).onChunkUnload();
+            }
             this.field_175730_i.removeAll(this.field_147483_b);
             this.field_147482_g.removeAll(this.field_147483_b);
             this.field_147483_b.clear();
@@ -1668,7 +1801,8 @@
 
     public boolean func_175700_a(TileEntity p_175700_1_)
     {
-        boolean flag = this.field_147482_g.add(p_175700_1_);
+        List dest = field_147481_N ? field_147484_a : field_147482_g;
+        boolean flag = dest.add(p_175700_1_);
 
         if (flag && p_175700_1_ instanceof IUpdatePlayerListBox)
         {
@@ -1710,9 +1844,12 @@
     {
         int i = MathHelper.func_76128_c(p_72866_1_.field_70165_t);
         int j = MathHelper.func_76128_c(p_72866_1_.field_70161_v);
-        byte b0 = 32;
+        boolean isForced = getPersistentChunks().containsKey(new ChunkCoordIntPair(i >> 4, j >> 4));
+        byte b0 = isForced ? (byte)0 : 32;
+        boolean canUpdate = !p_72866_2_ || this.func_175663_a(i - b0, 0, j - b0, i + b0, 0, j + b0, true);
+        if (!canUpdate) canUpdate = net.minecraftforge.event.ForgeEventFactory.canEntityUpdate(p_72866_1_);
 
-        if (!p_72866_2_ || this.func_175663_a(i - b0, 0, j - b0, i + b0, 0, j + b0, true))
+        if (canUpdate)
         {
             p_72866_1_.field_70142_S = p_72866_1_.field_70165_t;
             p_72866_1_.field_70137_T = p_72866_1_.field_70163_u;
@@ -1839,7 +1976,7 @@
                 {
                     Block block = this.func_180495_p(new BlockPos(k1, l1, i2)).func_177230_c();
 
-                    if (block.func_149688_o() != Material.field_151579_a)
+                    if (block.isAir(this, new BlockPos(k1, l1, i2)))
                     {
                         return true;
                     }
@@ -1901,6 +2038,10 @@
                         {
                             return true;
                         }
+                        else if (block.isBurning(this, new BlockPos(k1, l1, i2)))
+                        {
+                            return true;
+                        }
                     }
                 }
             }
@@ -2185,19 +2326,28 @@
             else
             {
                 this.func_175700_a(p_175690_2_);
-                this.func_175726_f(p_175690_1_).func_177426_a(p_175690_1_, p_175690_2_);
+                Chunk chunk = this.func_175726_f(p_175690_1_); //Forge add NPE protection
+                if (chunk != null) chunk.func_177426_a(p_175690_1_, p_175690_2_);
             }
+            this.func_175666_e(p_175690_1_, func_180495_p(p_175690_1_).func_177230_c()); //Notify neighbors of changes
         }
     }
 
     public void func_175713_t(BlockPos p_175713_1_)
     {
+        //Chunk chunk = this.getChunkFromBlockCoords(pos);
+        //if (chunk != null) chunk.removeTileEntity(pos);
+        //Forge ToDO: Are these patches needed anymore?
+
         TileEntity tileentity = this.func_175625_s(p_175713_1_);
 
         if (tileentity != null && this.field_147481_N)
         {
             tileentity.func_145843_s();
             this.field_147484_a.remove(tileentity);
+            if (!(tileentity instanceof IUpdatePlayerListBox)) //Forge: If they are not tickable they wont be removed in the update loop.
+                this.field_147482_g.remove(tileentity);
+
         }
         else
         {
@@ -2210,6 +2360,7 @@
 
             this.func_175726_f(p_175713_1_).func_177425_e(p_175713_1_);
         }
+        this.func_175666_e(p_175713_1_, func_180495_p(p_175713_1_).func_177230_c()); //Notify neighbors of changes
     }
 
     public void func_147457_a(TileEntity p_147457_1_)
@@ -2228,7 +2379,7 @@
     {
         IBlockState iblockstate = p_175683_0_.func_180495_p(p_175683_1_);
         Block block = iblockstate.func_177230_c();
-        return block.func_149688_o().func_76218_k() && block.func_149686_d() ? true : (block instanceof BlockStairs ? iblockstate.func_177229_b(BlockStairs.field_176308_b) == BlockStairs.EnumHalf.TOP : (block instanceof BlockSlab ? iblockstate.func_177229_b(BlockSlab.field_176554_a) == BlockSlab.EnumBlockHalf.TOP : (block instanceof BlockHopper ? true : (block instanceof BlockSnow ? ((Integer)iblockstate.func_177229_b(BlockSnow.field_176315_a)).intValue() == 7 : false))));
+        return block.isSideSolid(p_175683_0_, p_175683_1_, EnumFacing.UP);
     }
 
     public boolean func_175677_d(BlockPos p_175677_1_, boolean p_175677_2_)
@@ -2248,7 +2399,7 @@
             else
             {
                 Block block = this.func_180495_p(p_175677_1_).func_177230_c();
-                return block.func_149688_o().func_76218_k() && block.func_149686_d();
+                return block.isNormalCube(this, p_175677_1_);
             }
         }
     }
@@ -2265,8 +2416,7 @@
 
     public void func_72891_a(boolean p_72891_1_, boolean p_72891_2_)
     {
-        this.field_72985_G = p_72891_1_;
-        this.field_72992_H = p_72891_2_;
+        this.field_73011_w.setAllowedSpawnTypes(p_72891_1_, p_72891_2_);
     }
 
     public void func_72835_b()
@@ -2276,6 +2426,11 @@
 
     protected void func_72947_a()
     {
+        this.field_73011_w.calculateInitialWeather();
+    }
+
+    public void calculateInitialWeatherBody()
+    {
         if (this.field_72986_A.func_76059_o())
         {
             this.field_73004_o = 1.0F;
@@ -2289,6 +2444,11 @@
 
     protected void func_72979_l()
     {
+        this.field_73011_w.updateWeather();
+    }
+
+    public void updateWeatherBody()
+    {
         if (!this.field_73011_w.func_177495_o())
         {
             if (!this.field_72995_K)
@@ -2383,6 +2543,7 @@
     {
         this.field_72993_I.clear();
         this.field_72984_F.func_76320_a("buildList");
+        this.field_72993_I.addAll(getPersistentChunks().keySet());
         int i;
         EntityPlayer entityplayer;
         int j;
@@ -2445,7 +2606,7 @@
             l += p_147467_1_;
             i1 += p_147467_2_;
 
-            if (block.func_149688_o() == Material.field_151579_a && this.func_175699_k(blockpos) <= this.field_73012_v.nextInt(8) && this.func_175642_b(EnumSkyBlock.SKY, blockpos) <= 0)
+            if (block.isAir(this, blockpos) && this.func_175699_k(blockpos) <= this.field_73012_v.nextInt(8) && this.func_175642_b(EnumSkyBlock.SKY, blockpos) <= 0)
             {
                 EntityPlayer entityplayer = this.func_72977_a((double)l + 0.5D, (double)j1 + 0.5D, (double)i1 + 0.5D, 8.0D);
 
@@ -2485,6 +2646,11 @@
 
     public boolean func_175670_e(BlockPos p_175670_1_, boolean p_175670_2_)
     {
+        return this.field_73011_w.canBlockFreeze(p_175670_1_, p_175670_2_);
+    }
+
+    public boolean canBlockFreezeBody(BlockPos p_175670_1_, boolean p_175670_2_)
+    {
         BiomeGenBase biomegenbase = this.func_180494_b(p_175670_1_);
         float f = biomegenbase.func_180626_a(p_175670_1_);
 
@@ -2526,6 +2692,11 @@
 
     public boolean func_175708_f(BlockPos p_175708_1_, boolean p_175708_2_)
     {
+        return this.field_73011_w.canSnowAt(p_175708_1_, p_175708_2_);
+    }
+
+    public boolean canSnowAtBody(BlockPos p_175708_1_, boolean p_175708_2_)
+    {
         BiomeGenBase biomegenbase = this.func_180494_b(p_175708_1_);
         float f = biomegenbase.func_180626_a(p_175708_1_);
 
@@ -2543,7 +2714,7 @@
             {
                 Block block = this.func_180495_p(p_175708_1_).func_177230_c();
 
-                if (block.func_149688_o() == Material.field_151579_a && Blocks.field_150431_aC.func_176196_c(this, p_175708_1_))
+                if (block.isAir(this, p_175708_1_) && Blocks.field_150431_aC.func_176196_c(this, p_175708_1_))
                 {
                     return true;
                 }
@@ -2575,10 +2746,11 @@
         else
         {
             Block block = this.func_180495_p(p_175638_1_).func_177230_c();
-            int i = p_175638_2_ == EnumSkyBlock.SKY ? 0 : block.func_149750_m();
-            int j = block.func_149717_k();
+            int blockLight = block.getLightValue(this, p_175638_1_);
+            int i = p_175638_2_ == EnumSkyBlock.SKY ? 0 : blockLight;
+            int j = block.getLightOpacity(this, p_175638_1_);
 
-            if (j >= 15 && block.func_149750_m() > 0)
+            if (j >= 15 && blockLight > 0)
             {
                 j = 1;
             }
@@ -2792,10 +2964,10 @@
     public List func_175674_a(Entity p_175674_1_, AxisAlignedBB p_175674_2_, Predicate p_175674_3_)
     {
         ArrayList arraylist = Lists.newArrayList();
-        int i = MathHelper.func_76128_c((p_175674_2_.field_72340_a - 2.0D) / 16.0D);
-        int j = MathHelper.func_76128_c((p_175674_2_.field_72336_d + 2.0D) / 16.0D);
-        int k = MathHelper.func_76128_c((p_175674_2_.field_72339_c - 2.0D) / 16.0D);
-        int l = MathHelper.func_76128_c((p_175674_2_.field_72334_f + 2.0D) / 16.0D);
+        int i = MathHelper.func_76128_c((p_175674_2_.field_72340_a - MAX_ENTITY_RADIUS) / 16.0D);
+        int j = MathHelper.func_76128_c((p_175674_2_.field_72336_d + MAX_ENTITY_RADIUS) / 16.0D);
+        int k = MathHelper.func_76128_c((p_175674_2_.field_72339_c - MAX_ENTITY_RADIUS) / 16.0D);
+        int l = MathHelper.func_76128_c((p_175674_2_.field_72334_f + MAX_ENTITY_RADIUS) / 16.0D);
 
         for (int i1 = i; i1 <= j; ++i1)
         {
@@ -2854,10 +3026,10 @@
 
     public List func_175647_a(Class p_175647_1_, AxisAlignedBB p_175647_2_, Predicate p_175647_3_)
     {
-        int i = MathHelper.func_76128_c((p_175647_2_.field_72340_a - 2.0D) / 16.0D);
-        int j = MathHelper.func_76128_c((p_175647_2_.field_72336_d + 2.0D) / 16.0D);
-        int k = MathHelper.func_76128_c((p_175647_2_.field_72339_c - 2.0D) / 16.0D);
-        int l = MathHelper.func_76128_c((p_175647_2_.field_72334_f + 2.0D) / 16.0D);
+        int i = MathHelper.func_76128_c((p_175647_2_.field_72340_a - MAX_ENTITY_RADIUS) / 16.0D);
+        int j = MathHelper.func_76128_c((p_175647_2_.field_72336_d + MAX_ENTITY_RADIUS) / 16.0D);
+        int k = MathHelper.func_76128_c((p_175647_2_.field_72339_c - MAX_ENTITY_RADIUS) / 16.0D);
+        int l = MathHelper.func_76128_c((p_175647_2_.field_72334_f + MAX_ENTITY_RADIUS) / 16.0D);
         ArrayList arraylist = Lists.newArrayList();
 
         for (int i1 = i; i1 <= j; ++i1)
@@ -2938,13 +3110,16 @@
 
     public void func_175650_b(Collection p_175650_1_)
     {
-        this.field_72996_f.addAll(p_175650_1_);
         Iterator iterator = p_175650_1_.iterator();
 
         while (iterator.hasNext())
         {
             Entity entity = (Entity)iterator.next();
-            this.func_72923_a(entity);
+            if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(entity, this)))
+            {
+                field_72996_f.add(entity);
+                this.func_72923_a(entity);
+            }
         }
     }
 
@@ -2957,7 +3132,9 @@
     {
         Block block1 = this.func_180495_p(p_175716_2_).func_177230_c();
         AxisAlignedBB axisalignedbb = p_175716_3_ ? null : p_175716_1_.func_180640_a(this, p_175716_2_, p_175716_1_.func_176223_P());
-        return axisalignedbb != null && !this.func_72917_a(axisalignedbb, p_175716_5_) ? false : (block1.func_149688_o() == Material.field_151594_q && p_175716_1_ == Blocks.field_150467_bQ ? true : block1.func_149688_o().func_76222_j() && p_175716_1_.func_176193_a(this, p_175716_2_, p_175716_4_, p_175716_6_));
+        if (axisalignedbb != null && !this.func_72917_a(axisalignedbb, p_175716_5_)) return false;
+        if (block1.func_149688_o() == Material.field_151594_q && p_175716_1_ == Blocks.field_150467_bQ) return true;
+        return block1.func_176200_f(this, p_175716_2_) && p_175716_1_.func_176193_a(this, p_175716_2_, p_175716_4_, p_175716_6_);
     }
 
     public int func_175627_a(BlockPos p_175627_1_, EnumFacing p_175627_2_)
@@ -3032,7 +3209,7 @@
     {
         IBlockState iblockstate = this.func_180495_p(p_175651_1_);
         Block block = iblockstate.func_177230_c();
-        return block.func_149721_r() ? this.func_175676_y(p_175651_1_) : block.func_180656_a(this, p_175651_1_, iblockstate, p_175651_2_);
+        return block.shouldCheckWeakPower(this, p_175651_1_, p_175651_2_) ? this.func_175676_y(p_175651_1_) : block.func_180656_a(this, p_175651_1_, iblockstate, p_175651_2_);
     }
 
     public boolean func_175640_z(BlockPos p_175640_1_)
@@ -3160,7 +3337,7 @@
 
     public long func_72905_C()
     {
-        return this.field_72986_A.func_76063_b();
+        return this.field_73011_w.getSeed();
     }
 
     public long func_82737_E()
@@ -3170,17 +3347,17 @@
 
     public long func_72820_D()
     {
-        return this.field_72986_A.func_76073_f();
+        return this.field_73011_w.getWorldTime();
     }
 
     public void func_72877_b(long p_72877_1_)
     {
-        this.field_72986_A.func_76068_b(p_72877_1_);
+        this.field_73011_w.setWorldTime(p_72877_1_);
     }
 
     public BlockPos func_175694_M()
     {
-        BlockPos blockpos = new BlockPos(this.field_72986_A.func_76079_c(), this.field_72986_A.func_76075_d(), this.field_72986_A.func_76074_e());
+        BlockPos blockpos = this.field_73011_w.getSpawnPoint();
 
         if (!this.func_175723_af().func_177746_a(blockpos))
         {
@@ -3192,7 +3369,7 @@
 
     public void func_175652_B(BlockPos p_175652_1_)
     {
-        this.field_72986_A.func_176143_a(p_175652_1_);
+        this.field_73011_w.setSpawnPoint(p_175652_1_);
     }
 
     @SideOnly(Side.CLIENT)
@@ -3212,12 +3389,18 @@
 
         if (!this.field_72996_f.contains(p_72897_1_))
         {
+            if (!net.minecraftforge.common.MinecraftForge.EVENT_BUS.post(new net.minecraftforge.event.entity.EntityJoinWorldEvent(p_72897_1_, this)))
             this.field_72996_f.add(p_72897_1_);
         }
     }
 
     public boolean func_175660_a(EntityPlayer p_175660_1_, BlockPos p_175660_2_)
     {
+        return this.field_73011_w.canMineBlock(p_175660_1_, p_175660_2_);
+    }
+
+    public boolean canMineBlockBody(EntityPlayer p_175660_1_, BlockPos p_175660_2_)
+    {
         return true;
     }
 
@@ -3307,8 +3490,7 @@
 
     public boolean func_180502_D(BlockPos p_180502_1_)
     {
-        BiomeGenBase biomegenbase = this.func_180494_b(p_180502_1_);
-        return biomegenbase.func_76736_e();
+        return this.field_73011_w.isBlockHighHumidity(p_180502_1_);
     }
 
     public MapStorage func_175693_T()
@@ -3367,12 +3549,12 @@
 
     public int func_72800_K()
     {
-        return 256;
+        return this.field_73011_w.getHeight();
     }
 
     public int func_72940_L()
     {
-        return this.field_73011_w.func_177495_o() ? 128 : 256;
+        return this.field_73011_w.getActualHeight();
     }
 
     public Random func_72843_D(int p_72843_1_, int p_72843_2_, int p_72843_3_)
@@ -3429,7 +3611,7 @@
     @SideOnly(Side.CLIENT)
     public double func_72919_O()
     {
-        return this.field_72986_A.func_76067_t().getHorizon(this);
+        return field_73011_w.getHorizon();
     }
 
     public void func_175715_c(int p_175715_1_, BlockPos p_175715_2_, int p_175715_3_)
@@ -3461,29 +3643,21 @@
 
     public void func_175666_e(BlockPos p_175666_1_, Block p_175666_2_)
     {
-        Iterator iterator = EnumFacing.Plane.HORIZONTAL.iterator();
-
-        while (iterator.hasNext())
+        for (EnumFacing enumfacing : EnumFacing.values())
         {
-            EnumFacing enumfacing = (EnumFacing)iterator.next();
             BlockPos blockpos1 = p_175666_1_.func_177972_a(enumfacing);
 
             if (this.func_175667_e(blockpos1))
             {
                 IBlockState iblockstate = this.func_180495_p(blockpos1);
-
-                if (Blocks.field_150441_bU.func_149907_e(iblockstate.func_177230_c()))
+                iblockstate.func_177230_c().onNeighborChange(this, blockpos1, p_175666_1_);
+                if (iblockstate.func_177230_c().isNormalCube(this, blockpos1))
                 {
-                    iblockstate.func_177230_c().func_176204_a(this, blockpos1, iblockstate, p_175666_2_);
-                }
-                else if (iblockstate.func_177230_c().func_149721_r())
-                {
-                    blockpos1 = blockpos1.func_177972_a(enumfacing);
-                    iblockstate = this.func_180495_p(blockpos1);
-
-                    if (Blocks.field_150441_bU.func_149907_e(iblockstate.func_177230_c()))
+                    BlockPos posOther = blockpos1.func_177972_a(enumfacing);
+                    Block other = func_180495_p(posOther).func_177230_c();
+                    if (other.getWeakChanges(this, posOther))
                     {
-                        iblockstate.func_177230_c().func_176204_a(this, blockpos1, iblockstate, p_175666_2_);
+                        other.onNeighborChange(this, posOther, p_175666_1_);
                     }
                 }
             }
@@ -3553,4 +3727,82 @@
         short short1 = 128;
         return k >= -short1 && k <= short1 && l >= -short1 && l <= short1;
     }
+
+
+    /* ======================================== FORGE START =====================================*/
+    /**
+     * Determine if the given block is considered solid on the
+     * specified side.  Used by placement logic.
+     *
+     * @param pos Block Position
+     * @param side The Side in question
+     * @return True if the side is solid
+    */
+    public boolean isSideSolid(BlockPos pos, EnumFacing side)
+    {
+       return isSideSolid(pos, side, false);
+    }
+
+    /**
+     * Determine if the given block is considered solid on the
+     * specified side.  Used by placement logic.
+     *
+     * @param pos Block Position
+     * @param side The Side in question
+     * @param _default The default to return if the block doesn't exist.
+     * @return True if the side is solid
+     */
+    @Override
+    public boolean isSideSolid(BlockPos pos, EnumFacing side, boolean _default)
+    {
+        if (!this.func_175701_a(pos)) return _default;
+
+        Chunk chunk = func_175726_f(pos);
+        if (chunk == null || chunk.func_76621_g()) return _default;
+        return func_180495_p(pos).func_177230_c().isSideSolid(this, pos, side);
+    }
+
+    /**
+     * Get the persistent chunks for this world
+     *
+     * @return
+     */
+    public ImmutableSetMultimap<ChunkCoordIntPair, Ticket> getPersistentChunks()
+    {
+        return ForgeChunkManager.getPersistentChunksFor(this);
+    }
+
+    /**
+     * Readded as it was removed, very useful helper function
+     *
+     * @param pos Block position
+     * @return The blocks light opacity
+     */
+    public int getBlockLightOpacity(BlockPos pos)
+    {
+        if (!this.func_175701_a(pos)) return 0;
+        return func_175726_f(pos).func_177437_b(pos);
+    }
+
+    /**
+     * Returns a count of entities that classify themselves as the specified creature type.
+     */
+    public int countEntities(EnumCreatureType type, boolean forSpawnCount)
+    {
+        int count = 0;
+        for (int x = 0; x < field_72996_f.size(); x++)
+        {
+            if (((Entity)field_72996_f.get(x)).isCreatureType(type, forSpawnCount))
+            {
+                count++;
+            }
+        }
+        return count;
+    }
+
+    protected MapStorage perWorldStorage; //Moved to a getter to simulate final without being final so we can load in subclasses.
+    public MapStorage getPerWorldStorage()
+    {
+        return perWorldStorage;
+    }
 }
