package net.minecraft.block;

import cpw.mods.fml.common.registry.GameData;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import net.minecraft.block.material.MapColor;
import net.minecraft.block.material.Material;
import net.minecraft.client.particle.EffectRenderer;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.entity.boss.EntityDragon;
import net.minecraft.entity.boss.EntityWither;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.stats.StatList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntitySign;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.IIcon;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.RegistryNamespaced;
import net.minecraft.util.RegistryNamespacedDefaultedByKey;
import net.minecraft.util.StatCollector;
import net.minecraft.util.Vec3;
import net.minecraft.world.Explosion;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraft.world.WorldProviderEnd;
import net.minecraftforge.common.EnumPlantType;
import net.minecraftforge.common.ForgeHooks;
import net.minecraftforge.common.IPlantable;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.common.util.RotationHelper;
import net.minecraftforge.event.ForgeEventFactory;
import static net.minecraftforge.common.util.ForgeDirection.*;

public class Block
{
	public static final RegistryNamespaced blockRegistry = GameData.getBlockRegistry();
	private CreativeTabs displayOnCreativeTab;
	protected String textureName;
	public static final Block.SoundType soundTypeStone = new Block.SoundType("stone", 1.0F, 1.0F);
	public static final Block.SoundType soundTypeWood = new Block.SoundType("wood", 1.0F, 1.0F);
	public static final Block.SoundType soundTypeGravel = new Block.SoundType("gravel", 1.0F, 1.0F);
	public static final Block.SoundType soundTypeGrass = new Block.SoundType("grass", 1.0F, 1.0F);
	public static final Block.SoundType soundTypePiston = new Block.SoundType("stone", 1.0F, 1.0F);
	public static final Block.SoundType soundTypeMetal = new Block.SoundType("stone", 1.0F, 1.5F);
	public static final Block.SoundType soundTypeGlass = new Block.SoundType("stone", 1.0F, 1.0F)
	{
		private static final String __OBFID = "CL_00000200";
		public String getBreakSound()
		{
			return "dig.glass";
		}
		public String func_150496_b()
		{
			return "step.stone";
		}
	};
	public static final Block.SoundType soundTypeCloth = new Block.SoundType("cloth", 1.0F, 1.0F);
	public static final Block.SoundType soundTypeSand = new Block.SoundType("sand", 1.0F, 1.0F);
	public static final Block.SoundType soundTypeSnow = new Block.SoundType("snow", 1.0F, 1.0F);
	public static final Block.SoundType soundTypeLadder = new Block.SoundType("ladder", 1.0F, 1.0F)
	{
		private static final String __OBFID = "CL_00000201";
		public String getBreakSound()
		{
			return "dig.wood";
		}
	};
	public static final Block.SoundType soundTypeAnvil = new Block.SoundType("anvil", 0.3F, 1.0F)
	{
		private static final String __OBFID = "CL_00000202";
		public String getBreakSound()
		{
			return "dig.stone";
		}
		public String func_150496_b()
		{
			return "random.anvil_land";
		}
	};
	protected boolean opaque;
	protected int lightOpacity;
	protected boolean canBlockGrass;
	protected int lightValue;
	protected boolean useNeighborBrightness;
	protected float blockHardness;
	protected float blockResistance;
	protected boolean blockConstructorCalled = true;
	protected boolean enableStats = true;
	protected boolean needsRandomTick;
	protected boolean isBlockContainer;
	protected double minX;
	protected double minY;
	protected double minZ;
	protected double maxX;
	protected double maxY;
	protected double maxZ;
	public Block.SoundType stepSound;
	public float blockParticleGravity;
	protected final Material blockMaterial;
	public float slipperiness;
	private String unlocalizedName;
	@SideOnly(Side.CLIENT)
	protected IIcon blockIcon;
	private static final String __OBFID = "CL_00000199";

	public static int getIdFromBlock(Block p_149682_0_)
	{
		return blockRegistry.getIDForObject(p_149682_0_);
	}

	public static Block getBlockById(int p_149729_0_)
	{
		Block ret = (Block)blockRegistry.getObjectById(p_149729_0_);
		return ret == null ? Blocks.air : ret;
	}

	public static Block getBlockFromItem(Item p_149634_0_)
	{
		return getBlockById(Item.getIdFromItem(p_149634_0_));
	}

	public static Block getBlockFromName(String p_149684_0_)
	{
		if (blockRegistry.containsKey(p_149684_0_))
		{
			return (Block)blockRegistry.getObject(p_149684_0_);
		}
		else
		{
			try
			{
				return (Block)blockRegistry.getObjectById(Integer.parseInt(p_149684_0_));
			}
			catch (NumberFormatException numberformatexception)
			{
				return null;
			}
		}
	}

	public boolean func_149730_j()
	{
		return this.opaque;
	}

	public int getLightOpacity()
	{
		return this.lightOpacity;
	}

	@SideOnly(Side.CLIENT)
	public boolean getCanBlockGrass()
	{
		return this.canBlockGrass;
	}

	public int getLightValue()
	{
		return this.lightValue;
	}

	public boolean getUseNeighborBrightness()
	{
		return this.useNeighborBrightness;
	}

	public Material getMaterial()
	{
		return this.blockMaterial;
	}

	public MapColor getMapColor(int p_149728_1_)
	{
		return this.getMaterial().getMaterialMapColor();
	}

