--- ../src-base/minecraft/net/minecraft/world/chunk/Chunk.java
+++ ../src-work/minecraft/net/minecraft/world/chunk/Chunk.java
@@ -35,6 +35,9 @@
 import net.minecraft.world.gen.ChunkProviderDebug;
 import net.minecraftforge.fml.relauncher.Side;
 import net.minecraftforge.fml.relauncher.SideOnly;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.event.entity.EntityEvent;
+import net.minecraftforge.event.world.ChunkEvent;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
@@ -174,7 +177,7 @@
                     {
                         Block block = this.func_150810_a(j, l - 1, k);
 
-                        if (block.func_149717_k() == 0)
+                        if (func_150808_b(j, l - 1, k) == 0)
                         {
                             --l;
                             continue;
@@ -469,12 +472,12 @@
 
     public int func_177437_b(BlockPos p_177437_1_)
     {
-        return this.func_177428_a(p_177437_1_).func_149717_k();
+        return this.func_177428_a(p_177437_1_).getLightOpacity(field_76637_e, p_177437_1_);
     }
 
     private int func_150808_b(int p_150808_1_, int p_150808_2_, int p_150808_3_)
     {
-        return this.func_150810_a(p_150808_1_, p_150808_2_, p_150808_3_).func_149717_k();
+        return func_177437_b(new BlockPos((field_76635_g << 4) + p_150808_1_, p_150808_2_, (field_76647_h << 4) + p_150808_3_));
     }
 
     private Block func_150810_a(int p_150810_1_, int p_150810_2_, int p_150810_3_)
@@ -653,16 +656,20 @@
                 flag = j >= i1;
             }
 
+            int j1 = block.getLightOpacity(this.field_76637_e, p_177436_1_);
+
             extendedblockstorage.func_177484_a(i, j & 15, k, p_177436_2_);
 
-            if (block1 != block)
+            //if (block1 != block)
             {
                 if (!this.field_76637_e.field_72995_K)
                 {
                     block1.func_180663_b(this.field_76637_e, p_177436_1_, iblockstate1);
                 }
-                else if (block1 instanceof ITileEntityProvider)
+                else if (block1.hasTileEntity(iblockstate1))
                 {
+                    TileEntity te = this.func_177424_a(p_177436_1_, Chunk.EnumCreateEntityType.CHECK);
+                    if (te != null && te.shouldRefresh(this.field_76637_e, p_177436_1_, iblockstate1, p_177436_2_))
                     this.field_76637_e.func_175713_t(p_177436_1_);
                 }
             }
@@ -679,8 +686,7 @@
                 }
                 else
                 {
-                    int j1 = block.func_149717_k();
-                    int k1 = block1.func_149717_k();
+                    int k1 = block.getLightOpacity(this.field_76637_e, p_177436_1_);
 
                     if (j1 > 0)
                     {
@@ -702,28 +708,18 @@
 
                 TileEntity tileentity;
 
-                if (block1 instanceof ITileEntityProvider)
-                {
-                    tileentity = this.func_177424_a(p_177436_1_, Chunk.EnumCreateEntityType.CHECK);
-
-                    if (tileentity != null)
-                    {
-                        tileentity.func_145836_u();
-                    }
-                }
-
                 if (!this.field_76637_e.field_72995_K && block1 != block)
                 {
                     block.func_176213_c(this.field_76637_e, p_177436_1_, p_177436_2_);
                 }
 
-                if (block instanceof ITileEntityProvider)
+                if (block.hasTileEntity(p_177436_2_))
                 {
                     tileentity = this.func_177424_a(p_177436_1_, Chunk.EnumCreateEntityType.CHECK);
 
                     if (tileentity == null)
                     {
-                        tileentity = ((ITileEntityProvider)block).func_149915_a(this.field_76637_e, block.func_176201_c(p_177436_2_));
+                        tileentity = block.createTileEntity(this.field_76637_e, p_177436_2_);
                         this.field_76637_e.func_175690_a(p_177436_1_, tileentity);
                     }
 
@@ -826,6 +822,7 @@
             k = this.field_76645_j.length - 1;
         }
 
+        MinecraftForge.EVENT_BUS.post(new EntityEvent.EnteringChunk(p_76612_1_, this.field_76635_g, this.field_76647_h, p_76612_1_.field_70176_ah, p_76612_1_.field_70164_aj));
         p_76612_1_.field_70175_ag = true;
         p_76612_1_.field_70176_ah = this.field_76635_g;
         p_76612_1_.field_70162_ai = k;
@@ -864,13 +861,20 @@
     private TileEntity func_177422_i(BlockPos p_177422_1_)
     {
         Block block = this.func_177428_a(p_177422_1_);
-        return !block.func_149716_u() ? null : ((ITileEntityProvider)block).func_149915_a(this.field_76637_e, this.func_177418_c(p_177422_1_));
+        IBlockState state = block.func_176203_a(this.func_177418_c(p_177422_1_));
+        return !block.hasTileEntity(state) ? null : block.createTileEntity(this.field_76637_e, state);
     }
 
     public TileEntity func_177424_a(BlockPos p_177424_1_, Chunk.EnumCreateEntityType p_177424_2_)
     {
         TileEntity tileentity = (TileEntity)this.field_150816_i.get(p_177424_1_);
 
+        if (tileentity != null && tileentity.func_145837_r())
+        {
+            field_150816_i.remove(p_177424_1_);
+            tileentity = null;
+        }
+
         if (tileentity == null)
         {
             if (p_177424_2_ == Chunk.EnumCreateEntityType.IMMEDIATE)
@@ -883,11 +887,6 @@
                 this.field_177447_w.add(p_177424_1_);
             }
         }
-        else if (tileentity.func_145837_r())
-        {
-            this.field_150816_i.remove(p_177424_1_);
-            return null;
-        }
 
         return tileentity;
     }
@@ -907,7 +906,7 @@
         p_177426_2_.func_145834_a(this.field_76637_e);
         p_177426_2_.func_174878_a(p_177426_1_);
 
-        if (this.func_177428_a(p_177426_1_) instanceof ITileEntityProvider)
+        if (this.func_177428_a(p_177426_1_).hasTileEntity(func_177428_a(p_177426_1_).func_176203_a(this.func_177418_c(p_177426_1_))))
         {
             if (this.field_150816_i.containsKey(p_177426_1_))
             {
@@ -949,6 +948,7 @@
 
             this.field_76637_e.func_175650_b(this.field_76645_j[i]);
         }
+        MinecraftForge.EVENT_BUS.post(new ChunkEvent.Load(this));
     }
 
     public void func_76623_d()
@@ -966,6 +966,7 @@
         {
             this.field_76637_e.func_175681_c(this.field_76645_j[i]);
         }
+        MinecraftForge.EVENT_BUS.post(new ChunkEvent.Unload(this));
     }
 
     public void func_76630_e()
