--- ../src-base/minecraft/net/minecraft/block/Block.java
+++ ../src-work/minecraft/net/minecraft/block/Block.java
@@ -140,7 +140,8 @@
 
     public static Block func_149729_e(int p_149729_0_)
     {
-        return (Block)field_149771_c.func_148754_a(p_149729_0_);
+        Block ret = (Block)field_149771_c.func_148754_a(p_149729_0_);
+        return ret == null ? net.minecraft.init.Blocks.field_150350_a : ret;
     }
 
     public static IBlockState func_176220_d(int p_176220_0_)
@@ -341,9 +342,10 @@
         return this.field_149789_z;
     }
 
+    @Deprecated //Forge: New State sensitive version.
     public boolean func_149716_u()
     {
-        return this.field_149758_A;
+        return hasTileEntity(func_176223_P());
     }
 
     public final void func_149676_a(float p_149676_1_, float p_149676_2_, float p_149676_3_, float p_149676_4_, float p_149676_5_, float p_149676_6_)
@@ -360,13 +362,13 @@
     public int func_176207_c(IBlockAccess p_176207_1_, BlockPos p_176207_2_)
     {
         Block block = p_176207_1_.func_180495_p(p_176207_2_).func_177230_c();
-        int i = p_176207_1_.func_175626_b(p_176207_2_, block.func_149750_m());
+        int i = p_176207_1_.func_175626_b(p_176207_2_, block.getLightValue(p_176207_1_, p_176207_2_));
 
         if (i == 0 && block instanceof BlockSlab)
         {
             p_176207_2_ = p_176207_2_.func_177977_b();
             block = p_176207_1_.func_180495_p(p_176207_2_).func_177230_c();
-            return p_176207_1_.func_175626_b(p_176207_2_, block.func_149750_m());
+            return p_176207_1_.func_175626_b(p_176207_2_, block.getLightValue(p_176207_1_, p_176207_2_));
         }
         else
         {
@@ -442,7 +444,13 @@
 
     public void func_176213_c(World p_176213_1_, BlockPos p_176213_2_, IBlockState p_176213_3_) {}
 
-    public void func_180663_b(World p_180663_1_, BlockPos p_180663_2_, IBlockState p_180663_3_) {}
+    public void func_180663_b(World p_180663_1_, BlockPos p_180663_2_, IBlockState p_180663_3_)
+    {
+        if (hasTileEntity(p_180663_3_) && !(this instanceof BlockContainer))
+        {
+            p_180663_1_.func_175713_t(p_180663_2_);
+        }
+    }
 
     public int func_149745_a(Random p_149745_1_)
     {
@@ -456,8 +464,7 @@
 
     public float func_180647_a(EntityPlayer p_180647_1_, World p_180647_2_, BlockPos p_180647_3_)
     {
-        float f = this.func_176195_g(p_180647_2_, p_180647_3_);
-        return f < 0.0F ? 0.0F : (!p_180647_1_.func_146099_a(this) ? p_180647_1_.func_180471_a(this) / f / 100.0F : p_180647_1_.func_180471_a(this) / f / 30.0F);
+        return net.minecraftforge.common.ForgeHooks.blockStrength(p_180647_2_.func_180495_p(p_180647_3_), p_180647_1_, p_180647_2_, p_180647_3_);
     }
 
     public final void func_176226_b(World p_176226_1_, BlockPos p_176226_2_, IBlockState p_176226_3_, int p_176226_4_)
@@ -467,20 +474,16 @@
 
     public void func_180653_a(World p_180653_1_, BlockPos p_180653_2_, IBlockState p_180653_3_, float p_180653_4_, int p_180653_5_)
     {
-        if (!p_180653_1_.field_72995_K)
+        if (!p_180653_1_.field_72995_K && !p_180653_1_.restoringBlockSnapshots) // do not drop items while restoring blockstates, prevents item dupe
         {
-            int j = this.func_149679_a(p_180653_5_, p_180653_1_.field_73012_v);
+            java.util.List<ItemStack> items = getDrops(p_180653_1_, p_180653_2_, p_180653_1_.func_180495_p(p_180653_2_), p_180653_5_);
+            p_180653_4_ = net.minecraftforge.event.ForgeEventFactory.fireBlockHarvesting(items, p_180653_1_, p_180653_2_, p_180653_3_, p_180653_5_, p_180653_4_, false, harvesters.get());
 
-            for (int k = 0; k < j; ++k)
+            for (ItemStack item : items)
             {
                 if (p_180653_1_.field_73012_v.nextFloat() <= p_180653_4_)
                 {
-                    Item item = this.func_180660_a(p_180653_3_, p_180653_1_.field_73012_v, p_180653_5_);
-
-                    if (item != null)
-                    {
-                        func_180635_a(p_180653_1_, p_180653_2_, new ItemStack(item, 1, this.func_180651_a(p_180653_3_)));
-                    }
+                    func_180635_a(p_180653_1_, p_180653_2_, item);
                 }
             }
         }
@@ -488,8 +491,13 @@
 
     public static void func_180635_a(World p_180635_0_, BlockPos p_180635_1_, ItemStack p_180635_2_)
     {
-        if (!p_180635_0_.field_72995_K && p_180635_0_.func_82736_K().func_82766_b("doTileDrops"))
+        if (!p_180635_0_.field_72995_K && p_180635_0_.func_82736_K().func_82766_b("doTileDrops") && !p_180635_0_.restoringBlockSnapshots) // do not drop items while restoring blockstates, prevents item dupe
         {
+            if (captureDrops.get())
+            {
+                capturedDrops.get().add(p_180635_2_);
+                return;
+            }
             float f = 0.5F;
             double d0 = (double)(p_180635_0_.field_73012_v.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
             double d1 = (double)(p_180635_0_.field_73012_v.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
@@ -674,7 +682,7 @@
 
     public boolean func_176196_c(World p_176196_1_, BlockPos p_176196_2_)
     {
-        return p_176196_1_.func_180495_p(p_176196_2_).func_177230_c().field_149764_J.func_76222_j();
+        return p_176196_1_.func_180495_p(p_176196_2_).func_177230_c().func_176200_f(p_176196_1_, p_176196_2_);
     }
 
     public boolean func_180639_a(World p_180639_1_, BlockPos p_180639_2_, IBlockState p_180639_3_, EntityPlayer p_180639_4_, EnumFacing p_180639_5_, float p_180639_6_, float p_180639_7_, float p_180639_8_)
@@ -776,25 +784,35 @@
         p_180657_2_.func_71029_a(StatList.field_75934_C[func_149682_b(this)]);
         p_180657_2_.func_71020_j(0.025F);
 
-        if (this.func_149700_E() && EnchantmentHelper.func_77502_d(p_180657_2_))
+        if (this.canSilkHarvest(p_180657_1_, p_180657_3_, p_180657_1_.func_180495_p(p_180657_3_), p_180657_2_) && EnchantmentHelper.func_77502_d(p_180657_2_))
         {
+            java.util.ArrayList<ItemStack> items = new java.util.ArrayList<ItemStack>();
             ItemStack itemstack = this.func_180643_i(p_180657_4_);
 
             if (itemstack != null)
             {
-                func_180635_a(p_180657_1_, p_180657_3_, itemstack);
+                items.add(itemstack);
             }
+
+            net.minecraftforge.event.ForgeEventFactory.fireBlockHarvesting(items, p_180657_1_, p_180657_3_, p_180657_1_.func_180495_p(p_180657_3_), 0, 1.0f, true, p_180657_2_);
+            for (ItemStack stack : items)
+            {
+                func_180635_a(p_180657_1_, p_180657_3_, stack);
+            }
         }
         else
         {
+            harvesters.set(p_180657_2_);
             int i = EnchantmentHelper.func_77517_e(p_180657_2_);
             this.func_176226_b(p_180657_1_, p_180657_3_, p_180657_4_, i);
+            harvesters.set(null);
         }
     }
 
+    @Deprecated //Forge: State sensitive version
     protected boolean func_149700_E()
     {
-        return this.func_149686_d() && !this.field_149758_A;
+        return this.func_149686_d() && !this.hasTileEntity(silk_check_state.get());
     }
 
     protected ItemStack func_180643_i(IBlockState p_180643_1_)
@@ -971,6 +989,1011 @@
         return Block.EnumOffsetType.NONE;
     }
 
+    /* ======================================== FORGE START =====================================*/
+    //For ForgeInternal use Only!
+    protected ThreadLocal<EntityPlayer> harvesters = new ThreadLocal();
+    private ThreadLocal<IBlockState> silk_check_state = new ThreadLocal();
+    protected static java.util.Random RANDOM = new java.util.Random(); // Useful for random things without a seed.
+    /**
+     * Get a light value for the block at the specified coordinates, normal ranges are between 0 and 15
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return The light value
+     */
+    public int getLightValue(IBlockAccess world, BlockPos pos)
+    {
+        Block block = world.func_180495_p(pos).func_177230_c();
+        if (block != this)
+        {
+            return block.getLightValue(world, pos);
+        }
+        return func_149750_m();
+    }
+
+    /**
+     * Checks if a player or entity can use this block to 'climb' like a ladder.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param entity The entity trying to use the ladder, CAN be null.
+     * @return True if the block should act like a ladder
+     */
+    public boolean isLadder(IBlockAccess world, BlockPos pos, EntityLivingBase entity) { return false; }
+
+    /**
+     * Return true if the block is a normal, solid cube.  This
+     * determines indirect power state, entity ejection from blocks, and a few
+     * others.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return True if the block is a full cube
+     */
+    public boolean isNormalCube(IBlockAccess world, BlockPos pos)
+    {
+        return func_149688_o().func_76218_k() && func_149686_d() && !func_149744_f();
+    }
+
+    /**
+     * Checks if the block is a solid face on the given side, used by placement logic.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param side The side to check
+     * @return True if the block is solid on the specified side.
+     */
+    public boolean isSideSolid(IBlockAccess world, BlockPos pos, EnumFacing side)
+    {
+        IBlockState state = this.func_176221_a(world.func_180495_p(pos), world, pos);
+
+        if (this instanceof BlockSlab)
+        {
+            return func_149730_j() || (state.func_177229_b(BlockSlab.field_176554_a) == BlockSlab.EnumBlockHalf.TOP && side == EnumFacing.UP);
+        }
+        else if (this instanceof BlockFarmland)
+        {
+            return (side != EnumFacing.DOWN && side != EnumFacing.UP);
+        }
+        else if (this instanceof BlockStairs)
+        {
+            boolean flipped = state.func_177229_b(BlockStairs.field_176308_b) == BlockStairs.EnumHalf.TOP;
+            BlockStairs.EnumShape shape = (BlockStairs.EnumShape)state.func_177229_b(BlockStairs.field_176310_M);
+            EnumFacing facing = (EnumFacing)state.func_177229_b(BlockStairs.field_176309_a);
+            if (side == EnumFacing.UP) return flipped;
+            if (facing == side) return true;
+            if (flipped)
+            {
+                if (shape == BlockStairs.EnumShape.INNER_LEFT ) return side == facing.func_176735_f();
+                if (shape == BlockStairs.EnumShape.INNER_RIGHT) return side == facing.func_176746_e();
+            }
+            else
+            {
+                if (shape == BlockStairs.EnumShape.INNER_LEFT ) return side == facing.func_176746_e();
+                if (shape == BlockStairs.EnumShape.INNER_RIGHT) return side == facing.func_176735_f();
+            }
+            return false;
+        }
+        else if (this instanceof BlockSnow)
+        {
+            return ((Integer)state.func_177229_b(BlockSnow.field_176315_a)) >= 8;
+        }
+        else if (this instanceof BlockHopper && side == EnumFacing.UP)
+        {
+            return true;
+        }
+        else if (this instanceof BlockCompressedPowered)
+        {
+            return true;
+        }
+        return isNormalCube(world, pos);
+    }
+
+    /**
+     * Determines if this block should set fire and deal fire damage
+     * to entities coming into contact with it.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return True if the block should deal damage
+     */
+    public boolean isBurning(IBlockAccess world, BlockPos pos)
+    {
+        return false;
+    }
+
+    /**
+     * Determines this block should be treated as an air block
+     * by the rest of the code. This method is primarily
+     * useful for creating pure logic-blocks that will be invisible
+     * to the player and otherwise interact as air would.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return True if the block considered air
+     */
+    public boolean isAir(IBlockAccess world, BlockPos pos)
+    {
+        return func_149688_o() == Material.field_151579_a;
+    }
+
+    /**
+     * Determines if the player can harvest this block, obtaining it's drops when the block is destroyed.
+     *
+     * @param player The player damaging the block, may be null
+     * @param meta The block's current metadata
+     * @return True to spawn the drops
+     */
+    public boolean canHarvestBlock(IBlockAccess world, BlockPos pos, EntityPlayer player)
+    {
+        return net.minecraftforge.common.ForgeHooks.canHarvestBlock(this, player, world, pos);
+    }
+
+    /**
+     * Called when a player removes a block.  This is responsible for
+     * actually destroying the block, and the block is intact at time of call.
+     * This is called regardless of whether the player can harvest the block or
+     * not.
+     *
+     * Return true if the block is actually destroyed.
+     *
+     * Note: When used in multiplayer, this is called on both client and
+     * server sides!
+     *
+     * @param world The current world
+     * @param player The player damaging the block, may be null
+     * @param pos Block position in world
+     * @param willHarvest True if Block.harvestBlock will be called after this, if the return in true.
+     *        Can be useful to delay the destruction of tile entities till after harvestBlock
+     * @return True if the block is actually destroyed.
+     */
+    public boolean removedByPlayer(World world, BlockPos pos, EntityPlayer player, boolean willHarvest)
+    {
+        return world.func_175698_g(pos);
+    }
+
+    /**
+     * Chance that fire will spread and consume this block.
+     * 300 being a 100% chance, 0, being a 0% chance.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param face The face that the fire is coming from
+     * @return A number ranging from 0 to 300 relating used to determine if the block will be consumed by fire
+     */
+    public int getFlammability(IBlockAccess world, BlockPos pos, EnumFacing face)
+    {
+        return net.minecraft.init.Blocks.field_150480_ab.func_176532_c(this);
+    }
+
+    /**
+     * Called when fire is updating, checks if a block face can catch fire.
+     *
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param face The face that the fire is coming from
+     * @return True if the face can be on fire, false otherwise.
+     */
+    public boolean isFlammable(IBlockAccess world, BlockPos pos, EnumFacing face)
+    {
+        return getFlammability(world, pos, face) > 0;
+    }
+
+    /**
+     * Called when fire is updating on a neighbor block.
+     * The higher the number returned, the faster fire will spread around this block.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param face The face that the fire is coming from
+     * @return A number that is used to determine the speed of fire growth around the block
+     */
+    public int getFireSpreadSpeed(IBlockAccess world, BlockPos pos, EnumFacing face)
+    {
+        return net.minecraft.init.Blocks.field_150480_ab.func_176534_d(this);
+    }
+
+    /**
+     * Currently only called by fire when it is on top of this block.
+     * Returning true will prevent the fire from naturally dying during updating.
+     * Also prevents firing from dying from rain.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param metadata The blocks current metadata
+     * @param side The face that the fire is coming from
+     * @return True if this block sustains fire, meaning it will never go out.
+     */
+    public boolean isFireSource(World world, BlockPos pos, EnumFacing side)
+    {
+        if (this == net.minecraft.init.Blocks.field_150424_aL && side == EnumFacing.UP)
+        {
+            return true;
+        }
+        if ((world.field_73011_w instanceof net.minecraft.world.WorldProviderEnd) && this == net.minecraft.init.Blocks.field_150357_h && side == EnumFacing.UP)
+        {
+            return true;
+        }
+        return false;
+    }
+
+    private boolean isTileProvider = this instanceof ITileEntityProvider;
+    /**
+     * Called throughout the code as a replacement for block instanceof BlockContainer
+     * Moving this to the Block base class allows for mods that wish to extend vanilla
+     * blocks, and also want to have a tile entity on that block, may.
+     *
+     * Return true from this function to specify this block has a tile entity.
+     *
+     * @param state State of the current block
+     * @return True if block has a tile entity, false otherwise
+     */
+    public boolean hasTileEntity(IBlockState state)
+    {
+        return isTileProvider;
+    }
+
+    /**
+     * Called throughout the code as a replacement for ITileEntityProvider.createNewTileEntity
+     * Return the same thing you would from that function.
+     * This will fall back to ITileEntityProvider.createNewTileEntity(World) if this block is a ITileEntityProvider
+     *
+     * @param metadata The Metadata of the current block
+     * @return A instance of a class extending TileEntity
+     */
+    public TileEntity createTileEntity(World world, IBlockState state)
+    {
+        if (isTileProvider)
+        {
+            return ((ITileEntityProvider)this).func_149915_a(world, func_176201_c(state));
+        }
+        return null;
+    }
+
+    /**
+     * State and fortune sensitive version, this replaces the old (int meta, Random rand)
+     * version in 1.1.
+     *
+     * @param state Current state
+     * @param fortune Current item fortune level
+     * @param random Random number generator
+     * @return The number of items to drop
+     */
+    public int quantityDropped(IBlockState state, int fortune, Random random)
+    {
+        return func_149679_a(fortune, random);
+    }
+
+    /**
+     * This returns a complete list of items dropped from this block.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param state Current state
+     * @param fortune Breakers fortune level
+     * @return A ArrayList containing all items this block drops
+     */
+    public List<ItemStack> getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune)
+    {
+        List<ItemStack> ret = new java.util.ArrayList<ItemStack>();
+
+        Random rand = world instanceof World ? ((World)world).field_73012_v : new Random();
+
+        int count = quantityDropped(state, fortune, rand);
+        for(int i = 0; i < count; i++)
+        {
+            Item item = this.func_180660_a(state, rand, fortune);
+            if (item != null)
+            {
+                ret.add(new ItemStack(item, 1, this.func_180651_a(state)));
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Return true from this function if the player with silk touch can harvest this block directly, and not it's normal drops.
+     *
+     * @param world The world
+     * @param pos Block position in world
+     * @param state current block state
+     * @param player The player doing the harvesting
+     * @return True if the block can be directly harvested using silk touch
+     */
+    public boolean canSilkHarvest(World world, BlockPos pos, IBlockState state, EntityPlayer player)
+    {
+        silk_check_state.set(state);;
+        boolean ret = this.func_149700_E();
+        silk_check_state.set(null);
+        return ret;
+    }
+
+    /**
+     * Determines if a specified mob type can spawn on this block, returning false will
+     * prevent any mob from spawning on the block.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param type The Mob Category Type
+     * @return True to allow a mob of the specified category to spawn, false to prevent it.
+     */
+    public boolean canCreatureSpawn(IBlockAccess world, BlockPos pos, net.minecraft.entity.EntityLiving.SpawnPlacementType type)
+    {
+        IBlockState state = world.func_180495_p(pos);
+        if (this instanceof BlockSlab)
+        {
+            return (func_149730_j() || state.func_177229_b(BlockSlab.field_176554_a) == BlockSlab.EnumBlockHalf.TOP);
+        }
+        else if (this instanceof BlockStairs)
+        {
+            return state.func_177229_b(BlockStairs.field_176308_b) == BlockStairs.EnumHalf.TOP;
+        }
+        return isSideSolid(world, pos, EnumFacing.UP);
+    }
+
+    /**
+     * Determines if this block is classified as a Bed, Allowing
+     * players to sleep in it, though the block has to specifically
+     * perform the sleeping functionality in it's activated event.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param player The player or camera entity, null in some cases.
+     * @return True to treat this as a bed
+     */
+    public boolean isBed(IBlockAccess world, BlockPos pos, Entity player)
+    {
+        return this == net.minecraft.init.Blocks.field_150324_C;
+    }
+
+    /**
+     * Returns the position that the player is moved to upon
+     * waking up, or respawning at the bed.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param player The player or camera entity, null in some cases.
+     * @return The spawn position
+     */
+    public BlockPos getBedSpawnPosition(IBlockAccess world, BlockPos pos, EntityPlayer player)
+    {
+        if (world instanceof World)
+            return BlockBed.func_176468_a((World)world, pos, 0);
+        return null;
+    }
+
+    /**
+     * Called when a user either starts or stops sleeping in the bed.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param player The player or camera entity, null in some cases.
+     * @param occupied True if we are occupying the bed, or false if they are stopping use of the bed
+     */
+    public void setBedOccupied(IBlockAccess world, BlockPos pos, EntityPlayer player, boolean occupied)
+    {
+        if (world instanceof World)
+        {
+            IBlockState state = world.func_180495_p(pos);
+            state = state.func_177230_c().func_176221_a(state, world, pos);
+            state = state.func_177226_a(BlockBed.field_176471_b, true);
+            ((World)world).func_180501_a(pos, state, 4);
+        }
+    }
+
+    /**
+     * Returns the direction of the block. Same values that
+     * are returned by BlockDirectional
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return Bed direction
+     */
+    public EnumFacing getBedDirection(IBlockAccess world, BlockPos pos)
+    {
+        return (EnumFacing)func_176221_a(world.func_180495_p(pos), world, pos).func_177229_b(BlockDirectional.field_176387_N);
+    }
+
+    /**
+     * Determines if the current block is the foot half of the bed.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return True if the current block is the foot side of a bed.
+     */
+    public boolean isBedFoot(IBlockAccess world, BlockPos pos)
+    {
+        return func_176221_a(world.func_180495_p(pos), world, pos).func_177229_b(BlockBed.field_176472_a) == BlockBed.EnumPartType.FOOT;
+    }
+
+    /**
+     * Called when a leaf should start its decay process.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     */
+    public void beginLeavesDecay(World world, BlockPos pos){}
+
+    /**
+     * Determines if this block can prevent leaves connected to it from decaying.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return true if the presence this block can prevent leaves from decaying.
+     */
+    public boolean canSustainLeaves(IBlockAccess world, BlockPos pos)
+    {
+        return false;
+    }
+
+    /**
+     * Determines if this block is considered a leaf block, used to apply the leaf decay and generation system.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return true if this block is considered leaves.
+     */
+    public boolean isLeaves(IBlockAccess world, BlockPos pos)
+    {
+        return func_149688_o() == Material.field_151584_j;
+    }
+
+    /**
+     * Used during tree growth to determine if newly generated leaves can replace this block.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return true if this block can be replaced by growing leaves.
+     */
+    public boolean canBeReplacedByLeaves(IBlockAccess world, BlockPos pos)
+    {
+        return !func_149730_j();
+    }
+
+    /**
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return  true if the block is wood (logs)
+     */
+    public boolean isWood(IBlockAccess world, BlockPos pos)
+    {
+        return false;
+    }
+
+    /**
+     * Determines if the current block is replaceable by Ore veins during world generation.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param target The generic target block the gen is looking for, Standards define stone
+     *      for overworld generation, and neatherack for the nether.
+     * @return True to allow this block to be replaced by a ore
+     */
+    public boolean isReplaceableOreGen(World world, BlockPos pos, com.google.common.base.Predicate<IBlockState> target)
+    {
+        return target.apply(world.func_180495_p(pos));
+    }
+
+    /**
+     * Location sensitive version of getExplosionRestance
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param exploder The entity that caused the explosion, can be null
+     * @param explosion The explosion
+     * @return The amount of the explosion absorbed.
+     */
+    public float getExplosionResistance(World world, BlockPos pos, Entity exploder, Explosion explosion)
+    {
+        return func_149638_a(exploder);
+    }
+
+    /**
+     * Called when the block is destroyed by an explosion.
+     * Useful for allowing the block to take into account tile entities,
+     * state, etc. when exploded, before it is removed.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param Explosion The explosion instance affecting the block
+     */
+    public void onBlockExploded(World world, BlockPos pos, Explosion explosion)
+    {
+        world.func_175698_g(pos);
+        func_180652_a(world, pos, explosion);
+    }
+
+    /**
+     * Determine if this block can make a redstone connection on the side provided,
+     * Useful to control which sides are inputs and outputs for redstone wires.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param side The side that is trying to make the connection, CAN BE NULL
+     * @return True to make the connection
+     */
+    public boolean canConnectRedstone(IBlockAccess world, BlockPos pos, EnumFacing side)
+    {
+        return func_149744_f() && side != null;
+    }
+
+    /**
+     * Determines if a torch can be placed on the top surface of this block.
+     * Useful for creating your own block that torches can be on, such as fences.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return True to allow the torch to be placed
+     */
+    public boolean canPlaceTorchOnTop(IBlockAccess world, BlockPos pos)
+    {
+        if (isSideSolid(world, pos, EnumFacing.UP))
+        {
+            return true;
+        }
+        else
+        {
+            return this instanceof BlockFence || this == net.minecraft.init.Blocks.field_150359_w || this == net.minecraft.init.Blocks.field_150463_bK || this == net.minecraft.init.Blocks.field_150399_cn;
+        }
+    }
+
+    /** Dont think this exists in 1.8 anymore
+    /**
+     * Determines if this block should render in this pass.
+     *
+     * @param pass The pass in question
+     * @return True to render
+     * /
+    public boolean canRenderInPass(int pass)
+    {
+        return pass == func_149701_w();
+    }
+    */
+
+    /**
+     * Called when a user uses the creative pick block button on this block
+     *
+     * @param target The full target the player is looking at
+     * @return A ItemStack to add to the player's inventory, Null if nothing should be added.
+     */
+    public ItemStack getPickBlock(MovingObjectPosition target, World world, BlockPos pos)
+    {
+        Item item = func_180665_b(world, pos);
+
+        if (item == null)
+        {
+            return null;
+        }
+
+        Block block = item instanceof ItemBlock && !func_149648_K() ? Block.func_149634_a(item) : this;
+        return new ItemStack(item, 1, block.func_176222_j(world, pos));
+    }
+
+    /**
+     * Used by getTopSolidOrLiquidBlock while placing biome decorations, villages, etc
+     * Also used to determine if the player can spawn on this block.
+     *
+     * @return False to disallow spawning
+     */
+    public boolean isFoliage(IBlockAccess world, BlockPos pos)
+    {
+        return false;
+    }
+
+    /**
+     * Spawn a digging particle effect in the world, this is a wrapper
+     * around EffectRenderer.addBlockHitEffects to allow the block more
+     * control over the particles. Useful when you have entirely different
+     * texture sheets for different sides/locations in the world.
+     *
+     * @param world The current world
+     * @param target The target the player is looking at {x/y/z/side/sub}
+     * @param effectRenderer A reference to the current effect renderer.
+     * @return True to prevent vanilla digging particles form spawning.
+     */
+    @SideOnly(Side.CLIENT)
+    public boolean addHitEffects(World worldObj, MovingObjectPosition target, net.minecraft.client.particle.EffectRenderer effectRenderer)
+    {
+        return false;
+    }
+
+    /**
+     * Spawn particles for when the block is destroyed. Due to the nature
+     * of how this is invoked, the x/y/z locations are not always guaranteed
+     * to host your block. So be sure to do proper sanity checks before assuming
+     * that the location is this block.
+     *
+     * @param world The current world
+     * @param pos Position to spawn the particle
+     * @param effectRenderer A reference to the current effect renderer.
+     * @return True to prevent vanilla break particles from spawning.
+     */
+    @SideOnly(Side.CLIENT)
+    public boolean addDestroyEffects(World world, BlockPos pos, net.minecraft.client.particle.EffectRenderer effectRenderer)
+    {
+        return false;
+    }
+
+    /**
+     * Determines if this block can support the passed in plant, allowing it to be planted and grow.
+     * Some examples:
+     *   Reeds check if its a reed, or if its sand/dirt/grass and adjacent to water
+     *   Cacti checks if its a cacti, or if its sand
+     *   Nether types check for soul sand
+     *   Crops check for tilled soil
+     *   Caves check if it's a solid surface
+     *   Plains check if its grass or dirt
+     *   Water check if its still water
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param direction The direction relative to the given position the plant wants to be, typically its UP
+     * @param plantable The plant that wants to check
+     * @return True to allow the plant to be planted/stay.
+     */
+    public boolean canSustainPlant(IBlockAccess world, BlockPos pos, EnumFacing direction, net.minecraftforge.common.IPlantable plantable)
+    {
+        IBlockState state = world.func_180495_p(pos);
+        IBlockState plant = plantable.getPlant(world, pos.func_177984_a());
+        net.minecraftforge.common.EnumPlantType plantType = plantable.getPlantType(world, pos.func_177984_a());
+
+        if (plant.func_177230_c() == net.minecraft.init.Blocks.field_150434_aF && this == net.minecraft.init.Blocks.field_150434_aF)
+        {
+            return true;
+        }
+
+        if (plant.func_177230_c() == net.minecraft.init.Blocks.field_150436_aH && this == net.minecraft.init.Blocks.field_150436_aH)
+        {
+            return true;
+        }
+
+        if (plantable instanceof BlockBush && ((BlockBush)plantable).func_149854_a(this))
+        {
+            return true;
+        }
+
+        switch (plantType)
+        {
+            case Desert: return this == net.minecraft.init.Blocks.field_150354_m || this == net.minecraft.init.Blocks.field_150405_ch || this == net.minecraft.init.Blocks.field_150406_ce || this == net.minecraft.init.Blocks.field_150346_d;
+            case Nether: return this == net.minecraft.init.Blocks.field_150425_aM;
+            case Crop:   return this == net.minecraft.init.Blocks.field_150458_ak;
+            case Cave:   return isSideSolid(world, pos, EnumFacing.UP);
+            case Plains: return this == net.minecraft.init.Blocks.field_150349_c || this == net.minecraft.init.Blocks.field_150346_d || this == net.minecraft.init.Blocks.field_150458_ak;
+            case Water:  return func_149688_o() == Material.field_151586_h && ((Integer)state.func_177229_b(BlockLiquid.field_176367_b)) == 0;
+            case Beach:
+                boolean isBeach = this == net.minecraft.init.Blocks.field_150349_c || this == net.minecraft.init.Blocks.field_150346_d || this == net.minecraft.init.Blocks.field_150354_m;
+                boolean hasWater = (world.func_180495_p(pos.func_177974_f()).func_177230_c().func_149688_o() == Material.field_151586_h ||
+                                    world.func_180495_p(pos.func_177976_e()).func_177230_c().func_149688_o() == Material.field_151586_h ||
+                                    world.func_180495_p(pos.func_177978_c()).func_177230_c().func_149688_o() == Material.field_151586_h ||
+                                    world.func_180495_p(pos.func_177968_d()).func_177230_c().func_149688_o() == Material.field_151586_h);
+                return isBeach && hasWater;
+        }
+
+        return false;
+    }
+
+    /**
+     * Called when a plant grows on this block, only implemented for saplings using the WorldGen*Trees classes right now.
+     * Modder may implement this for custom plants.
+     * This does not use ForgeDirection, because large/huge trees can be located in non-representable direction,
+     * so the source location is specified.
+     * Currently this just changes the block to dirt if it was grass.
+     *
+     * Note: This happens DURING the generation, the generation may not be complete when this is called.
+     *
+     * @param world Current world
+     * @param pos Block position in world
+     * @param source Source plant's position in world
+     */
+    public void onPlantGrow(World world, BlockPos pos, BlockPos source)
+    {
+        if (this == net.minecraft.init.Blocks.field_150349_c || this == net.minecraft.init.Blocks.field_150458_ak)
+        {
+            world.func_180501_a(pos, net.minecraft.init.Blocks.field_150346_d.func_176223_P(), 2);
+        }
+    }
+
+    /**
+     * Checks if this soil is fertile, typically this means that growth rates
+     * of plants on this soil will be slightly sped up.
+     * Only vanilla case is tilledField when it is within range of water.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return True if the soil should be considered fertile.
+     */
+    public boolean isFertile(World world, BlockPos pos)
+    {
+        if (this == net.minecraft.init.Blocks.field_150458_ak)
+        {
+            return ((Integer)world.func_180495_p(pos).func_177229_b(BlockFarmland.field_176531_a)) > 0;
+        }
+
+        return false;
+    }
+
+    /**
+     * Location aware and overrideable version of the lightOpacity array,
+     * return the number to subtract from the light value when it passes through this block.
+     *
+     * This is not guaranteed to have the tile entity in place before this is called, so it is
+     * Recommended that you have your tile entity call relight after being placed if you
+     * rely on it for light info.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return The amount of light to block, 0 for air, 255 for fully opaque.
+     */
+    public int getLightOpacity(IBlockAccess world, BlockPos pos)
+    {
+        return func_149717_k();
+    }
+
+    /**
+     * Determines if this block is can be destroyed by the specified entities normal behavior.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @return True to allow the ender dragon to destroy this block
+     */
+    public boolean canEntityDestroy(IBlockAccess world, BlockPos pos, Entity entity)
+    {
+        if (entity instanceof net.minecraft.entity.boss.EntityWither)
+        {
+            return this != net.minecraft.init.Blocks.field_180401_cv && this != net.minecraft.init.Blocks.field_150357_h && this != net.minecraft.init.Blocks.field_150384_bq && this != net.minecraft.init.Blocks.field_150378_br && this != net.minecraft.init.Blocks.field_150483_bI;
+        }
+        else if (entity instanceof net.minecraft.entity.boss.EntityDragon)
+        {
+            return this != net.minecraft.init.Blocks.field_180401_cv && this != net.minecraft.init.Blocks.field_150343_Z && this != net.minecraft.init.Blocks.field_150377_bs && this != net.minecraft.init.Blocks.field_150357_h && this != net.minecraft.init.Blocks.field_150483_bI;
+        }
+
+        return true;
+    }
+
+    /**
+     * Determines if this block can be used as the base of a beacon.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param beacon Beacon position in world
+     * @return True, to support the beacon, and make it active with this block.
+     */
+    public boolean isBeaconBase(IBlockAccess worldObj, BlockPos pos, BlockPos beacon)
+    {
+        return this == net.minecraft.init.Blocks.field_150475_bE || this == net.minecraft.init.Blocks.field_150340_R || this == net.minecraft.init.Blocks.field_150484_ah || this == net.minecraft.init.Blocks.field_150339_S;
+    }
+
+    /**
+     * Rotate the block. For vanilla blocks this rotates around the axis passed in (generally, it should be the "face" that was hit).
+     * Note: for mod blocks, this is up to the block and modder to decide. It is not mandated that it be a rotation around the
+     * face, but could be a rotation to orient *to* that face, or a visiting of possible rotations.
+     * The method should return true if the rotation was successful though.
+     *
+     * @param world The world
+     * @param pos Block position in world
+     * @param axis The axis to rotate around
+     * @return True if the rotation was successful, False if the rotation failed, or is not possible
+     */
+    public boolean rotateBlock(World world, BlockPos pos, EnumFacing axis)
+    {
+        IBlockState state = world.func_180495_p(pos);
+        for (IProperty prop : (java.util.Set<IProperty>)state.func_177228_b().keySet())
+        {
+            if (prop.func_177701_a().equals("facing"))
+            {
+                world.func_175656_a(pos, state.func_177231_a(prop));
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Get the rotations that can apply to the block at the specified coordinates. Null means no rotations are possible.
+     * Note, this is up to the block to decide. It may not be accurate or representative.
+     * @param world The world
+     * @param pos Block position in world
+     * @return An array of valid axes to rotate around, or null for none or unknown
+     */
+    public EnumFacing[] getValidRotations(World world, BlockPos pos)
+    {
+        IBlockState state = world.func_180495_p(pos);
+        for (IProperty prop : (java.util.Set<IProperty>)state.func_177228_b().keySet())
+        {
+            if (prop.func_177701_a().equals("facing") && prop.func_177699_b() == EnumFacing.class)
+            {
+                java.util.Collection<EnumFacing> values = ((java.util.Collection<EnumFacing>)prop.func_177700_c());
+                return values.toArray(new EnumFacing[values.size()]);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Determines the amount of enchanting power this block can provide to an enchanting table.
+     * @param world The World
+     * @param pos Block position in world
+     * @return The amount of enchanting power this block produces.
+     */
+    public float getEnchantPowerBonus(World world, BlockPos pos)
+    {
+        return this == net.minecraft.init.Blocks.field_150342_X ? 1 : 0;
+    }
+
+    /**
+     * Common way to recolor a block with an external tool
+     * @param world The world
+     * @param pos Block position in world
+     * @param side The side hit with the coloring tool
+     * @param color The color to change to
+     * @return If the recoloring was successful
+     */
+    public boolean recolorBlock(World world, BlockPos pos, EnumFacing side, net.minecraft.item.EnumDyeColor color)
+    {
+        IBlockState state = world.func_180495_p(pos);
+        for (IProperty prop : (java.util.Set<IProperty>)state.func_177228_b().keySet())
+        {
+            if (prop.func_177701_a().equals("color") && prop.func_177699_b() == net.minecraft.item.EnumDyeColor.class)
+            {
+                net.minecraft.item.EnumDyeColor current = (net.minecraft.item.EnumDyeColor)state.func_177229_b(prop);
+                if (current != color)
+                {
+                    world.func_175656_a(pos, state.func_177226_a(prop, color));
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Gathers how much experience this block drops when broken.
+     *
+     * @param world The world
+     * @param pos Block position
+     * @param fortune
+     * @return Amount of XP from breaking this block.
+     */
+    public int getExpDrop(IBlockAccess world, BlockPos pos, int fortune)
+    {
+        return 0;
+    }
+
+    /**
+     * Called when a tile entity on a side of this block changes is created or is destroyed.
+     * @param world The world
+     * @param pos Block position in world
+     * @param neighbor Block position of neighbor
+     */
+    public void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor){}
+
+    /**
+     * Called to determine whether to allow the a block to handle its own indirect power rather than using the default rules.
+     * @param world The world
+     * @param pos Block position in world
+     * @param side The INPUT side of the block to be powered - ie the opposite of this block's output side
+     * @return Whether Block#isProvidingWeakPower should be called when determining indirect power
+     */
+    public boolean shouldCheckWeakPower(IBlockAccess world, BlockPos pos, EnumFacing side)
+    {
+        return func_149721_r();
+    }
+
+    /**
+     * If this block should be notified of weak changes.
+     * Weak changes are changes 1 block away through a solid block.
+     * Similar to comparators.
+     *
+     * @param world The current world
+     * @param pos Block position in world
+     * @param side The side to check
+     * @return true To be notified of changes
+     */
+    public boolean getWeakChanges(IBlockAccess world, BlockPos pos)
+    {
+        return false;
+    }
+
+    private String[] harvestTool = new String[16];;
+    private int[] harvestLevel = new int[]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
+    /**
+     * Sets or removes the tool and level required to harvest this block.
+     *
+     * @param toolClass Class
+     * @param level Harvest level:
+     *     Wood:    0
+     *     Stone:   1
+     *     Iron:    2
+     *     Diamond: 3
+     *     Gold:    0
+     */
+    public void setHarvestLevel(String toolClass, int level)
+    {
+        Iterator<IBlockState> itr = func_176194_O().func_177619_a().iterator();
+        while (itr.hasNext())
+        {
+            setHarvestLevel(toolClass, level, itr.next());
+        }
+    }
+
+    /**
+     * Sets or removes the tool and level required to harvest this block.
+     *
+     * @param toolClass Class
+     * @param level Harvest level:
+     *     Wood:    0
+     *     Stone:   1
+     *     Iron:    2
+     *     Diamond: 3
+     *     Gold:    0
+     * @param state The specific state.
+     */
+    public void setHarvestLevel(String toolClass, int level, IBlockState state)
+    {
+        int idx = this.func_176201_c(state);
+        this.harvestTool[idx] = toolClass;
+        this.harvestLevel[idx] = level;
+    }
+
+    /**
+     * Queries the class of tool required to harvest this block, if null is returned
+     * we assume that anything can harvest this block.
+     */
+    public String getHarvestTool(IBlockState state)
+    {
+        return harvestTool[func_176201_c(state)];
+    }
+
+    /**
+     * Queries the harvest level of this item stack for the specified tool class,
+     * Returns -1 if this tool is not of the specified type
+     *
+     * @param stack This item stack instance
+     * @return Harvest level, or -1 if not the specified tool type.
+     */
+    public int getHarvestLevel(IBlockState state)
+    {
+        return harvestLevel[func_176201_c(state)];
+    }
+
+    /**
+     * Checks if the specified tool type is efficient on this block,
+     * meaning that it digs at full speed.
+     */
+    public boolean isToolEffective(String type, IBlockState state)
+    {
+        if ("pickaxe".equals(type) && (this == net.minecraft.init.Blocks.field_150450_ax || this == net.minecraft.init.Blocks.field_150439_ay || this == net.minecraft.init.Blocks.field_150343_Z))
+            return false;
+        return type != null && getHarvestTool(state).equals(type);
+    }
+
+    // For Internal use only to capture droped items inside getDrops
+    protected static ThreadLocal<Boolean> captureDrops = new ThreadLocal<Boolean>()
+    {
+        @Override protected Boolean initialValue() { return false; }
+    };
+    protected static ThreadLocal<List<ItemStack>> capturedDrops = new ThreadLocal<List<ItemStack>>()
+    {
+        @Override protected List<ItemStack> initialValue() { return new java.util.ArrayList<ItemStack>(); }
+    };
+    protected List<ItemStack> captureDrops(boolean start)
+    {
+        if (start)
+        {
+            captureDrops.set(true);
+            capturedDrops.get().clear();
+            return null;
+        }
+        else
+        {
+            captureDrops.set(false);
+            return capturedDrops.get();
+        }
+    }
+    /* ========================================= FORGE END ======================================*/
+
     public static void func_149671_p()
     {
         func_176215_a(0, field_176230_a, (new BlockAir()).func_149663_c("air"));