	public static void registerBlocks()
	{
		blockRegistry.addObject(0, "air", (new BlockAir()).setBlockName("air"));
		blockRegistry.addObject(1, "stone", (new BlockStone()).setHardness(1.5F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("stone").setBlockTextureName("stone"));
		blockRegistry.addObject(2, "grass", (new BlockGrass()).setHardness(0.6F).setStepSound(soundTypeGrass).setBlockName("grass").setBlockTextureName("grass"));
		blockRegistry.addObject(3, "dirt", (new BlockDirt()).setHardness(0.5F).setStepSound(soundTypeGravel).setBlockName("dirt").setBlockTextureName("dirt"));
		Block block = (new Block(Material.rock)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("stonebrick").setCreativeTab(CreativeTabs.tabBlock).setBlockTextureName("cobblestone");
		blockRegistry.addObject(4, "cobblestone", block);
		Block block1 = (new BlockWood()).setHardness(2.0F).setResistance(5.0F).setStepSound(soundTypeWood).setBlockName("wood").setBlockTextureName("planks");
		blockRegistry.addObject(5, "planks", block1);
		blockRegistry.addObject(6, "sapling", (new BlockSapling()).setHardness(0.0F).setStepSound(soundTypeGrass).setBlockName("sapling").setBlockTextureName("sapling"));
		blockRegistry.addObject(7, "bedrock", (new Block(Material.rock)).setBlockUnbreakable().setResistance(6000000.0F).setStepSound(soundTypePiston).setBlockName("bedrock").disableStats().setCreativeTab(CreativeTabs.tabBlock).setBlockTextureName("bedrock"));
		blockRegistry.addObject(8, "flowing_water", (new BlockDynamicLiquid(Material.water)).setHardness(100.0F).setLightOpacity(3).setBlockName("water").disableStats().setBlockTextureName("water_flow"));
		blockRegistry.addObject(9, "water", (new BlockStaticLiquid(Material.water)).setHardness(100.0F).setLightOpacity(3).setBlockName("water").disableStats().setBlockTextureName("water_still"));
		blockRegistry.addObject(10, "flowing_lava", (new BlockDynamicLiquid(Material.lava)).setHardness(100.0F).setLightLevel(1.0F).setBlockName("lava").disableStats().setBlockTextureName("lava_flow"));
		blockRegistry.addObject(11, "lava", (new BlockStaticLiquid(Material.lava)).setHardness(100.0F).setLightLevel(1.0F).setBlockName("lava").disableStats().setBlockTextureName("lava_still"));
		blockRegistry.addObject(12, "sand", (new BlockSand()).setHardness(0.5F).setStepSound(soundTypeSand).setBlockName("sand").setBlockTextureName("sand"));
		blockRegistry.addObject(13, "gravel", (new BlockGravel()).setHardness(0.6F).setStepSound(soundTypeGravel).setBlockName("gravel").setBlockTextureName("gravel"));
		blockRegistry.addObject(14, "gold_ore", (new BlockOre()).setHardness(3.0F).setResistance(5.0F).setStepSound(soundTypePiston).setBlockName("oreGold").setBlockTextureName("gold_ore"));
		blockRegistry.addObject(15, "iron_ore", (new BlockOre()).setHardness(3.0F).setResistance(5.0F).setStepSound(soundTypePiston).setBlockName("oreIron").setBlockTextureName("iron_ore"));
		blockRegistry.addObject(16, "coal_ore", (new BlockOre()).setHardness(3.0F).setResistance(5.0F).setStepSound(soundTypePiston).setBlockName("oreCoal").setBlockTextureName("coal_ore"));
		blockRegistry.addObject(17, "log", (new BlockOldLog()).setBlockName("log").setBlockTextureName("log"));
		blockRegistry.addObject(18, "leaves", (new BlockOldLeaf()).setBlockName("leaves").setBlockTextureName("leaves"));
		blockRegistry.addObject(19, "sponge", (new BlockSponge()).setHardness(0.6F).setStepSound(soundTypeGrass).setBlockName("sponge").setBlockTextureName("sponge"));
		blockRegistry.addObject(20, "glass", (new BlockGlass(Material.glass, false)).setHardness(0.3F).setStepSound(soundTypeGlass).setBlockName("glass").setBlockTextureName("glass"));
		blockRegistry.addObject(21, "lapis_ore", (new BlockOre()).setHardness(3.0F).setResistance(5.0F).setStepSound(soundTypePiston).setBlockName("oreLapis").setBlockTextureName("lapis_ore"));
		blockRegistry.addObject(22, "lapis_block", (new BlockCompressed(MapColor.lapisColor)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundTypePiston).setBlockName("blockLapis").setCreativeTab(CreativeTabs.tabBlock).setBlockTextureName("lapis_block"));
		blockRegistry.addObject(23, "dispenser", (new BlockDispenser()).setHardness(3.5F).setStepSound(soundTypePiston).setBlockName("dispenser").setBlockTextureName("dispenser"));
		Block block2 = (new BlockSandStone()).setStepSound(soundTypePiston).setHardness(0.8F).setBlockName("sandStone").setBlockTextureName("sandstone");
		blockRegistry.addObject(24, "sandstone", block2);
		blockRegistry.addObject(25, "noteblock", (new BlockNote()).setHardness(0.8F).setBlockName("musicBlock").setBlockTextureName("noteblock"));
		blockRegistry.addObject(26, "bed", (new BlockBed()).setHardness(0.2F).setBlockName("bed").disableStats().setBlockTextureName("bed"));
		blockRegistry.addObject(27, "golden_rail", (new BlockRailPowered()).setHardness(0.7F).setStepSound(soundTypeMetal).setBlockName("goldenRail").setBlockTextureName("rail_golden"));
		blockRegistry.addObject(28, "detector_rail", (new BlockRailDetector()).setHardness(0.7F).setStepSound(soundTypeMetal).setBlockName("detectorRail").setBlockTextureName("rail_detector"));
		blockRegistry.addObject(29, "sticky_piston", (new BlockPistonBase(true)).setBlockName("pistonStickyBase"));
		blockRegistry.addObject(30, "web", (new BlockWeb()).setLightOpacity(1).setHardness(4.0F).setBlockName("web").setBlockTextureName("web"));
		blockRegistry.addObject(31, "tallgrass", (new BlockTallGrass()).setHardness(0.0F).setStepSound(soundTypeGrass).setBlockName("tallgrass"));
		blockRegistry.addObject(32, "deadbush", (new BlockDeadBush()).setHardness(0.0F).setStepSound(soundTypeGrass).setBlockName("deadbush").setBlockTextureName("deadbush"));
		blockRegistry.addObject(33, "piston", (new BlockPistonBase(false)).setBlockName("pistonBase"));
		blockRegistry.addObject(34, "piston_head", new BlockPistonExtension());
		blockRegistry.addObject(35, "wool", (new BlockColored(Material.cloth)).setHardness(0.8F).setStepSound(soundTypeCloth).setBlockName("cloth").setBlockTextureName("wool_colored"));
		blockRegistry.addObject(36, "piston_extension", new BlockPistonMoving());
		blockRegistry.addObject(37, "yellow_flower", (new BlockFlower(0)).setHardness(0.0F).setStepSound(soundTypeGrass).setBlockName("flower1").setBlockTextureName("flower_dandelion"));
		blockRegistry.addObject(38, "red_flower", (new BlockFlower(1)).setHardness(0.0F).setStepSound(soundTypeGrass).setBlockName("flower2").setBlockTextureName("flower_rose"));
		blockRegistry.addObject(39, "brown_mushroom", (new BlockMushroom()).setHardness(0.0F).setStepSound(soundTypeGrass).setLightLevel(0.125F).setBlockName("mushroom").setBlockTextureName("mushroom_brown"));
		blockRegistry.addObject(40, "red_mushroom", (new BlockMushroom()).setHardness(0.0F).setStepSound(soundTypeGrass).setBlockName("mushroom").setBlockTextureName("mushroom_red"));
		blockRegistry.addObject(41, "gold_block", (new BlockCompressed(MapColor.goldColor)).setHardness(3.0F).setResistance(10.0F).setStepSound(soundTypeMetal).setBlockName("blockGold").setBlockTextureName("gold_block"));
		blockRegistry.addObject(42, "iron_block", (new BlockCompressed(MapColor.ironColor)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundTypeMetal).setBlockName("blockIron").setBlockTextureName("iron_block"));
		blockRegistry.addObject(43, "double_stone_slab", (new BlockStoneSlab(true)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("stoneSlab"));
		blockRegistry.addObject(44, "stone_slab", (new BlockStoneSlab(false)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("stoneSlab"));
		Block block3 = (new Block(Material.rock)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("brick").setCreativeTab(CreativeTabs.tabBlock).setBlockTextureName("brick");
		blockRegistry.addObject(45, "brick_block", block3);
		blockRegistry.addObject(46, "tnt", (new BlockTNT()).setHardness(0.0F).setStepSound(soundTypeGrass).setBlockName("tnt").setBlockTextureName("tnt"));
		blockRegistry.addObject(47, "bookshelf", (new BlockBookshelf()).setHardness(1.5F).setStepSound(soundTypeWood).setBlockName("bookshelf").setBlockTextureName("bookshelf"));
		blockRegistry.addObject(48, "mossy_cobblestone", (new Block(Material.rock)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("stoneMoss").setCreativeTab(CreativeTabs.tabBlock).setBlockTextureName("cobblestone_mossy"));
		blockRegistry.addObject(49, "obsidian", (new BlockObsidian()).setHardness(50.0F).setResistance(2000.0F).setStepSound(soundTypePiston).setBlockName("obsidian").setBlockTextureName("obsidian"));
		blockRegistry.addObject(50, "torch", (new BlockTorch()).setHardness(0.0F).setLightLevel(0.9375F).setStepSound(soundTypeWood).setBlockName("torch").setBlockTextureName("torch_on"));
		blockRegistry.addObject(51, "fire", (new BlockFire()).setHardness(0.0F).setLightLevel(1.0F).setStepSound(soundTypeWood).setBlockName("fire").disableStats().setBlockTextureName("fire"));
		blockRegistry.addObject(52, "mob_spawner", (new BlockMobSpawner()).setHardness(5.0F).setStepSound(soundTypeMetal).setBlockName("mobSpawner").disableStats().setBlockTextureName("mob_spawner"));
		blockRegistry.addObject(53, "oak_stairs", (new BlockStairs(block1, 0)).setBlockName("stairsWood"));
		blockRegistry.addObject(54, "chest", (new BlockChest(0)).setHardness(2.5F).setStepSound(soundTypeWood).setBlockName("chest"));
		blockRegistry.addObject(55, "redstone_wire", (new BlockRedstoneWire()).setHardness(0.0F).setStepSound(soundTypeStone).setBlockName("redstoneDust").disableStats().setBlockTextureName("redstone_dust"));
		blockRegistry.addObject(56, "diamond_ore", (new BlockOre()).setHardness(3.0F).setResistance(5.0F).setStepSound(soundTypePiston).setBlockName("oreDiamond").setBlockTextureName("diamond_ore"));
		blockRegistry.addObject(57, "diamond_block", (new BlockCompressed(MapColor.diamondColor)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundTypeMetal).setBlockName("blockDiamond").setBlockTextureName("diamond_block"));
		blockRegistry.addObject(58, "crafting_table", (new BlockWorkbench()).setHardness(2.5F).setStepSound(soundTypeWood).setBlockName("workbench").setBlockTextureName("crafting_table"));
		blockRegistry.addObject(59, "wheat", (new BlockCrops()).setBlockName("crops").setBlockTextureName("wheat"));
		Block block4 = (new BlockFarmland()).setHardness(0.6F).setStepSound(soundTypeGravel).setBlockName("farmland").setBlockTextureName("farmland");
		blockRegistry.addObject(60, "farmland", block4);
		blockRegistry.addObject(61, "furnace", (new BlockFurnace(false)).setHardness(3.5F).setStepSound(soundTypePiston).setBlockName("furnace").setCreativeTab(CreativeTabs.tabDecorations));
		blockRegistry.addObject(62, "lit_furnace", (new BlockFurnace(true)).setHardness(3.5F).setStepSound(soundTypePiston).setLightLevel(0.875F).setBlockName("furnace"));
		blockRegistry.addObject(63, "standing_sign", (new BlockSign(TileEntitySign.class, true)).setHardness(1.0F).setStepSound(soundTypeWood).setBlockName("sign").disableStats());
		blockRegistry.addObject(64, "wooden_door", (new BlockDoor(Material.wood)).setHardness(3.0F).setStepSound(soundTypeWood).setBlockName("doorWood").disableStats().setBlockTextureName("door_wood"));
		blockRegistry.addObject(65, "ladder", (new BlockLadder()).setHardness(0.4F).setStepSound(soundTypeLadder).setBlockName("ladder").setBlockTextureName("ladder"));
		blockRegistry.addObject(66, "rail", (new BlockRail()).setHardness(0.7F).setStepSound(soundTypeMetal).setBlockName("rail").setBlockTextureName("rail_normal"));
		blockRegistry.addObject(67, "stone_stairs", (new BlockStairs(block, 0)).setBlockName("stairsStone"));
		blockRegistry.addObject(68, "wall_sign", (new BlockSign(TileEntitySign.class, false)).setHardness(1.0F).setStepSound(soundTypeWood).setBlockName("sign").disableStats());
		blockRegistry.addObject(69, "lever", (new BlockLever()).setHardness(0.5F).setStepSound(soundTypeWood).setBlockName("lever").setBlockTextureName("lever"));
		blockRegistry.addObject(70, "stone_pressure_plate", (new BlockPressurePlate("stone", Material.rock, BlockPressurePlate.Sensitivity.mobs)).setHardness(0.5F).setStepSound(soundTypePiston).setBlockName("pressurePlate"));
		blockRegistry.addObject(71, "iron_door", (new BlockDoor(Material.iron)).setHardness(5.0F).setStepSound(soundTypeMetal).setBlockName("doorIron").disableStats().setBlockTextureName("door_iron"));
		blockRegistry.addObject(72, "wooden_pressure_plate", (new BlockPressurePlate("planks_oak", Material.wood, BlockPressurePlate.Sensitivity.everything)).setHardness(0.5F).setStepSound(soundTypeWood).setBlockName("pressurePlate"));
		blockRegistry.addObject(73, "redstone_ore", (new BlockRedstoneOre(false)).setHardness(3.0F).setResistance(5.0F).setStepSound(soundTypePiston).setBlockName("oreRedstone").setCreativeTab(CreativeTabs.tabBlock).setBlockTextureName("redstone_ore"));
		blockRegistry.addObject(74, "lit_redstone_ore", (new BlockRedstoneOre(true)).setLightLevel(0.625F).setHardness(3.0F).setResistance(5.0F).setStepSound(soundTypePiston).setBlockName("oreRedstone").setBlockTextureName("redstone_ore"));
		blockRegistry.addObject(75, "unlit_redstone_torch", (new BlockRedstoneTorch(false)).setHardness(0.0F).setStepSound(soundTypeWood).setBlockName("notGate").setBlockTextureName("redstone_torch_off"));
		blockRegistry.addObject(76, "redstone_torch", (new BlockRedstoneTorch(true)).setHardness(0.0F).setLightLevel(0.5F).setStepSound(soundTypeWood).setBlockName("notGate").setCreativeTab(CreativeTabs.tabRedstone).setBlockTextureName("redstone_torch_on"));
		blockRegistry.addObject(77, "stone_button", (new BlockButtonStone()).setHardness(0.5F).setStepSound(soundTypePiston).setBlockName("button"));
		blockRegistry.addObject(78, "snow_layer", (new BlockSnow()).setHardness(0.1F).setStepSound(soundTypeSnow).setBlockName("snow").setLightOpacity(0).setBlockTextureName("snow"));
		blockRegistry.addObject(79, "ice", (new BlockIce()).setHardness(0.5F).setLightOpacity(3).setStepSound(soundTypeGlass).setBlockName("ice").setBlockTextureName("ice"));
		blockRegistry.addObject(80, "snow", (new BlockSnowBlock()).setHardness(0.2F).setStepSound(soundTypeSnow).setBlockName("snow").setBlockTextureName("snow"));
		blockRegistry.addObject(81, "cactus", (new BlockCactus()).setHardness(0.4F).setStepSound(soundTypeCloth).setBlockName("cactus").setBlockTextureName("cactus"));
		blockRegistry.addObject(82, "clay", (new BlockClay()).setHardness(0.6F).setStepSound(soundTypeGravel).setBlockName("clay").setBlockTextureName("clay"));
		blockRegistry.addObject(83, "reeds", (new BlockReed()).setHardness(0.0F).setStepSound(soundTypeGrass).setBlockName("reeds").disableStats().setBlockTextureName("reeds"));
		blockRegistry.addObject(84, "jukebox", (new BlockJukebox()).setHardness(2.0F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("jukebox").setBlockTextureName("jukebox"));
		blockRegistry.addObject(85, "fence", (new BlockFence("planks_oak", Material.wood)).setHardness(2.0F).setResistance(5.0F).setStepSound(soundTypeWood).setBlockName("fence"));
		Block block5 = (new BlockPumpkin(false)).setHardness(1.0F).setStepSound(soundTypeWood).setBlockName("pumpkin").setBlockTextureName("pumpkin");
		blockRegistry.addObject(86, "pumpkin", block5);
		blockRegistry.addObject(87, "netherrack", (new BlockNetherrack()).setHardness(0.4F).setStepSound(soundTypePiston).setBlockName("hellrock").setBlockTextureName("netherrack"));
		blockRegistry.addObject(88, "soul_sand", (new BlockSoulSand()).setHardness(0.5F).setStepSound(soundTypeSand).setBlockName("hellsand").setBlockTextureName("soul_sand"));
		blockRegistry.addObject(89, "glowstone", (new BlockGlowstone(Material.glass)).setHardness(0.3F).setStepSound(soundTypeGlass).setLightLevel(1.0F).setBlockName("lightgem").setBlockTextureName("glowstone"));
		blockRegistry.addObject(90, "portal", (new BlockPortal()).setHardness(-1.0F).setStepSound(soundTypeGlass).setLightLevel(0.75F).setBlockName("portal").setBlockTextureName("portal"));
		blockRegistry.addObject(91, "lit_pumpkin", (new BlockPumpkin(true)).setHardness(1.0F).setStepSound(soundTypeWood).setLightLevel(1.0F).setBlockName("litpumpkin").setBlockTextureName("pumpkin"));
		blockRegistry.addObject(92, "cake", (new BlockCake()).setHardness(0.5F).setStepSound(soundTypeCloth).setBlockName("cake").disableStats().setBlockTextureName("cake"));
		blockRegistry.addObject(93, "unpowered_repeater", (new BlockRedstoneRepeater(false)).setHardness(0.0F).setStepSound(soundTypeWood).setBlockName("diode").disableStats().setBlockTextureName("repeater_off"));
		blockRegistry.addObject(94, "powered_repeater", (new BlockRedstoneRepeater(true)).setHardness(0.0F).setLightLevel(0.625F).setStepSound(soundTypeWood).setBlockName("diode").disableStats().setBlockTextureName("repeater_on"));
		blockRegistry.addObject(95, "stained_glass", (new BlockStainedGlass(Material.glass)).setHardness(0.3F).setStepSound(soundTypeGlass).setBlockName("stainedGlass").setBlockTextureName("glass"));
		blockRegistry.addObject(96, "trapdoor", (new BlockTrapDoor(Material.wood)).setHardness(3.0F).setStepSound(soundTypeWood).setBlockName("trapdoor").disableStats().setBlockTextureName("trapdoor"));
		blockRegistry.addObject(97, "monster_egg", (new BlockSilverfish()).setHardness(0.75F).setBlockName("monsterStoneEgg"));
		Block block6 = (new BlockStoneBrick()).setHardness(1.5F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("stonebricksmooth").setBlockTextureName("stonebrick");
		blockRegistry.addObject(98, "stonebrick", block6);
		blockRegistry.addObject(99, "brown_mushroom_block", (new BlockHugeMushroom(Material.wood, 0)).setHardness(0.2F).setStepSound(soundTypeWood).setBlockName("mushroom").setBlockTextureName("mushroom_block"));
		blockRegistry.addObject(100, "red_mushroom_block", (new BlockHugeMushroom(Material.wood, 1)).setHardness(0.2F).setStepSound(soundTypeWood).setBlockName("mushroom").setBlockTextureName("mushroom_block"));
		blockRegistry.addObject(101, "iron_bars", (new BlockPane("iron_bars", "iron_bars", Material.iron, true)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundTypeMetal).setBlockName("fenceIron"));
		blockRegistry.addObject(102, "glass_pane", (new BlockPane("glass", "glass_pane_top", Material.glass, false)).setHardness(0.3F).setStepSound(soundTypeGlass).setBlockName("thinGlass"));
		Block block7 = (new BlockMelon()).setHardness(1.0F).setStepSound(soundTypeWood).setBlockName("melon").setBlockTextureName("melon");
		blockRegistry.addObject(103, "melon_block", block7);
		blockRegistry.addObject(104, "pumpkin_stem", (new BlockStem(block5)).setHardness(0.0F).setStepSound(soundTypeWood).setBlockName("pumpkinStem").setBlockTextureName("pumpkin_stem"));
		blockRegistry.addObject(105, "melon_stem", (new BlockStem(block7)).setHardness(0.0F).setStepSound(soundTypeWood).setBlockName("pumpkinStem").setBlockTextureName("melon_stem"));
		blockRegistry.addObject(106, "vine", (new BlockVine()).setHardness(0.2F).setStepSound(soundTypeGrass).setBlockName("vine").setBlockTextureName("vine"));
		blockRegistry.addObject(107, "fence_gate", (new BlockFenceGate()).setHardness(2.0F).setResistance(5.0F).setStepSound(soundTypeWood).setBlockName("fenceGate"));
		blockRegistry.addObject(108, "brick_stairs", (new BlockStairs(block3, 0)).setBlockName("stairsBrick"));
		blockRegistry.addObject(109, "stone_brick_stairs", (new BlockStairs(block6, 0)).setBlockName("stairsStoneBrickSmooth"));
		blockRegistry.addObject(110, "mycelium", (new BlockMycelium()).setHardness(0.6F).setStepSound(soundTypeGrass).setBlockName("mycel").setBlockTextureName("mycelium"));
		blockRegistry.addObject(111, "waterlily", (new BlockLilyPad()).setHardness(0.0F).setStepSound(soundTypeGrass).setBlockName("waterlily").setBlockTextureName("waterlily"));
		Block block8 = (new Block(Material.rock)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("netherBrick").setCreativeTab(CreativeTabs.tabBlock).setBlockTextureName("nether_brick");
		blockRegistry.addObject(112, "nether_brick", block8);
		blockRegistry.addObject(113, "nether_brick_fence", (new BlockFence("nether_brick", Material.rock)).setHardness(2.0F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("netherFence"));
		blockRegistry.addObject(114, "nether_brick_stairs", (new BlockStairs(block8, 0)).setBlockName("stairsNetherBrick"));
		blockRegistry.addObject(115, "nether_wart", (new BlockNetherWart()).setBlockName("netherStalk").setBlockTextureName("nether_wart"));
		blockRegistry.addObject(116, "enchanting_table", (new BlockEnchantmentTable()).setHardness(5.0F).setResistance(2000.0F).setBlockName("enchantmentTable").setBlockTextureName("enchanting_table"));
		blockRegistry.addObject(117, "brewing_stand", (new BlockBrewingStand()).setHardness(0.5F).setLightLevel(0.125F).setBlockName("brewingStand").setBlockTextureName("brewing_stand"));
		blockRegistry.addObject(118, "cauldron", (new BlockCauldron()).setHardness(2.0F).setBlockName("cauldron").setBlockTextureName("cauldron"));
		blockRegistry.addObject(119, "end_portal", (new BlockEndPortal(Material.portal)).setHardness(-1.0F).setResistance(6000000.0F));
		blockRegistry.addObject(120, "end_portal_frame", (new BlockEndPortalFrame()).setStepSound(soundTypeGlass).setLightLevel(0.125F).setHardness(-1.0F).setBlockName("endPortalFrame").setResistance(6000000.0F).setCreativeTab(CreativeTabs.tabDecorations).setBlockTextureName("endframe"));
		blockRegistry.addObject(121, "end_stone", (new Block(Material.rock)).setHardness(3.0F).setResistance(15.0F).setStepSound(soundTypePiston).setBlockName("whiteStone").setCreativeTab(CreativeTabs.tabBlock).setBlockTextureName("end_stone"));
		blockRegistry.addObject(122, "dragon_egg", (new BlockDragonEgg()).setHardness(3.0F).setResistance(15.0F).setStepSound(soundTypePiston).setLightLevel(0.125F).setBlockName("dragonEgg").setBlockTextureName("dragon_egg"));
		blockRegistry.addObject(123, "redstone_lamp", (new BlockRedstoneLight(false)).setHardness(0.3F).setStepSound(soundTypeGlass).setBlockName("redstoneLight").setCreativeTab(CreativeTabs.tabRedstone).setBlockTextureName("redstone_lamp_off"));
		blockRegistry.addObject(124, "lit_redstone_lamp", (new BlockRedstoneLight(true)).setHardness(0.3F).setStepSound(soundTypeGlass).setBlockName("redstoneLight").setBlockTextureName("redstone_lamp_on"));
		blockRegistry.addObject(125, "double_wooden_slab", (new BlockWoodSlab(true)).setHardness(2.0F).setResistance(5.0F).setStepSound(soundTypeWood).setBlockName("woodSlab"));
		blockRegistry.addObject(126, "wooden_slab", (new BlockWoodSlab(false)).setHardness(2.0F).setResistance(5.0F).setStepSound(soundTypeWood).setBlockName("woodSlab"));
		blockRegistry.addObject(127, "cocoa", (new BlockCocoa()).setHardness(0.2F).setResistance(5.0F).setStepSound(soundTypeWood).setBlockName("cocoa").setBlockTextureName("cocoa"));
		blockRegistry.addObject(128, "sandstone_stairs", (new BlockStairs(block2, 0)).setBlockName("stairsSandStone"));
		blockRegistry.addObject(129, "emerald_ore", (new BlockOre()).setHardness(3.0F).setResistance(5.0F).setStepSound(soundTypePiston).setBlockName("oreEmerald").setBlockTextureName("emerald_ore"));
		blockRegistry.addObject(130, "ender_chest", (new BlockEnderChest()).setHardness(22.5F).setResistance(1000.0F).setStepSound(soundTypePiston).setBlockName("enderChest").setLightLevel(0.5F));
		blockRegistry.addObject(131, "tripwire_hook", (new BlockTripWireHook()).setBlockName("tripWireSource").setBlockTextureName("trip_wire_source"));
		blockRegistry.addObject(132, "tripwire", (new BlockTripWire()).setBlockName("tripWire").setBlockTextureName("trip_wire"));
		blockRegistry.addObject(133, "emerald_block", (new BlockCompressed(MapColor.emeraldColor)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundTypeMetal).setBlockName("blockEmerald").setBlockTextureName("emerald_block"));
		blockRegistry.addObject(134, "spruce_stairs", (new BlockStairs(block1, 1)).setBlockName("stairsWoodSpruce"));
		blockRegistry.addObject(135, "birch_stairs", (new BlockStairs(block1, 2)).setBlockName("stairsWoodBirch"));
		blockRegistry.addObject(136, "jungle_stairs", (new BlockStairs(block1, 3)).setBlockName("stairsWoodJungle"));
		blockRegistry.addObject(137, "command_block", (new BlockCommandBlock()).setBlockUnbreakable().setResistance(6000000.0F).setBlockName("commandBlock").setBlockTextureName("command_block"));
		blockRegistry.addObject(138, "beacon", (new BlockBeacon()).setBlockName("beacon").setLightLevel(1.0F).setBlockTextureName("beacon"));
		blockRegistry.addObject(139, "cobblestone_wall", (new BlockWall(block)).setBlockName("cobbleWall"));
		blockRegistry.addObject(140, "flower_pot", (new BlockFlowerPot()).setHardness(0.0F).setStepSound(soundTypeStone).setBlockName("flowerPot").setBlockTextureName("flower_pot"));
		blockRegistry.addObject(141, "carrots", (new BlockCarrot()).setBlockName("carrots").setBlockTextureName("carrots"));
		blockRegistry.addObject(142, "potatoes", (new BlockPotato()).setBlockName("potatoes").setBlockTextureName("potatoes"));
		blockRegistry.addObject(143, "wooden_button", (new BlockButtonWood()).setHardness(0.5F).setStepSound(soundTypeWood).setBlockName("button"));
		blockRegistry.addObject(144, "skull", (new BlockSkull()).setHardness(1.0F).setStepSound(soundTypePiston).setBlockName("skull").setBlockTextureName("skull"));
		blockRegistry.addObject(145, "anvil", (new BlockAnvil()).setHardness(5.0F).setStepSound(soundTypeAnvil).setResistance(2000.0F).setBlockName("anvil"));
		blockRegistry.addObject(146, "trapped_chest", (new BlockChest(1)).setHardness(2.5F).setStepSound(soundTypeWood).setBlockName("chestTrap"));
		blockRegistry.addObject(147, "light_weighted_pressure_plate", (new BlockPressurePlateWeighted("gold_block", Material.iron, 15)).setHardness(0.5F).setStepSound(soundTypeWood).setBlockName("weightedPlate_light"));
		blockRegistry.addObject(148, "heavy_weighted_pressure_plate", (new BlockPressurePlateWeighted("iron_block", Material.iron, 150)).setHardness(0.5F).setStepSound(soundTypeWood).setBlockName("weightedPlate_heavy"));
		blockRegistry.addObject(149, "unpowered_comparator", (new BlockRedstoneComparator(false)).setHardness(0.0F).setStepSound(soundTypeWood).setBlockName("comparator").disableStats().setBlockTextureName("comparator_off"));
		blockRegistry.addObject(150, "powered_comparator", (new BlockRedstoneComparator(true)).setHardness(0.0F).setLightLevel(0.625F).setStepSound(soundTypeWood).setBlockName("comparator").disableStats().setBlockTextureName("comparator_on"));
		blockRegistry.addObject(151, "daylight_detector", (new BlockDaylightDetector()).setHardness(0.2F).setStepSound(soundTypeWood).setBlockName("daylightDetector").setBlockTextureName("daylight_detector"));
		blockRegistry.addObject(152, "redstone_block", (new BlockCompressedPowered(MapColor.tntColor)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundTypeMetal).setBlockName("blockRedstone").setBlockTextureName("redstone_block"));
		blockRegistry.addObject(153, "quartz_ore", (new BlockOre()).setHardness(3.0F).setResistance(5.0F).setStepSound(soundTypePiston).setBlockName("netherquartz").setBlockTextureName("quartz_ore"));
		blockRegistry.addObject(154, "hopper", (new BlockHopper()).setHardness(3.0F).setResistance(8.0F).setStepSound(soundTypeWood).setBlockName("hopper").setBlockTextureName("hopper"));
		Block block9 = (new BlockQuartz()).setStepSound(soundTypePiston).setHardness(0.8F).setBlockName("quartzBlock").setBlockTextureName("quartz_block");
		blockRegistry.addObject(155, "quartz_block", block9);
		blockRegistry.addObject(156, "quartz_stairs", (new BlockStairs(block9, 0)).setBlockName("stairsQuartz"));
		blockRegistry.addObject(157, "activator_rail", (new BlockRailPowered()).setHardness(0.7F).setStepSound(soundTypeMetal).setBlockName("activatorRail").setBlockTextureName("rail_activator"));
		blockRegistry.addObject(158, "dropper", (new BlockDropper()).setHardness(3.5F).setStepSound(soundTypePiston).setBlockName("dropper").setBlockTextureName("dropper"));
		blockRegistry.addObject(159, "stained_hardened_clay", (new BlockColored(Material.rock)).setHardness(1.25F).setResistance(7.0F).setStepSound(soundTypePiston).setBlockName("clayHardenedStained").setBlockTextureName("hardened_clay_stained"));
		blockRegistry.addObject(160, "stained_glass_pane", (new BlockStainedGlassPane()).setHardness(0.3F).setStepSound(soundTypeGlass).setBlockName("thinStainedGlass").setBlockTextureName("glass"));
		blockRegistry.addObject(161, "leaves2", (new BlockNewLeaf()).setBlockName("leaves").setBlockTextureName("leaves"));
		blockRegistry.addObject(162, "log2", (new BlockNewLog()).setBlockName("log").setBlockTextureName("log"));
		blockRegistry.addObject(163, "acacia_stairs", (new BlockStairs(block1, 4)).setBlockName("stairsWoodAcacia"));
		blockRegistry.addObject(164, "dark_oak_stairs", (new BlockStairs(block1, 5)).setBlockName("stairsWoodDarkOak"));
		blockRegistry.addObject(170, "hay_block", (new BlockHay()).setHardness(0.5F).setStepSound(soundTypeGrass).setBlockName("hayBlock").setCreativeTab(CreativeTabs.tabBlock).setBlockTextureName("hay_block"));
		blockRegistry.addObject(171, "carpet", (new BlockCarpet()).setHardness(0.1F).setStepSound(soundTypeCloth).setBlockName("woolCarpet").setLightOpacity(0));
		blockRegistry.addObject(172, "hardened_clay", (new BlockHardenedClay()).setHardness(1.25F).setResistance(7.0F).setStepSound(soundTypePiston).setBlockName("clayHardened").setBlockTextureName("hardened_clay"));
		blockRegistry.addObject(173, "coal_block", (new Block(Material.rock)).setHardness(5.0F).setResistance(10.0F).setStepSound(soundTypePiston).setBlockName("blockCoal").setCreativeTab(CreativeTabs.tabBlock).setBlockTextureName("coal_block"));
		blockRegistry.addObject(174, "packed_ice", (new BlockPackedIce()).setHardness(0.5F).setStepSound(soundTypeGlass).setBlockName("icePacked").setBlockTextureName("ice_packed"));
		blockRegistry.addObject(175, "double_plant", new BlockDoublePlant());
		Iterator iterator = blockRegistry.iterator();

		while (iterator.hasNext())
		{
			Block block10 = (Block)iterator.next();

			if (block10.blockMaterial == Material.air)
			{
				block10.useNeighborBrightness = false;
			}
			else
			{
				boolean flag = false;
				boolean flag1 = block10.getRenderType() == 10;
				boolean flag2 = block10 instanceof BlockSlab;
				boolean flag3 = block10 == block4;
				boolean flag4 = block10.canBlockGrass;
				boolean flag5 = block10.lightOpacity == 0;

				if (flag1 || flag2 || flag3 || flag4 || flag5)
				{
					flag = true;
				}

				block10.useNeighborBrightness = flag;
			}
		}
	}

	protected Block(Material p_i45394_1_)
	{
		this.stepSound = soundTypeStone;
		this.blockParticleGravity = 1.0F;
		this.slipperiness = 0.6F;
		this.blockMaterial = p_i45394_1_;
		this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
		this.opaque = this.isOpaqueCube();
		this.lightOpacity = this.isOpaqueCube() ? 255 : 0;
		this.canBlockGrass = !p_i45394_1_.getCanBlockGrass();
	}

	public Block setStepSound(Block.SoundType p_149672_1_)
	{
		this.stepSound = p_149672_1_;
		return this;
	}

	public Block setLightOpacity(int p_149713_1_)
	{
		this.lightOpacity = p_149713_1_;
		return this;
	}

	public Block setLightLevel(float p_149715_1_)
	{
		this.lightValue = (int)(15.0F * p_149715_1_);
		return this;
	}

	public Block setResistance(float p_149752_1_)
	{
		this.blockResistance = p_149752_1_ * 3.0F;
		return this;
	}

	@SideOnly(Side.CLIENT)
	public boolean isBlockNormalCube()
	{
		return this.blockMaterial.blocksMovement() && this.renderAsNormalBlock();
	}

	public boolean isNormalCube()
	{
		return this.blockMaterial.isOpaque() && this.renderAsNormalBlock() && !this.canProvidePower();
	}

	public boolean renderAsNormalBlock()
	{
		return true;
	}

	public boolean getBlocksMovement(IBlockAccess p_149655_1_, int p_149655_2_, int p_149655_3_, int p_149655_4_)
	{
		return !this.blockMaterial.blocksMovement();
	}

	public int getRenderType()
	{
		return 0;
	}

	public Block setHardness(float p_149711_1_)
	{
		this.blockHardness = p_149711_1_;

		if (this.blockResistance < p_149711_1_ * 5.0F)
		{
			this.blockResistance = p_149711_1_ * 5.0F;
		}

		return this;
	}

	public Block setBlockUnbreakable()
	{
		this.setHardness(-1.0F);
		return this;
	}

	public float getBlockHardness(World p_149712_1_, int p_149712_2_, int p_149712_3_, int p_149712_4_)
	{
		return this.blockHardness;
	}

	public Block setTickRandomly(boolean p_149675_1_)
	{
		this.needsRandomTick = p_149675_1_;
		return this;
	}

	public boolean getTickRandomly()
	{
		return this.needsRandomTick;
	}

	@Deprecated //Forge: New Metadata sensitive version.
	public boolean hasTileEntity()
	{
		return hasTileEntity(0);
	}

	public final void setBlockBounds(float p_149676_1_, float p_149676_2_, float p_149676_3_, float p_149676_4_, float p_149676_5_, float p_149676_6_)
	{
		this.minX = (double)p_149676_1_;
		this.minY = (double)p_149676_2_;
		this.minZ = (double)p_149676_3_;
		this.maxX = (double)p_149676_4_;
		this.maxY = (double)p_149676_5_;
		this.maxZ = (double)p_149676_6_;
	}

	@SideOnly(Side.CLIENT)
	public int getMixedBrightnessForBlock(IBlockAccess p_149677_1_, int p_149677_2_, int p_149677_3_, int p_149677_4_)
	{
		Block block = p_149677_1_.getBlock(p_149677_2_, p_149677_3_, p_149677_4_);
		int l = p_149677_1_.getLightBrightnessForSkyBlocks(p_149677_2_, p_149677_3_, p_149677_4_, block.getLightValue(p_149677_1_, p_149677_2_, p_149677_3_, p_149677_4_));

		if (l == 0 && block instanceof BlockSlab)
		{
			--p_149677_3_;
			block = p_149677_1_.getBlock(p_149677_2_, p_149677_3_, p_149677_4_);
			return p_149677_1_.getLightBrightnessForSkyBlocks(p_149677_2_, p_149677_3_, p_149677_4_, block.getLightValue(p_149677_1_, p_149677_2_, p_149677_3_, p_149677_4_));
		}
		else
		{
			return l;
		}
	}

	@SideOnly(Side.CLIENT)
	public boolean shouldSideBeRendered(IBlockAccess p_149646_1_, int p_149646_2_, int p_149646_3_, int p_149646_4_, int p_149646_5_)
	{
		return p_149646_5_ == 0 && this.minY > 0.0D ? true : (p_149646_5_ == 1 && this.maxY < 1.0D ? true : (p_149646_5_ == 2 && this.minZ > 0.0D ? true : (p_149646_5_ == 3 && this.maxZ < 1.0D ? true : (p_149646_5_ == 4 && this.minX > 0.0D ? true : (p_149646_5_ == 5 && this.maxX < 1.0D ? true : !p_149646_1_.getBlock(p_149646_2_, p_149646_3_, p_149646_4_).isOpaqueCube())))));
	}

	public boolean isBlockSolid(IBlockAccess p_149747_1_, int p_149747_2_, int p_149747_3_, int p_149747_4_, int p_149747_5_)
	{
		return p_149747_1_.getBlock(p_149747_2_, p_149747_3_, p_149747_4_).getMaterial().isSolid();
	}

	@SideOnly(Side.CLIENT)
	public IIcon getIcon(IBlockAccess p_149673_1_, int p_149673_2_, int p_149673_3_, int p_149673_4_, int p_149673_5_)
	{
		return this.getIcon(p_149673_5_, p_149673_1_.getBlockMetadata(p_149673_2_, p_149673_3_, p_149673_4_));
	}

	@SideOnly(Side.CLIENT)
	public IIcon getIcon(int p_149691_1_, int p_149691_2_)
	{
		return this.blockIcon;
	}

	public void addCollisionBoxesToList(World p_149743_1_, int p_149743_2_, int p_149743_3_, int p_149743_4_, AxisAlignedBB p_149743_5_, List p_149743_6_, Entity p_149743_7_)
	{
		AxisAlignedBB axisalignedbb1 = this.getCollisionBoundingBoxFromPool(p_149743_1_, p_149743_2_, p_149743_3_, p_149743_4_);

		if (axisalignedbb1 != null && p_149743_5_.intersectsWith(axisalignedbb1))
		{
			p_149743_6_.add(axisalignedbb1);
		}
	}

	public AxisAlignedBB getCollisionBoundingBoxFromPool(World p_149668_1_, int p_149668_2_, int p_149668_3_, int p_149668_4_)
	{
		return AxisAlignedBB.getAABBPool().getAABB((double)p_149668_2_ + this.minX, (double)p_149668_3_ + this.minY, (double)p_149668_4_ + this.minZ, (double)p_149668_2_ + this.maxX, (double)p_149668_3_ + this.maxY, (double)p_149668_4_ + this.maxZ);
	}

	@SideOnly(Side.CLIENT)
	public final IIcon getBlockTextureFromSide(int p_149733_1_)
	{
		return this.getIcon(p_149733_1_, 0);
	}

	@SideOnly(Side.CLIENT)
	public AxisAlignedBB getSelectedBoundingBoxFromPool(World p_149633_1_, int p_149633_2_, int p_149633_3_, int p_149633_4_)
	{
		return AxisAlignedBB.getAABBPool().getAABB((double)p_149633_2_ + this.minX, (double)p_149633_3_ + this.minY, (double)p_149633_4_ + this.minZ, (double)p_149633_2_ + this.maxX, (double)p_149633_3_ + this.maxY, (double)p_149633_4_ + this.maxZ);
	}

	public boolean isOpaqueCube()
	{
		return true;
	}

	public boolean canCollideCheck(int p_149678_1_, boolean p_149678_2_)
	{
		return this.isCollidable();
	}

	public boolean isCollidable()
	{
		return true;
	}

	public void updateTick(World p_149674_1_, int p_149674_2_, int p_149674_3_, int p_149674_4_, Random p_149674_5_) {}

	@SideOnly(Side.CLIENT)
	public void randomDisplayTick(World p_149734_1_, int p_149734_2_, int p_149734_3_, int p_149734_4_, Random p_149734_5_) {}

	public void onBlockDestroyedByPlayer(World p_149664_1_, int p_149664_2_, int p_149664_3_, int p_149664_4_, int p_149664_5_) {}

	public void onNeighborBlockChange(World p_149695_1_, int p_149695_2_, int p_149695_3_, int p_149695_4_, Block p_149695_5_) {}

	public int tickRate(World p_149738_1_)
	{
		return 10;
	}

	public void onBlockAdded(World p_149726_1_, int p_149726_2_, int p_149726_3_, int p_149726_4_) {}

	public void breakBlock(World p_149749_1_, int p_149749_2_, int p_149749_3_, int p_149749_4_, Block p_149749_5_, int p_149749_6_)
	{
		if (hasTileEntity(p_149749_6_) && !(this instanceof BlockContainer))
		{
			p_149749_1_.removeTileEntity(p_149749_2_, p_149749_3_, p_149749_4_);
		}
	}

	public int quantityDropped(Random p_149745_1_)
	{
		return 1;
	}

	public Item getItemDropped(int p_149650_1_, Random p_149650_2_, int p_149650_3_)
	{
		return Item.getItemFromBlock(this);
	}

	public float getPlayerRelativeBlockHardness(EntityPlayer p_149737_1_, World p_149737_2_, int p_149737_3_, int p_149737_4_, int p_149737_5_)
	{
		return ForgeHooks.blockStrength(this, p_149737_1_, p_149737_2_, p_149737_3_, p_149737_4_, p_149737_5_);
	}

	public final void dropBlockAsItem(World p_149697_1_, int p_149697_2_, int p_149697_3_, int p_149697_4_, int p_149697_5_, int p_149697_6_)
	{
		this.dropBlockAsItemWithChance(p_149697_1_, p_149697_2_, p_149697_3_, p_149697_4_, p_149697_5_, 1.0F, p_149697_6_);
	}

	public void dropBlockAsItemWithChance(World p_149690_1_, int p_149690_2_, int p_149690_3_, int p_149690_4_, int p_149690_5_, float p_149690_6_, int p_149690_7_)
	{
		if (!p_149690_1_.isRemote)
		{
			ArrayList<ItemStack> items = getDrops(p_149690_1_, p_149690_2_, p_149690_3_, p_149690_4_, p_149690_5_, p_149690_7_);
			p_149690_6_ = ForgeEventFactory.fireBlockHarvesting(items, p_149690_1_, this, p_149690_2_, p_149690_3_, p_149690_4_, p_149690_5_, p_149690_7_, p_149690_6_, false, harvesters.get());

			for (ItemStack item : items)
			{
				if (p_149690_1_.rand.nextFloat() <= p_149690_6_)
				{
					this.dropBlockAsItem(p_149690_1_, p_149690_2_, p_149690_3_, p_149690_4_, item);
				}
			}
		}
	}

	protected void dropBlockAsItem(World p_149642_1_, int p_149642_2_, int p_149642_3_, int p_149642_4_, ItemStack p_149642_5_)
	{
		if (!p_149642_1_.isRemote && p_149642_1_.getGameRules().getGameRuleBooleanValue("doTileDrops"))
		{
			if (captureDrops.get())
			{
				capturedDrops.get().add(p_149642_5_);
				return;
			}
			float f = 0.7F;
			double d0 = (double)(p_149642_1_.rand.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
			double d1 = (double)(p_149642_1_.rand.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
			double d2 = (double)(p_149642_1_.rand.nextFloat() * f) + (double)(1.0F - f) * 0.5D;
			EntityItem entityitem = new EntityItem(p_149642_1_, (double)p_149642_2_ + d0, (double)p_149642_3_ + d1, (double)p_149642_4_ + d2, p_149642_5_);
			entityitem.delayBeforeCanPickup = 10;
			p_149642_1_.spawnEntityInWorld(entityitem);
		}
	}

	public void dropXpOnBlockBreak(World p_149657_1_, int p_149657_2_, int p_149657_3_, int p_149657_4_, int p_149657_5_)
	{
		if (!p_149657_1_.isRemote)
		{
			while (p_149657_5_ > 0)
			{
				int i1 = EntityXPOrb.getXPSplit(p_149657_5_);
				p_149657_5_ -= i1;
				p_149657_1_.spawnEntityInWorld(new EntityXPOrb(p_149657_1_, (double)p_149657_2_ + 0.5D, (double)p_149657_3_ + 0.5D, (double)p_149657_4_ + 0.5D, i1));
			}
		}
	}

	public int damageDropped(int p_149692_1_)
	{
		return 0;
	}

	public float getExplosionResistance(Entity p_149638_1_)
	{
		return this.blockResistance / 5.0F;
	}

	public MovingObjectPosition collisionRayTrace(World p_149731_1_, int p_149731_2_, int p_149731_3_, int p_149731_4_, Vec3 p_149731_5_, Vec3 p_149731_6_)
	{
		this.setBlockBoundsBasedOnState(p_149731_1_, p_149731_2_, p_149731_3_, p_149731_4_);
		p_149731_5_ = p_149731_5_.addVector((double)(-p_149731_2_), (double)(-p_149731_3_), (double)(-p_149731_4_));
		p_149731_6_ = p_149731_6_.addVector((double)(-p_149731_2_), (double)(-p_149731_3_), (double)(-p_149731_4_));
		Vec3 vec32 = p_149731_5_.getIntermediateWithXValue(p_149731_6_, this.minX);
		Vec3 vec33 = p_149731_5_.getIntermediateWithXValue(p_149731_6_, this.maxX);
		Vec3 vec34 = p_149731_5_.getIntermediateWithYValue(p_149731_6_, this.minY);
		Vec3 vec35 = p_149731_5_.getIntermediateWithYValue(p_149731_6_, this.maxY);
		Vec3 vec36 = p_149731_5_.getIntermediateWithZValue(p_149731_6_, this.minZ);
		Vec3 vec37 = p_149731_5_.getIntermediateWithZValue(p_149731_6_, this.maxZ);

		if (!this.isVecInsideYZBounds(vec32))
		{
			vec32 = null;
		}

		if (!this.isVecInsideYZBounds(vec33))
		{
			vec33 = null;
		}

		if (!this.isVecInsideXZBounds(vec34))
		{
			vec34 = null;
		}

		if (!this.isVecInsideXZBounds(vec35))
		{
			vec35 = null;
		}

		if (!this.isVecInsideXYBounds(vec36))
		{
			vec36 = null;
		}

		if (!this.isVecInsideXYBounds(vec37))
		{
			vec37 = null;
		}

		Vec3 vec38 = null;

		if (vec32 != null && (vec38 == null || p_149731_5_.squareDistanceTo(vec32) < p_149731_5_.squareDistanceTo(vec38)))
		{
			vec38 = vec32;
		}

		if (vec33 != null && (vec38 == null || p_149731_5_.squareDistanceTo(vec33) < p_149731_5_.squareDistanceTo(vec38)))
		{
			vec38 = vec33;
		}

		if (vec34 != null && (vec38 == null || p_149731_5_.squareDistanceTo(vec34) < p_149731_5_.squareDistanceTo(vec38)))
		{
			vec38 = vec34;
		}

		if (vec35 != null && (vec38 == null || p_149731_5_.squareDistanceTo(vec35) < p_149731_5_.squareDistanceTo(vec38)))
		{
			vec38 = vec35;
		}

		if (vec36 != null && (vec38 == null || p_149731_5_.squareDistanceTo(vec36) < p_149731_5_.squareDistanceTo(vec38)))
		{
			vec38 = vec36;
		}

		if (vec37 != null && (vec38 == null || p_149731_5_.squareDistanceTo(vec37) < p_149731_5_.squareDistanceTo(vec38)))
		{
			vec38 = vec37;
		}

		if (vec38 == null)
		{
			return null;
		}
		else
		{
			byte b0 = -1;

			if (vec38 == vec32)
			{
				b0 = 4;
			}

			if (vec38 == vec33)
			{
				b0 = 5;
			}

			if (vec38 == vec34)
			{
				b0 = 0;
			}

			if (vec38 == vec35)
			{
				b0 = 1;
			}

			if (vec38 == vec36)
			{
				b0 = 2;
			}

			if (vec38 == vec37)
			{
				b0 = 3;
			}

			return new MovingObjectPosition(p_149731_2_, p_149731_3_, p_149731_4_, b0, vec38.addVector((double)p_149731_2_, (double)p_149731_3_, (double)p_149731_4_));
		}
	}

	private boolean isVecInsideYZBounds(Vec3 p_149654_1_)
	{
		return p_149654_1_ == null ? false : p_149654_1_.yCoord >= this.minY && p_149654_1_.yCoord <= this.maxY && p_149654_1_.zCoord >= this.minZ && p_149654_1_.zCoord <= this.maxZ;
	}

	private boolean isVecInsideXZBounds(Vec3 p_149687_1_)
	{
		return p_149687_1_ == null ? false : p_149687_1_.xCoord >= this.minX && p_149687_1_.xCoord <= this.maxX && p_149687_1_.zCoord >= this.minZ && p_149687_1_.zCoord <= this.maxZ;
	}

	private boolean isVecInsideXYBounds(Vec3 p_149661_1_)
	{
		return p_149661_1_ == null ? false : p_149661_1_.xCoord >= this.minX && p_149661_1_.xCoord <= this.maxX && p_149661_1_.yCoord >= this.minY && p_149661_1_.yCoord <= this.maxY;
	}

	public void onBlockDestroyedByExplosion(World p_149723_1_, int p_149723_2_, int p_149723_3_, int p_149723_4_, Explosion p_149723_5_) {}

	public boolean canReplace(World p_149705_1_, int p_149705_2_, int p_149705_3_, int p_149705_4_, int p_149705_5_, ItemStack p_149705_6_)
	{
		return this.canPlaceBlockOnSide(p_149705_1_, p_149705_2_, p_149705_3_, p_149705_4_, p_149705_5_);
	}

	@SideOnly(Side.CLIENT)
	public int getRenderBlockPass()
	{
		return 0;
	}

	public boolean canPlaceBlockOnSide(World p_149707_1_, int p_149707_2_, int p_149707_3_, int p_149707_4_, int p_149707_5_)
	{
		return this.canPlaceBlockAt(p_149707_1_, p_149707_2_, p_149707_3_, p_149707_4_);
	}

	public boolean canPlaceBlockAt(World p_149742_1_, int p_149742_2_, int p_149742_3_, int p_149742_4_)
	{
		return p_149742_1_.getBlock(p_149742_2_, p_149742_3_, p_149742_4_).isReplaceable(p_149742_1_, p_149742_2_, p_149742_3_, p_149742_4_);
	}

	public boolean onBlockActivated(World p_149727_1_, int p_149727_2_, int p_149727_3_, int p_149727_4_, EntityPlayer p_149727_5_, int p_149727_6_, float p_149727_7_, float p_149727_8_, float p_149727_9_)
	{
		return false;
	}

	public void onEntityWalking(World p_149724_1_, int p_149724_2_, int p_149724_3_, int p_149724_4_, Entity p_149724_5_) {}

	public int onBlockPlaced(World p_149660_1_, int p_149660_2_, int p_149660_3_, int p_149660_4_, int p_149660_5_, float p_149660_6_, float p_149660_7_, float p_149660_8_, int p_149660_9_)
	{
		return p_149660_9_;
	}

	public void onBlockClicked(World p_149699_1_, int p_149699_2_, int p_149699_3_, int p_149699_4_, EntityPlayer p_149699_5_) {}

	public void velocityToAddToEntity(World p_149640_1_, int p_149640_2_, int p_149640_3_, int p_149640_4_, Entity p_149640_5_, Vec3 p_149640_6_) {}

	public void setBlockBoundsBasedOnState(IBlockAccess p_149719_1_, int p_149719_2_, int p_149719_3_, int p_149719_4_) {}

	public final double getBlockBoundsMinX()
	{
		return this.minX;
	}

	public final double getBlockBoundsMaxX()
	{
		return this.maxX;
	}

	public final double getBlockBoundsMinY()
	{
		return this.minY;
	}

	public final double getBlockBoundsMaxY()
	{
		return this.maxY;
	}

	public final double getBlockBoundsMinZ()
	{
		return this.minZ;
	}

	public final double getBlockBoundsMaxZ()
	{
		return this.maxZ;
	}

	@SideOnly(Side.CLIENT)
	public int getBlockColor()
	{
		return 16777215;
	}

	@SideOnly(Side.CLIENT)
	public int getRenderColor(int p_149741_1_)
	{
		return 16777215;
	}

	@SideOnly(Side.CLIENT)
	public int colorMultiplier(IBlockAccess p_149720_1_, int p_149720_2_, int p_149720_3_, int p_149720_4_)
	{
		return 16777215;
	}

	public int isProvidingWeakPower(IBlockAccess p_149709_1_, int p_149709_2_, int p_149709_3_, int p_149709_4_, int p_149709_5_)
	{
		return 0;
	}

	public boolean canProvidePower()
	{
		return false;
	}

	public void onEntityCollidedWithBlock(World p_149670_1_, int p_149670_2_, int p_149670_3_, int p_149670_4_, Entity p_149670_5_) {}

	public int isProvidingStrongPower(IBlockAccess p_149748_1_, int p_149748_2_, int p_149748_3_, int p_149748_4_, int p_149748_5_)
	{
		return 0;
	}

	public void setBlockBoundsForItemRender() {}

	public void harvestBlock(World p_149636_1_, EntityPlayer p_149636_2_, int p_149636_3_, int p_149636_4_, int p_149636_5_, int p_149636_6_)
	{
		p_149636_2_.addStat(StatList.mineBlockStatArray[getIdFromBlock(this)], 1);
		p_149636_2_.addExhaustion(0.025F);

		if (this.canSilkHarvest(p_149636_1_, p_149636_2_, p_149636_3_, p_149636_4_, p_149636_5_, p_149636_6_) && EnchantmentHelper.getSilkTouchModifier(p_149636_2_))
		{
			ArrayList<ItemStack> items = new ArrayList<ItemStack>();
			ItemStack itemstack = this.createStackedBlock(p_149636_6_);

			if (itemstack != null)
			{
				items.add(itemstack);
			}

			ForgeEventFactory.fireBlockHarvesting(items, p_149636_1_, this, p_149636_3_, p_149636_4_, p_149636_5_, p_149636_6_, 0, 1.0f, true, p_149636_2_);
			for (ItemStack is : items)
			{
				this.dropBlockAsItem(p_149636_1_, p_149636_3_, p_149636_4_, p_149636_5_, is);
			}
		}
		else
		{
			harvesters.set(p_149636_2_);
			int i1 = EnchantmentHelper.getFortuneModifier(p_149636_2_);
			this.dropBlockAsItem(p_149636_1_, p_149636_3_, p_149636_4_, p_149636_5_, p_149636_6_, i1);
			harvesters.set(null);
		}
	}

	protected boolean canSilkHarvest()
	{
		Integer meta = silk_check_meta.get();
		return this.renderAsNormalBlock() && !this.hasTileEntity(meta == null ? 0 : meta);
	}

	protected ItemStack createStackedBlock(int p_149644_1_)
	{
		int j = 0;
		Item item = Item.getItemFromBlock(this);

		if (item != null && item.getHasSubtypes())
		{
			j = p_149644_1_;
		}

		return new ItemStack(item, 1, j);
	}

	public int quantityDroppedWithBonus(int p_149679_1_, Random p_149679_2_)
	{
		return this.quantityDropped(p_149679_2_);
	}

	public boolean canBlockStay(World p_149718_1_, int p_149718_2_, int p_149718_3_, int p_149718_4_)
	{
		return true;
	}

	public void onBlockPlacedBy(World p_149689_1_, int p_149689_2_, int p_149689_3_, int p_149689_4_, EntityLivingBase p_149689_5_, ItemStack p_149689_6_) {}

	public void onPostBlockPlaced(World p_149714_1_, int p_149714_2_, int p_149714_3_, int p_149714_4_, int p_149714_5_) {}

	public Block setBlockName(String p_149663_1_)
	{
		this.unlocalizedName = p_149663_1_;
		return this;
	}

	public String getLocalizedName()
	{
		return StatCollector.translateToLocal(this.getUnlocalizedName() + ".name");
	}

	public String getUnlocalizedName()
	{
		return "tile." + this.unlocalizedName;
	}

	public boolean onBlockEventReceived(World p_149696_1_, int p_149696_2_, int p_149696_3_, int p_149696_4_, int p_149696_5_, int p_149696_6_)
	{
		return false;
	}

	public boolean getEnableStats()
	{
		return this.enableStats;
	}

	protected Block disableStats()
	{
		this.enableStats = false;
		return this;
	}

	public int getMobilityFlag()
	{
		return this.blockMaterial.getMaterialMobility();
	}

	@SideOnly(Side.CLIENT)
	public float getAmbientOcclusionLightValue()
	{
		return this.isBlockNormalCube() ? 0.2F : 1.0F;
	}

	public void onFallenUpon(World p_149746_1_, int p_149746_2_, int p_149746_3_, int p_149746_4_, Entity p_149746_5_, float p_149746_6_) {}

	@SideOnly(Side.CLIENT)
	public Item getItem(World p_149694_1_, int p_149694_2_, int p_149694_3_, int p_149694_4_)
	{
		return Item.getItemFromBlock(this);
	}

	public int getDamageValue(World p_149643_1_, int p_149643_2_, int p_149643_3_, int p_149643_4_)
	{
		return this.damageDropped(p_149643_1_.getBlockMetadata(p_149643_2_, p_149643_3_, p_149643_4_));
	}

	@SideOnly(Side.CLIENT)
	public void getSubBlocks(Item p_149666_1_, CreativeTabs p_149666_2_, List p_149666_3_)
	{
		p_149666_3_.add(new ItemStack(p_149666_1_, 1, 0));
	}

	public Block setCreativeTab(CreativeTabs p_149647_1_)
	{
		this.displayOnCreativeTab = p_149647_1_;
		return this;
	}

	public void onBlockHarvested(World p_149681_1_, int p_149681_2_, int p_149681_3_, int p_149681_4_, int p_149681_5_, EntityPlayer p_149681_6_) {}

	@SideOnly(Side.CLIENT)
	public CreativeTabs getCreativeTabToDisplayOn()
	{
		return this.displayOnCreativeTab;
	}

	public void onBlockPreDestroy(World p_149725_1_, int p_149725_2_, int p_149725_3_, int p_149725_4_, int p_149725_5_) {}

	public void fillWithRain(World p_149639_1_, int p_149639_2_, int p_149639_3_, int p_149639_4_) {}

	@SideOnly(Side.CLIENT)
	public boolean isFlowerPot()
	{
		return false;
	}

	public boolean func_149698_L()
	{
		return true;
	}

	public boolean canDropFromExplosion(Explosion p_149659_1_)
	{
		return true;
	}

	public boolean isAssociatedBlock(Block p_149667_1_)
	{
		return this == p_149667_1_;
	}

	public static boolean isEqualTo(Block p_149680_0_, Block p_149680_1_)
	{
		return p_149680_0_ != null && p_149680_1_ != null ? (p_149680_0_ == p_149680_1_ ? true : p_149680_0_.isAssociatedBlock(p_149680_1_)) : false;
	}

	public boolean hasComparatorInputOverride()
	{
		return false;
	}

	public int getComparatorInputOverride(World p_149736_1_, int p_149736_2_, int p_149736_3_, int p_149736_4_, int p_149736_5_)
	{
		return 0;
	}

	public Block setBlockTextureName(String p_149658_1_)
	{
		this.textureName = p_149658_1_;
		return this;
	}

	@SideOnly(Side.CLIENT)
	protected String getTextureName()
	{
		return this.textureName == null ? "MISSING_ICON_BLOCK_" + getIdFromBlock(this) + "_" + this.unlocalizedName : this.textureName;
	}

	@SideOnly(Side.CLIENT)
	public IIcon func_149735_b(int p_149735_1_, int p_149735_2_)
	{
		return this.getIcon(p_149735_1_, p_149735_2_);
	}

	@SideOnly(Side.CLIENT)
	public void registerBlockIcons(IIconRegister p_149651_1_)
	{
		this.blockIcon = p_149651_1_.registerIcon(this.getTextureName());
	}

	@SideOnly(Side.CLIENT)
	public String getItemIconName()
	{
		return null;
	}

	/* ======================================== FORGE START =====================================*/
	//For ForgeInternal use Only!
	protected ThreadLocal<EntityPlayer> harvesters = new ThreadLocal();
	private ThreadLocal<Integer> silk_check_meta = new ThreadLocal(); 
	/**
	 * Get a light value for the block at the specified coordinates, normal ranges are between 0 and 15
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y position
	 * @param z Z position
	 * @return The light value
	 */
	public int getLightValue(IBlockAccess world, int x, int y, int z)
	{
		Block block = world.getBlock(x, y, z);
		if (block != this)
		{
			return block.getLightValue(world, x, y, z);
		}
		return getLightValue();
	}

	/**
	 * Checks if a player or entity can use this block to 'climb' like a ladder.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y position
	 * @param z Z position
	 * @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, int x, int y, int z, 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 x X Position
	 * @param y Y position
	 * @param z Z position
	 * @return True if the block is a full cube
	 */
	public boolean isNormalCube(IBlockAccess world, int x, int y, int z)
	{
		return getMaterial().isOpaque() && renderAsNormalBlock() && !canProvidePower();
	}

	/**
	 * Checks if the block is a solid face on the given side, used by placement logic.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y position
	 * @param z Z position
	 * @param side The side to check
	 * @return True if the block is solid on the specified side.
	 */
	public boolean isSideSolid(IBlockAccess world, int x, int y, int z, ForgeDirection side)
	{
		int meta = world.getBlockMetadata(x, y, z);

		if (this instanceof BlockSlab)
		{
			return (((meta & 8) == 8 && (side == UP)) || func_149730_j());
		}
		else if (this instanceof BlockFarmland)
		{
			return (side != DOWN && side != UP);
		}
		else if (this instanceof BlockStairs)
		{
			boolean flipped = ((meta & 4) != 0);
			return ((meta & 3) + side.ordinal() == 5) || (side == UP && flipped);
		}
		else if (this instanceof BlockSnow)
		{
			return (meta & 7) == 7;
		}
		else if (this instanceof BlockHopper && side == UP)
		{
			return true;
		}
		else if (this instanceof BlockCompressedPowered)
		{
			return true;
		}
		return isNormalCube(world, x, y, z);
	}

	/**
	 * Determines if a new block can be replace the space occupied by this one,
	 * Used in the player's placement code to make the block act like water, and lava.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y position
	 * @param z Z position
	 * @return True if the block is replaceable by another block
	 */
	public boolean isReplaceable(IBlockAccess world, int x, int y, int z)
	{
		return blockMaterial.isReplaceable();
	}

	/**
	 * Determines if this block should set fire and deal fire damage
	 * to entities coming into contact with it.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y position
	 * @param z Z position
	 * @return True if the block should deal damage
	 */
	public boolean isBurning(IBlockAccess world, int x, int y, int z)
	{
		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 x X Position
	 * @param y Y position
	 * @param z Z position
	 * @return True if the block considered air
	 */
	public boolean isAir(IBlockAccess world, int x, int y, int z)
	{
		return getMaterial() == Material.air;
	}

	/**
	 * 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(EntityPlayer player, int meta)
	{
		return ForgeHooks.canHarvestBlock(this, player, meta);
	}

	/**
	 * 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 x X Position
	 * @param y Y position
	 * @param z Z position
	 * @return True if the block is actually destroyed.
	 */
	public boolean removedByPlayer(World world, EntityPlayer player, int x, int y, int z)
	{
		return world.setBlockToAir(x, y, z);
	}

	/**
	 * 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 x The blocks X position
	 * @param y The blocks Y position
	 * @param z The blocks Z position
	 * @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, int x, int y, int z, ForgeDirection face)
	{
		return Blocks.fire.getFlammability(this);
	}

	/**
	 * Called when fire is updating, checks if a block face can catch fire.
	 *
	 *
	 * @param world The current world
	 * @param x The blocks X position
	 * @param y The blocks Y position
	 * @param z The blocks Z position
	 * @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, int x, int y, int z, ForgeDirection face)
	{
		return getFlammability(world, x, y, z, 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 x The blocks X position
	 * @param y The blocks Y position
	 * @param z The blocks Z position
	 * @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, int x, int y, int z, ForgeDirection face)
	{
		return Blocks.fire.getEncouragement(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 x The blocks X position
	 * @param y The blocks Y position
	 * @param z The blocks Z position
	 * @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, int x, int y, int z, ForgeDirection side)
	{
		if (this == Blocks.netherrack && side == UP)
		{
			return true;
		}
		if ((world.provider instanceof WorldProviderEnd) && this == Blocks.bedrock && side == 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 metadata Metadata of the current block
	 * @return True if block has a tile entity, false otherwise
	 */
	public boolean hasTileEntity(int metadata)
	{
		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, int metadata)
	{
		if (isTileProvider)
		{
			return ((ITileEntityProvider)this).createNewTileEntity(world, metadata);
		}
		return null;
	}

	/**
	 * Metadata and fortune sensitive version, this replaces the old (int meta, Random rand)
	 * version in 1.1.
	 *
	 * @param meta Blocks Metadata
	 * @param fortune Current item fortune level
	 * @param random Random number generator
	 * @return The number of items to drop
	 */
	public int quantityDropped(int meta, int fortune, Random random)
	{
		return quantityDroppedWithBonus(fortune, random);
	}

	/**
	 * This returns a complete list of items dropped from this block.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @param metadata Current metadata
	 * @param fortune Breakers fortune level
	 * @return A ArrayList containing all items this block drops
	 */
	public ArrayList<ItemStack> getDrops(World world, int x, int y, int z, int metadata, int fortune)
	{
		ArrayList<ItemStack> ret = new ArrayList<ItemStack>();

		int count = quantityDropped(metadata, fortune, world.rand);
		for(int i = 0; i < count; i++)
		{
			Item item = getItemDropped(metadata, world.rand, fortune);
			if (item != null)
			{
				ret.add(new ItemStack(item, 1, damageDropped(metadata)));
			}
		}
		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 player The player doing the harvesting
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @param metadata The metadata
	 * @return True if the block can be directly harvested using silk touch
	 */
	public boolean canSilkHarvest(World world, EntityPlayer player, int x, int y, int z, int metadata)
	{
		silk_check_meta.set(metadata);;
		boolean ret = this.canSilkHarvest();
		silk_check_meta.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 type The Mob Category Type
	 * @param world The current world
	 * @param x The X Position
	 * @param y The Y Position
	 * @param z The Z Position
	 * @return True to allow a mob of the specified category to spawn, false to prevent it.
	 */
	public boolean canCreatureSpawn(EnumCreatureType type, IBlockAccess world, int x, int y, int z)
	{
		int meta = world.getBlockMetadata(x, y, z);
		if (this instanceof BlockSlab)
		{
			return (((meta & 8) == 8) || func_149730_j());
		}
		else if (this instanceof BlockStairs)
		{
			return ((meta & 4) != 0);
		}
		return isSideSolid(world, x, y, z, 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 x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @param player The player or camera entity, null in some cases.
	 * @return True to treat this as a bed
	 */
	public boolean isBed(IBlockAccess world, int x, int y, int z, EntityLivingBase player)
	{
		return this == Blocks.bed;
	}

	/**
	 * Returns the position that the player is moved to upon
	 * waking up, or respawning at the bed.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @param player The player or camera entity, null in some cases.
	 * @return The spawn position
	 */
	public ChunkCoordinates getBedSpawnPosition(IBlockAccess world, int x, int y, int z, EntityPlayer player)
	{
		if (world instanceof World)
			return BlockBed.func_149977_a((World)world, x, y, z, 0);
		return null;
	}

	/**
	 * Called when a user either starts or stops sleeping in the bed.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @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, int x, int y, int z, EntityPlayer player, boolean occupied)
	{
		if (world instanceof World)
			BlockBed.func_149979_a((World)world,  x, y, z, occupied);
	}

	/**
	 * Returns the direction of the block. Same values that
	 * are returned by BlockDirectional
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @return Bed direction
	 */
	public int getBedDirection(IBlockAccess world, int x, int y, int z)
	{
		return BlockBed.getDirection(world.getBlockMetadata(x,  y, z));
	}

	/**
	 * Determines if the current block is the foot half of the bed.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @return True if the current block is the foot side of a bed.
	 */
	public boolean isBedFoot(IBlockAccess world, int x, int y, int z)
	{
		return BlockBed.isBlockHeadOfBed(world.getBlockMetadata(x,  y, z));
	}

	/**
	 * Called when a leaf should start its decay process.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 */
	public void beginLeavesDecay(World world, int x, int y, int z){}

	/**
	 * Determines if this block can prevent leaves connected to it from decaying.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @return true if the presence this block can prevent leaves from decaying.
	 */
	public boolean canSustainLeaves(IBlockAccess world, int x, int y, int z)
	{
		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 x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @return true if this block is considered leaves.
	 */
	public boolean isLeaves(IBlockAccess world, int x, int y, int z)
	{
		return getMaterial() == Material.leaves;
	}

	/**
	 * Used during tree growth to determine if newly generated leaves can replace this block.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @return true if this block can be replaced by growing leaves.
	 */
	public boolean canBeReplacedByLeaves(IBlockAccess world, int x, int y, int z)
	{
		return !func_149730_j();
	}

	/**
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @return  true if the block is wood (logs)
	 */
	public boolean isWood(IBlockAccess world, int x, int y, int z)
	{
		 return false;
	}

	/**
	 * Determines if the current block is replaceable by Ore veins during world generation.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @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, int x, int y, int z, Block target)
	{
		return this == target;
	}

	/**
	 * Location sensitive version of getExplosionRestance
	 *
	 * @param par1Entity The entity that caused the explosion
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @param explosionX Explosion source X Position
	 * @param explosionY Explosion source X Position
	 * @param explosionZ Explosion source X Position
	 * @return The amount of the explosion absorbed.
	 */
	public float getExplosionResistance(Entity par1Entity, World world, int x, int y, int z, double explosionX, double explosionY, double explosionZ)
	{
		return getExplosionResistance(par1Entity);
	}

	/**
	 * Called when the block is destroyed by an explosion.
	 * Useful for allowing the block to take into account tile entities,
	 * metadata, etc. when exploded, before it is removed.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @param Explosion The explosion instance affecting the block
	 */
	public void onBlockExploded(World world, int x, int y, int z, Explosion explosion)
	{
		world.setBlockToAir(x, y, z);
		onBlockDestroyedByExplosion(world, x, y, z, 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.
	 *
	 * Side:
	 *  -1: UP
	 *   0: NORTH
	 *   1: EAST
	 *   2: SOUTH
	 *   3: WEST
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @param side The side that is trying to make the connection
	 * @return True to make the connection
	 */
	public boolean canConnectRedstone(IBlockAccess world, int x, int y, int z, int side)
	{
		return canProvidePower() && side != -1;
	}

	/**
	 * 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 x X Position
	 * @param y Y Position
	 * @param z Z Position
	 * @return True to allow the torch to be placed
	 */
	public boolean canPlaceTorchOnTop(World world, int x, int y, int z)
	{
		if (isSideSolid(world, x, y, z, UP))
		{
			return true;
		}
		else
		{
			return this == Blocks.fence || this == Blocks.nether_brick_fence || this == Blocks.glass || this == Blocks.cobblestone_wall;
		}
	}

	/**
	 * 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 == getRenderBlockPass();
	}

	/**
	 * 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, int x, int y, int z)
	{
		Item item = getItem(world, x, y, z);

		if (item == null)
		{
			return null;
		}

		Block block = item instanceof ItemBlock && !isFlowerPot() ? Block.getBlockFromItem(item) : this;
		return new ItemStack(item, 1, block.getDamageValue(world, x, y, z));
	}

	/**
	 * 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, int x, int y, int z)
	{
		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, 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 x X position to spawn the particle
	 * @param y Y position to spawn the particle
	 * @param z Z position to spawn the particle
	 * @param meta The metadata for the block before it was destroyed.
	 * @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, int x, int y, int z, int meta, 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 x X Position
	 * @param y Y Position
	 * @param z Z position
	 * @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, int x, int y, int z, ForgeDirection direction, IPlantable plantable)
	{
		Block plant = plantable.getPlant(world, x, y + 1, z);
		EnumPlantType plantType = plantable.getPlantType(world, x, y + 1, z);

		if (plant == Blocks.cactus && this == Blocks.cactus)
		{
			return true;
		}

		if (plant == Blocks.reeds && this == Blocks.reeds)
		{
			return true;
		}

		if (plantable instanceof BlockBush && ((BlockBush)plantable).canPlaceBlockOn(this))
		{
			return true;
		}

		switch (plantType)
		{
			case Desert: return this == Blocks.sand;
			case Nether: return this == Blocks.soul_sand;
			case Crop:   return this == Blocks.farmland;
			case Cave:   return isSideSolid(world, x, y, z, UP);
			case Plains: return this == Blocks.grass || this == Blocks.dirt || this == Blocks.farmland;
			case Water:  return world.getBlock(x, y, z).getMaterial() == Material.water && world.getBlockMetadata(x, y, z) == 0;
			case Beach:
				boolean isBeach = this == Blocks.grass || this == Blocks.dirt || this == Blocks.sand;
				boolean hasWater = (world.getBlock(x - 1, y, z    ).getMaterial() == Material.water ||
									world.getBlock(x + 1, y, z    ).getMaterial() == Material.water ||
									world.getBlock(x,     y, z - 1).getMaterial() == Material.water ||
									world.getBlock(x,     y, z + 1).getMaterial() == Material.water);
				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 x Soil X
	 * @param y Soil Y
	 * @param z Soil Z
	 * @param sourceX Plant growth location X
	 * @param sourceY Plant growth location Y
	 * @param sourceZ Plant growth location Z
	 */
	public void onPlantGrow(World world, int x, int y, int z, int sourceX, int sourceY, int sourceZ)
	{
		if (this == Blocks.grass || this == Blocks.farmland)
		{
			world.setBlock(x, y, z, Blocks.dirt, 0, 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 x X Position
	 * @param y Y Position
	 * @param z Z position
	 * @return True if the soil should be considered fertile.
	 */
	public boolean isFertile(World world, int x, int y, int z)
	{
		if (this == Blocks.farmland)
		{
			return world.getBlockMetadata(x, y, z) > 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 x X Position
	 * @param y Y Position
	 * @param z Z position
	 * @return The amount of light to block, 0 for air, 255 for fully opaque.
	 */
	public int getLightOpacity(IBlockAccess world, int x, int y, int z)
	{
		return getLightOpacity();
	}

	/**
	 * Determines if this block is can be destroyed by the specified entities normal behavior.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z position
	 * @return True to allow the ender dragon to destroy this block
	 */
	public boolean canEntityDestroy(IBlockAccess world, int x, int y, int z, Entity entity)
	{
		if (entity instanceof EntityWither)
		{
			return this != Blocks.bedrock && this != Blocks.end_portal && this != Blocks.end_portal_frame && this != Blocks.command_block;
		}
		else if (entity instanceof EntityDragon)
		{
			return this != Blocks.obsidian && this != Blocks.end_stone && this != Blocks.bedrock; 
		}

		return true;
	}

	/**
	 * Determines if this block can be used as the base of a beacon.
	 *
	 * @param world The current world
	 * @param x X Position
	 * @param y Y Position
	 * @param z Z position
	 * @param beaconX Beacons X Position
	 * @param beaconY Beacons Y Position
	 * @param beaconZ Beacons Z Position
	 * @return True, to support the beacon, and make it active with this block.
	 */
	public boolean isBeaconBase(IBlockAccess worldObj, int x, int y, int z, int beaconX, int beaconY, int beaconZ)
	{
		return this == Blocks.emerald_block || this == Blocks.gold_block || this == Blocks.diamond_block || this == Blocks.iron_block;
	}

	/**
	 * 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 worldObj The world
	 * @param x X position
	 * @param y Y position
	 * @param z Z position
	 * @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 worldObj, int x, int y, int z, ForgeDirection axis)
	{
		return RotationHelper.rotateVanillaBlock(this, worldObj, x, y, z, axis);
	}

	/**
	 * 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 worldObj The world
	 * @param x X position
	 * @param y Y position
	 * @param z Z position
	 * @return An array of valid axes to rotate around, or null for none or unknown
	 */
	public ForgeDirection[] getValidRotations(World worldObj, int x, int y, int z)
	{
		return RotationHelper.getValidVanillaBlockRotations(this);
	}

	/**
	 * Determines the amount of enchanting power this block can provide to an enchanting table.
	 * @param world The World
	 * @param x X position
	 * @param y Y position
	 * @param z Z position
	 * @return The amount of enchanting power this block produces.
	 */
	public float getEnchantPowerBonus(World world, int x, int y, int z)
	{
		return this == Blocks.bookshelf ? 1 : 0;
	}

	/**
	 * Common way to recolour a block with an external tool
	 * @param world The world
	 * @param x X
	 * @param y Y
	 * @param z Z
	 * @param side The side hit with the colouring tool
	 * @param colour The colour to change to
	 * @return If the recolouring was successful
	 */
	public boolean recolourBlock(World world, int x, int y, int z, ForgeDirection side, int colour)
	{
		if (this == Blocks.wool)
		{
			int meta = world.getBlockMetadata(x, y, z);
			if (meta != colour)
			{
				world.setBlockMetadataWithNotify(x, y, z, colour, 3);
				return true;
			}
		}
		return false;
	}

	/**
	 * Gathers how much experience this block drops when broken.
	 * 
	 * @param world The world
	 * @param metadata
	 * @param fortune
	 * @return Amount of XP from breaking this block.
	 */
	public int getExpDrop(IBlockAccess world, int metadata, 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 x The x position of this block instance
	 * @param y The y position of this block instance
	 * @param z The z position of this block instance
	 * @param tileX The x position of the tile that changed
	 * @param tileY The y position of the tile that changed
	 * @param tileZ The z position of the tile that changed
	 */
	public void onNeighborChange(IBlockAccess world, int x, int y, int z, int tileX, int tileY, int tileZ)
	{
	}

	/**
	 * 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 x The x position of this block instance
	 * @param y The y position of this block instance
	 * @param z The z position of this block instance
	 * @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, int x, int y, int z, int side)
	{
		return isNormalCube();
	}

	/**
	 * 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 x X Position
	 * @param y Y position
	 * @param z Z position
	 * @param side The side to check
	 * @return true To be notified of changes
	 */
	public boolean getWeakChanges(IBlockAccess world, int x, int y, int z)
	{
		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)
	{
		for (int m = 0; m < 16; m++)
		{
			setHarvestLevel(toolClass, level, m);
		}
	}

	/**
	 * 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 metadata The specific metadata to set
	 */
	public void setHarvestLevel(String toolClass, int level, int metadata)
	{
		this.harvestTool[metadata] = toolClass;
		this.harvestLevel[metadata] = level;
	}

	/**
	 * Queries the class of tool required to harvest this block, if null is returned 
	 * we assume that anything can harvest this block.
	 * 
	 * @param metadata
	 * @return
	 */
	public String getHarvestTool(int metadata)
	{
		return harvestTool[metadata];
	}

	/**
	 * Queries the harvest level of this item stack for the specifred 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(int metadata)
	{
		return harvestLevel[metadata];
	}

	/**
	 * Checks if the specified tool type is efficient on this block, 
	 * meaning that it digs at full speed.
	 * 
	 * @param type
	 * @param metadata
	 * @return
	 */
	public boolean isToolEffective(String type, int metadata)
	{
		if ("pickaxe".equals(type) && (this == Blocks.redstone_ore || this == Blocks.lit_redstone_ore || this == Blocks.obsidian))
			return false;
		if (harvestTool[metadata] == null) return false;
		return harvestTool[metadata].equals(type);
	}


	// For Inernal use only to capture droped items inside getDrops
	protected ThreadLocal<Boolean> captureDrops = new ThreadLocal<Boolean>()
	{
		@Override protected Boolean initialValue() { return false; }
	};
	protected ThreadLocal<List<ItemStack>> capturedDrops = new ThreadLocal<List<ItemStack>>()
	{
		@Override protected List<ItemStack> initialValue() { return new 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 class SoundType
		{
			public final String soundName;
			public final float volume;
			public final float frequency;
			private static final String __OBFID = "CL_00000203";

			public SoundType(String p_i45393_1_, float p_i45393_2_, float p_i45393_3_)
			{
				this.soundName = p_i45393_1_;
				this.volume = p_i45393_2_;
				this.frequency = p_i45393_3_;
			}

			public float getVolume()
			{
				return this.volume;
			}

			public float getPitch()
			{
				return this.frequency;
			}

			public String getBreakSound()
			{
				return "dig." + this.soundName;
			}

			public String getStepResourcePath()
			{
				return "step." + this.soundName;
			}

			public String func_150496_b()
			{
				return this.getBreakSound();
			}
		}
}