@@ -975,8 +976,8 @@
 
     public void func_177414_a(Entity p_177414_1_, AxisAlignedBB p_177414_2_, List p_177414_3_, Predicate p_177414_4_)
     {
-        int i = MathHelper.func_76128_c((p_177414_2_.field_72338_b - 2.0D) / 16.0D);
-        int j = MathHelper.func_76128_c((p_177414_2_.field_72337_e + 2.0D) / 16.0D);
+        int i = MathHelper.func_76128_c((p_177414_2_.field_72338_b - World.MAX_ENTITY_RADIUS) / 16.0D);
+        int j = MathHelper.func_76128_c((p_177414_2_.field_72337_e + World.MAX_ENTITY_RADIUS) / 16.0D);
         i = MathHelper.func_76125_a(i, 0, this.field_76645_j.length - 1);
         j = MathHelper.func_76125_a(j, 0, this.field_76645_j.length - 1);
 
@@ -1012,8 +1013,8 @@
 
     public void func_177430_a(Class p_177430_1_, AxisAlignedBB p_177430_2_, List p_177430_3_, Predicate p_177430_4_)
     {
-        int i = MathHelper.func_76128_c((p_177430_2_.field_72338_b - 2.0D) / 16.0D);
-        int j = MathHelper.func_76128_c((p_177430_2_.field_72337_e + 2.0D) / 16.0D);
+        int i = MathHelper.func_76128_c((p_177430_2_.field_72338_b - World.MAX_ENTITY_RADIUS) / 16.0D);
+        int j = MathHelper.func_76128_c((p_177430_2_.field_72337_e + World.MAX_ENTITY_RADIUS) / 16.0D);
         i = MathHelper.func_76125_a(i, 0, this.field_76645_j.length - 1);
         j = MathHelper.func_76125_a(j, 0, this.field_76645_j.length - 1);
 
@@ -1179,8 +1180,10 @@
         while (!this.field_177447_w.isEmpty())
         {
             BlockPos blockpos = (BlockPos)this.field_177447_w.poll();
+            Block block = this.func_177428_a(blockpos);
+            IBlockState state = block.func_176203_a(this.func_177418_c(blockpos));
 
-            if (this.func_177424_a(blockpos, Chunk.EnumCreateEntityType.CHECK) == null && this.func_177428_a(blockpos).func_149716_u())
+            if (this.func_177424_a(blockpos, Chunk.EnumCreateEntityType.CHECK) == null && block.hasTileEntity(state))
             {
                 TileEntity tileentity = this.func_177422_i(blockpos);
                 this.field_76637_e.func_175690_a(blockpos, tileentity);
@@ -1242,6 +1245,15 @@
     @SideOnly(Side.CLIENT)
     public void func_177439_a(byte[] p_177439_1_, int p_177439_2_, boolean p_177439_3_)
     {
+        Iterator iterator = field_150816_i.values().iterator();
+        while(iterator.hasNext())
+        {
+            TileEntity tileEntity = (TileEntity)iterator.next();
+            tileEntity.func_145836_u();
+            tileEntity.func_145832_p();
+            tileEntity.func_145838_q();
+        }
+
         int j = 0;
         boolean flag1 = !this.field_76637_e.field_73011_w.func_177495_o();
         int k;
@@ -1311,13 +1323,18 @@
         this.field_150814_l = true;
         this.field_76646_k = true;
         this.func_76590_a();
-        Iterator iterator = this.field_150816_i.values().iterator();
+        List<TileEntity> invalidList = new java.util.ArrayList<TileEntity>();
+        iterator = this.field_150816_i.values().iterator();
 
         while (iterator.hasNext())
         {
             TileEntity tileentity = (TileEntity)iterator.next();
+            if (tileentity.func_145838_q() != func_177428_a(tileentity.func_174877_v()) || tileentity.func_145832_p() != func_177418_c(tileentity.func_174877_v()))
+                invalidList.add(tileentity);
             tileentity.func_145836_u();
         }
+
+        for (TileEntity te : invalidList) te.func_145843_s();
     }
 
     public BiomeGenBase func_177411_a(BlockPos p_177411_1_, WorldChunkManager p_177411_2_)
@@ -1644,4 +1661,20 @@
 
         private static final String __OBFID = "CL_00002009";
     }
+
+    /**
+     * Removes the tile entity at the specified position, only if it's
+     * marked as invalid.
+     */
+    public void removeInvalidTileEntity(BlockPos pos)
+    {
+        if (field_76636_d)
+        {
+            TileEntity entity = (TileEntity)field_150816_i.get(pos);
+            if (entity != null && entity.func_145837_r())
+            {
+                field_150816_i.remove(pos);
+            }
+        }
+    }
 }
